From f3f895e9c3d7c1b3ab810e9aec384808fb918190 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Wed, 23 Nov 2022 14:30:03 -0500 Subject: [PATCH] V1.0.2 --- README.md | 11 ++- build.gradle | 5 + .../arsc/chunk/xml/AndroidManifestBlock.java | 90 ++++++++++++------ .../lib/arsc/chunk/xml/BaseXmlChunk.java | 7 ++ .../lib/arsc/chunk/xml/ResXmlElement.java | 93 +++++++++++++++++++ .../arsc/chunk/xml/ResXmlStartElement.java | 12 +++ 6 files changed, 187 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index ce5d24d..b2c43c0 100755 --- a/README.md +++ b/README.md @@ -28,15 +28,24 @@ AndroidManifestBlock manifestBlock=new AndroidManifestBlock(); manifestBlock.readBytes(file); + + List permissionNames = manifestBlock.getUsesPermissions(); + for(String perm:permissionNames){ + System.out.println(perm); + } //edit AndroidManifest as desired, for example to change the package: manifestBlock.setPackageName("com.new.package.name"); + + // add some permission + + manifestBlock.addUsesPermission("android.permission.WRITE_EXTERNAL_STORAGE"); //refresh to recalculate offsets manifestBlock.refresh(); - //save the edited table + //save the edited xml File outFile=new File("AndroidManifest_out.xml"); manifestBlock.writeBytes(outFile); } diff --git a/build.gradle b/build.gradle index 83d0cfa..1bac861 100755 --- a/build.gradle +++ b/build.gradle @@ -31,3 +31,8 @@ processResources { } } +task fatJar(type: Jar) { + from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } + with jar +} + diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/AndroidManifestBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/AndroidManifestBlock.java index 04e1c24..cefa6ea 100644 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/AndroidManifestBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/AndroidManifestBlock.java @@ -11,7 +11,7 @@ public class AndroidManifestBlock extends ResXmlBlock{ public AndroidManifestBlock(){ super(); } - public List getPermissions(){ + public List getUsesPermissions(){ List results=new ArrayList<>(); ResXmlElement manifestElement=getManifestElement(); if(manifestElement==null){ @@ -19,7 +19,7 @@ public class AndroidManifestBlock extends ResXmlBlock{ } List permissionList = manifestElement.searchElementsByTagName(TAG_uses_permission); for(ResXmlElement permission:permissionList){ - ResXmlAttribute nameAttr = permission.searchAttributeByName(ATTR_android_name); + ResXmlAttribute nameAttr = permission.searchAttributeById(ID_name); if(nameAttr==null){ continue; } @@ -30,35 +30,49 @@ public class AndroidManifestBlock extends ResXmlBlock{ } return results; } + public ResXmlElement addUsesPermission(String permissionName){ + ResXmlElement manifestElement=getManifestElement(); + if(manifestElement==null){ + return null; + } + manifestElement.getStartElement().getOrCreateString(TAG_uses_permission); + ResXmlElement result=manifestElement.createChildElement(TAG_uses_permission); + ResXmlAttribute attr = result.createAndroidAttribute(NAME_name, ID_name); + ResXmlString strPermission = result.getStartElement().getOrCreateString(permissionName); + attr.setRawValue(strPermission.getIndex()); + attr.setValueType(ValueType.STRING); + attr.setValueStringReference(strPermission.getIndex()); + return result; + } public String getPackageName(){ - return getManifestAttributeString(ATTR_PACKAGE); + return getManifestAttributeString(NAME_PACKAGE); } public boolean setPackageName(String packageName){ - return setManifestAttributeString(ATTR_PACKAGE, packageName); + return setManifestAttributeString(NAME_PACKAGE, packageName); } public Integer getCompileSdkVersion(){ - return getManifestAttributeInt(ATTR_compileSdkVersion); + return getManifestAttributeInt(NAME_compileSdkVersion); } public boolean setCompileSdkVersion(int val){ - return setManifestAttributeInt(ATTR_compileSdkVersion, val); + return setManifestAttributeInt(NAME_compileSdkVersion, val); } public String getCompileSdkVersionCodename(){ - return getManifestAttributeString(ATTR_compileSdkVersionCodename); + return getManifestAttributeString(NAME_compileSdkVersionCodename); } public boolean setCompileSdkVersionCodename(String val){ - return setManifestAttributeString(ATTR_compileSdkVersionCodename, val); + return setManifestAttributeString(NAME_compileSdkVersionCodename, val); } public Integer getVersionCode(){ - return getManifestAttributeInt(ATTR_versionCode); + return getManifestAttributeInt(NAME_versionCode); } public boolean setVersionCode(int val){ - return setManifestAttributeInt(ATTR_versionCode, val); + return setManifestAttributeInt(NAME_versionCode, val); } public String getVersionName(){ - return getManifestAttributeString(ATTR_versionName); + return getManifestAttributeString(NAME_versionName); } public boolean setVersionName(String packageName){ - return setManifestAttributeString(ATTR_versionName, packageName); + return setManifestAttributeString(NAME_versionName, packageName); } private String getManifestAttributeString(String name){ ResXmlElement manifestElement=getManifestElement(); @@ -115,12 +129,19 @@ public class AndroidManifestBlock extends ResXmlBlock{ } return attribute.getRawValue(); } + private ResXmlElement getApplicationElement(){ + ResXmlElement manifestElement=getManifestElement(); + if(manifestElement==null){ + return null; + } + return manifestElement.getElementByTagName(TAG_application); + } private ResXmlElement getManifestElement(){ ResXmlElement manifestElement=getResXmlElement(); if(manifestElement==null){ return null; } - if(!TAG_MANIFEST.equals(manifestElement.getTag())){ + if(!TAG_manifest.equals(manifestElement.getTag())){ return null; } return manifestElement; @@ -130,13 +151,13 @@ public class AndroidManifestBlock extends ResXmlBlock{ StringBuilder builder=new StringBuilder(); builder.append(getClass().getSimpleName()); builder.append("{"); - builder.append(ATTR_PACKAGE).append("=").append(getPackageName()); - builder.append(", ").append(ATTR_versionCode).append("=").append(getVersionCode()); - builder.append(", ").append(ATTR_versionName).append("=").append(getVersionName()); - builder.append(", ").append(ATTR_compileSdkVersion).append("=").append(getCompileSdkVersion()); - builder.append(", ").append(ATTR_compileSdkVersionCodename).append("=").append(getCompileSdkVersionCodename()); + builder.append(NAME_PACKAGE).append("=").append(getPackageName()); + builder.append(", ").append(NAME_versionCode).append("=").append(getVersionCode()); + builder.append(", ").append(NAME_versionName).append("=").append(getVersionName()); + builder.append(", ").append(NAME_compileSdkVersion).append("=").append(getCompileSdkVersion()); + builder.append(", ").append(NAME_compileSdkVersionCodename).append("=").append(getCompileSdkVersionCodename()); - List allPermissions=getPermissions(); + List allPermissions= getUsesPermissions(); builder.append(", PERMISSIONS["); boolean appendOnce=false; for(String permissions:allPermissions){ @@ -150,18 +171,27 @@ public class AndroidManifestBlock extends ResXmlBlock{ builder.append("}"); return builder.toString(); } - private static final String TAG_MANIFEST="manifest"; - private static final String TAG_uses_permission="uses-permission"; + public static final String TAG_manifest ="manifest"; + public static final String TAG_uses_permission="uses-permission"; + public static final String TAG_application ="application"; - private static final String ATTR_compileSdkVersion="compileSdkVersion"; - private static final String ATTR_compileSdkVersionCodename="compileSdkVersionCodename"; - private static final String ATTR_installLocation="installLocation"; - private static final String ATTR_PACKAGE="package"; - private static final String ATTR_platformBuildVersionCode="platformBuildVersionCode"; - private static final String ATTR_platformBuildVersionName="platformBuildVersionName"; - private static final String ATTR_versionCode="versionCode"; - private static final String ATTR_versionName="versionName"; + public static final String NAME_compileSdkVersion ="compileSdkVersion"; + public static final String NAME_compileSdkVersionCodename ="compileSdkVersionCodename"; + public static final String NAME_installLocation="installLocation"; + public static final String NAME_PACKAGE ="package"; + public static final String NAME_platformBuildVersionCode="platformBuildVersionCode"; + public static final String NAME_platformBuildVersionName ="platformBuildVersionName"; + public static final String NAME_versionCode ="versionCode"; + public static final String NAME_versionName ="versionName"; + public static final String NAME_name ="name"; + + public static final int ID_name = 0x01010003; + public static final int ID_compileSdkVersion = 0x01010572; + public static final int ID_compileSdkVersionCodename = 0x01010573; + public static final int ID_authorities = 0x01010018; + public static final int ID_host = 0x01010028; + public static final int ID_configChanges = 0x0101001f; + public static final int ID_screenOrientation = 0x0101001e; - private static final String ATTR_android_name="name"; public static final String FILE_NAME="AndroidManifest.xml"; } diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/BaseXmlChunk.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/BaseXmlChunk.java index e9283a5..0f71db2 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/BaseXmlChunk.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/BaseXmlChunk.java @@ -105,6 +105,13 @@ public class BaseXmlChunk extends BaseChunk { } return null; } + ResXmlString getOrCreateString(String str){ + ResXmlStringPool stringPool=getStringPool(); + if(stringPool==null){ + return null; + } + return stringPool.getOrCreate(str); + } public String getName(){ return getString(getStringReference()); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java index fdef7e5..4f369da 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java @@ -39,6 +39,54 @@ public class ResXmlElement extends FixedBlockContainer { addChild(4, mEndElementContainer); addChild(5, mEndNamespaceList); } + @Override + protected void refreshChildes(){ + List elementList = listElements(); + for (ResXmlElement element:elementList){ + element.refresh(); + } + super.refreshChildes(); + } + public ResXmlElement createChildElement(String tag){ + ResXmlElement resXmlElement=new ResXmlElement(); + ResXmlStartElement startElement=new ResXmlStartElement(); + resXmlElement.setStartElement(startElement); + ResXmlEndElement endElement=new ResXmlEndElement(); + resXmlElement.setEndElement(endElement); + addElement(resXmlElement); + resXmlElement.setTag(tag); + int lineNo=getStartElement().getLineNumber()+1; + startElement.setLineNumber(lineNo); + endElement.setLineNumber(lineNo); + endElement.setStringReference(startElement.getStringReference()); + return resXmlElement; + } + public ResXmlAttribute createAndroidAttribute(String name, int resourceId){ + ResXmlAttribute attribute=createAttribute(name, resourceId); + ResXmlStartNamespace ns = getOrCreateNamespace(NS_ANDROID_URI, NS_ANDROID_PREFIX); + attribute.setNamespaceReference(ns.getUriReference()); + return attribute; + } + public ResXmlAttribute createAttribute(String name, int resourceId){ + ResXmlAttribute attribute=new ResXmlAttribute(); + addAttribute(attribute); + attribute.setName(name, resourceId); + return attribute; + } + public void addAttribute(ResXmlAttribute attribute){ + getStartElement().getResXmlAttributeArray().add(attribute); + } + public ResXmlElement getElementByTagName(String name){ + if(name==null){ + return null; + } + for(ResXmlElement child:listElements()){ + if(name.equals(child.getTag())||name.equals(child.getTagName())){ + return child; + } + } + return null; + } public List searchElementsByTagName(String name){ List results=new ArrayList<>(); if(name==null){ @@ -58,6 +106,13 @@ public class ResXmlElement extends FixedBlockContainer { } return null; } + public ResXmlAttribute searchAttributeById(int resourceId){ + ResXmlStartElement startElement=getStartElement(); + if(startElement!=null){ + return startElement.searchAttributeById(resourceId); + } + return null; + } public void setTag(String tag){ ResXmlStringPool pool = getStringPool(); if(pool==null){ @@ -174,6 +229,41 @@ public class ResXmlElement extends FixedBlockContainer { } return null; } + public ResXmlStartNamespace getOrCreateNamespace(String uri, String prefix){ + ResXmlStartNamespace namespace=getStartNamespaceByUri(uri); + if(namespace!=null){ + return namespace; + } + ResXmlStartElement startElement = getStartElement(); + ResXmlString uriString = startElement.getOrCreateString(uri); + ResXmlString prefixString = startElement.getOrCreateString(prefix); + namespace=new ResXmlStartNamespace(); + addStartNamespace(namespace); + namespace.setUriReference(uriString.getIndex()); + namespace.setPrefixReference(prefixString.getIndex()); + ResXmlEndNamespace endNamespace=new ResXmlEndNamespace(); + addEndNamespace(endNamespace); + endNamespace.setUriReference(uriString.getIndex()); + endNamespace.setPrefixReference(prefixString.getIndex()); + namespace.setResXmlEndNamespace(endNamespace); + endNamespace.setResXmlStartNamespace(namespace); + return namespace; + } + public ResXmlStartNamespace getStartNamespaceByUri(String uri){ + if(uri==null){ + return null; + } + for(ResXmlStartNamespace ns:mStartNamespaceList.getChildes()){ + if(uri.equals(ns.getUri())){ + return ns; + } + } + ResXmlElement xmlElement=getParentResXmlElement(); + if(xmlElement!=null){ + return xmlElement.getStartNamespaceByUri(uri); + } + return null; + } public List getStartNamespaceList(){ @@ -430,4 +520,7 @@ public class ResXmlElement extends FixedBlockContainer { resXmlElement.setTag(tag); return resXmlElement; } + + public static final String NS_ANDROID_URI = "http://schemas.android.com/apk/res/android"; + public static final String NS_ANDROID_PREFIX = "android"; } diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlStartElement.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlStartElement.java index db34249..1fc1cd3 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlStartElement.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlStartElement.java @@ -1,5 +1,6 @@ package com.reandroid.lib.arsc.chunk.xml; +import com.reandroid.lib.arsc.base.BlockContainer; import com.reandroid.lib.arsc.chunk.ChunkType; import com.reandroid.lib.arsc.array.ResXmlAttributeArray; import com.reandroid.lib.arsc.item.IntegerItem; @@ -43,6 +44,17 @@ public class ResXmlStartElement extends BaseXmlChunk { } return null; } + public ResXmlAttribute searchAttributeById(int resourceId){ + if(resourceId==0){ + return null; + } + for(ResXmlAttribute attribute:listResXmlAttributes()){ + if(resourceId==attribute.getNameResourceID()){ + return attribute; + } + } + return null; + } public String getTagName(){ String prefix=getPrefix(); String name=getName();