mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-14 12:27:07 +02:00
implement new AndroidFrameworks
This commit is contained in:
parent
26b7ead67f
commit
d3ef84c59f
@ -38,7 +38,6 @@ javadoc {
|
|||||||
|
|
||||||
jar {
|
jar {
|
||||||
exclude('com/reandroid/test/**')
|
exclude('com/reandroid/test/**')
|
||||||
exclude('com/reandroid/facebook/**')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task fatJar(type: Jar) {
|
task fatJar(type: Jar) {
|
||||||
|
@ -33,6 +33,7 @@ import com.reandroid.arsc.value.ResConfig;
|
|||||||
import com.reandroid.common.Frameworks;
|
import com.reandroid.common.Frameworks;
|
||||||
import com.reandroid.common.TableEntryStore;
|
import com.reandroid.common.TableEntryStore;
|
||||||
import com.reandroid.xml.XMLDocument;
|
import com.reandroid.xml.XMLDocument;
|
||||||
|
import com.reandroid.xml.XMLElement;
|
||||||
import com.reandroid.xml.XMLException;
|
import com.reandroid.xml.XMLException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -57,27 +58,31 @@ public class ApkModule implements ApkFile {
|
|||||||
this.mUncompressedFiles=new UncompressedFiles();
|
this.mUncompressedFiles=new UncompressedFiles();
|
||||||
this.mUncompressedFiles.addPath(apkArchive);
|
this.mUncompressedFiles.addPath(apkArchive);
|
||||||
}
|
}
|
||||||
public void initializeAndroidFramework() throws IOException {
|
public FrameworkApk initializeAndroidFramework() throws IOException {
|
||||||
if(!hasTableBlock()){
|
if(!hasTableBlock()){
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
initializeAndroidFramework(getTableBlock());
|
Integer version = getAndroidFrameworkVersion();
|
||||||
|
return initializeAndroidFramework(getTableBlock(false), version);
|
||||||
}
|
}
|
||||||
private void initializeAndroidFramework(TableBlock tableBlock) throws IOException {
|
private FrameworkApk initializeAndroidFramework(TableBlock tableBlock, Integer version) throws IOException {
|
||||||
if(tableBlock == null || isAndroid(tableBlock)){
|
if(tableBlock == null || isAndroid(tableBlock)){
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
List<TableBlock> frameWorkList = tableBlock.getFrameWorks();
|
List<TableBlock> frameWorkList = tableBlock.getFrameWorks();
|
||||||
for(TableBlock frameWork:frameWorkList){
|
for(TableBlock frameWork:frameWorkList){
|
||||||
if(isAndroid(frameWork)){
|
if(isAndroid(frameWork)){
|
||||||
return;
|
ApkFile apkFile = frameWork.getApkFile();
|
||||||
|
if(apkFile instanceof FrameworkApk){
|
||||||
|
return (FrameworkApk) apkFile;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logMessage("Initializing android framework ...");
|
logMessage("Initializing android framework ...");
|
||||||
Integer version = getAndroidFrameworkVersion();
|
|
||||||
FrameworkApk frameworkApk;
|
FrameworkApk frameworkApk;
|
||||||
if(version==null){
|
if(version==null){
|
||||||
logMessage("Can not read framework version from manifest, loading latest");
|
logMessage("Can not read framework version, loading latest");
|
||||||
frameworkApk = AndroidFrameworks.getLatest();
|
frameworkApk = AndroidFrameworks.getLatest();
|
||||||
}else {
|
}else {
|
||||||
logMessage("Loading android framework for version: " + version);
|
logMessage("Loading android framework for version: " + version);
|
||||||
@ -86,6 +91,7 @@ public class ApkModule implements ApkFile {
|
|||||||
FrameworkTable frameworkTable = frameworkApk.getTableBlock();
|
FrameworkTable frameworkTable = frameworkApk.getTableBlock();
|
||||||
tableBlock.addFramework(frameworkTable);
|
tableBlock.addFramework(frameworkTable);
|
||||||
logMessage("Initialized framework: "+frameworkApk.getName());
|
logMessage("Initialized framework: "+frameworkApk.getName());
|
||||||
|
return frameworkApk;
|
||||||
}
|
}
|
||||||
private boolean isAndroid(TableBlock tableBlock){
|
private boolean isAndroid(TableBlock tableBlock){
|
||||||
if(tableBlock instanceof FrameworkTable){
|
if(tableBlock instanceof FrameworkTable){
|
||||||
@ -94,6 +100,60 @@ public class ApkModule implements ApkFile {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FrameworkApk initializeAndroidFramework(XMLDocument xmlDocument) throws IOException {
|
||||||
|
TableBlock tableBlock = getTableBlock(false);
|
||||||
|
if(isAndroidCoreApp(xmlDocument)){
|
||||||
|
logMessage("Looks framework itself, skip loading frameworks");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Integer version = readCompileVersionCode(xmlDocument);
|
||||||
|
return initializeAndroidFramework(tableBlock, version);
|
||||||
|
}
|
||||||
|
private boolean isAndroidCoreApp(XMLDocument manifestDocument){
|
||||||
|
XMLElement root = manifestDocument.getDocumentElement();
|
||||||
|
if(root == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!"android".equals(root.getAttributeValue("package"))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String coreApp = root.getAttributeValue("coreApp");
|
||||||
|
return "true".equals(coreApp);
|
||||||
|
}
|
||||||
|
private Integer readCompileVersionCode(XMLDocument manifestDocument) {
|
||||||
|
XMLElement root = manifestDocument.getDocumentElement();
|
||||||
|
String versionString = readVersionCodeString(root);
|
||||||
|
if(versionString==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
return Integer.parseInt(versionString);
|
||||||
|
}catch (NumberFormatException exception){
|
||||||
|
logMessage("NumberFormatException on manifest version reading: '"
|
||||||
|
+versionString+"': "+exception.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String readVersionCodeString(XMLElement manifestRoot){
|
||||||
|
String versionString = manifestRoot.getAttributeValue("android:compileSdkVersion");
|
||||||
|
if(versionString!=null){
|
||||||
|
return versionString;
|
||||||
|
}
|
||||||
|
versionString = manifestRoot.getAttributeValue("platformBuildVersionCode");
|
||||||
|
if(versionString!=null){
|
||||||
|
return versionString;
|
||||||
|
}
|
||||||
|
for(XMLElement element:manifestRoot.listChildElements()){
|
||||||
|
if(AndroidManifestBlock.TAG_uses_sdk.equals(element.getTagName())){
|
||||||
|
versionString = element.getAttributeValue("android:targetSdkVersion");
|
||||||
|
if(versionString!=null){
|
||||||
|
return versionString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public Integer getAndroidFrameworkVersion(){
|
public Integer getAndroidFrameworkVersion(){
|
||||||
if(!hasAndroidManifestBlock()){
|
if(!hasAndroidManifestBlock()){
|
||||||
return null;
|
return null;
|
||||||
@ -148,16 +208,7 @@ public class ApkModule implements ApkFile {
|
|||||||
ResXmlDocument resXmlDocument = loadResXmlDocument(path);
|
ResXmlDocument resXmlDocument = loadResXmlDocument(path);
|
||||||
AndroidManifestBlock manifestBlock = getAndroidManifestBlock();
|
AndroidManifestBlock manifestBlock = getAndroidManifestBlock();
|
||||||
int pkgId = manifestBlock.guessCurrentPackageId();
|
int pkgId = manifestBlock.guessCurrentPackageId();
|
||||||
return resXmlDocument.decodeToXml(getTableEntryStore(), pkgId);
|
return resXmlDocument.decodeToXml(getTableBlock(), pkgId);
|
||||||
}
|
|
||||||
private TableEntryStore getTableEntryStore() throws IOException {
|
|
||||||
if(mEntryStore!=null){
|
|
||||||
return mEntryStore;
|
|
||||||
}
|
|
||||||
mEntryStore = new TableEntryStore();
|
|
||||||
mEntryStore.add(getTableBlock());
|
|
||||||
mEntryStore.add(Frameworks.getAndroid());
|
|
||||||
return mEntryStore;
|
|
||||||
}
|
}
|
||||||
public List<DexFileInputSource> listDexFiles(){
|
public List<DexFileInputSource> listDexFiles(){
|
||||||
List<DexFileInputSource> results=new ArrayList<>();
|
List<DexFileInputSource> results=new ArrayList<>();
|
||||||
@ -436,16 +487,16 @@ public class ApkModule implements ApkFile {
|
|||||||
}
|
}
|
||||||
return mManifestBlock;
|
return mManifestBlock;
|
||||||
}
|
}
|
||||||
@Override
|
public TableBlock getTableBlock(boolean initFramework) {
|
||||||
public TableBlock getTableBlock() {
|
|
||||||
if(mTableBlock==null){
|
if(mTableBlock==null){
|
||||||
if(!hasTableBlock()){
|
if(!hasTableBlock()){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mTableBlock = loadTableBlock();
|
mTableBlock = loadTableBlock();
|
||||||
if(loadDefaultFramework){
|
if(initFramework && loadDefaultFramework){
|
||||||
initializeAndroidFramework(mTableBlock);
|
Integer version = getAndroidFrameworkVersion();
|
||||||
|
initializeAndroidFramework(mTableBlock, version);
|
||||||
}
|
}
|
||||||
} catch (IOException exception) {
|
} catch (IOException exception) {
|
||||||
throw new IllegalArgumentException(exception);
|
throw new IllegalArgumentException(exception);
|
||||||
@ -454,6 +505,10 @@ public class ApkModule implements ApkFile {
|
|||||||
return mTableBlock;
|
return mTableBlock;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
public TableBlock getTableBlock() {
|
||||||
|
return getTableBlock(true);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
public ResXmlDocument loadResXmlDocument(String path) throws IOException{
|
public ResXmlDocument loadResXmlDocument(String path) throws IOException{
|
||||||
InputSource inputSource = getApkArchive().getInputSource(path);
|
InputSource inputSource = getApkArchive().getInputSource(path);
|
||||||
if(inputSource==null){
|
if(inputSource==null){
|
||||||
|
@ -27,8 +27,6 @@ import com.reandroid.arsc.container.SpecTypePair;
|
|||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.*;
|
import com.reandroid.arsc.value.*;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.common.Frameworks;
|
|
||||||
import com.reandroid.common.TableEntryStore;
|
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
import com.reandroid.xml.XMLAttribute;
|
import com.reandroid.xml.XMLAttribute;
|
||||||
import com.reandroid.xml.XMLDocument;
|
import com.reandroid.xml.XMLDocument;
|
||||||
@ -55,27 +53,25 @@ import java.util.*;
|
|||||||
this.decodedEntries.clear();
|
this.decodedEntries.clear();
|
||||||
logMessage("Decoding ...");
|
logMessage("Decoding ...");
|
||||||
decodeUncompressedFiles(outDir);
|
decodeUncompressedFiles(outDir);
|
||||||
TableEntryStore entryStore=new TableEntryStore();
|
apkModule.initializeAndroidFramework();
|
||||||
entryStore.add(Frameworks.getAndroid());
|
|
||||||
TableBlock tableBlock=apkModule.getTableBlock();
|
TableBlock tableBlock=apkModule.getTableBlock();
|
||||||
entryStore.add(tableBlock);
|
|
||||||
|
|
||||||
decodePackageInfo(outDir, tableBlock);
|
decodePackageInfo(outDir, tableBlock);
|
||||||
|
|
||||||
xmlBagDecoder=new XMLBagDecoder(entryStore);
|
xmlBagDecoder=new XMLBagDecoder(tableBlock);
|
||||||
|
|
||||||
decodePublicXml(tableBlock, outDir);
|
decodePublicXml(tableBlock, outDir);
|
||||||
|
|
||||||
decodeAndroidManifest(entryStore, outDir);
|
decodeAndroidManifest(tableBlock, outDir);
|
||||||
|
|
||||||
addDecodedPath(TableBlock.FILE_NAME);
|
addDecodedPath(TableBlock.FILE_NAME);
|
||||||
|
|
||||||
logMessage("Decoding resource files ...");
|
logMessage("Decoding resource files ...");
|
||||||
List<ResFile> resFileList=apkModule.listResFiles();
|
List<ResFile> resFileList=apkModule.listResFiles();
|
||||||
for(ResFile resFile:resFileList){
|
for(ResFile resFile:resFileList){
|
||||||
decodeResFile(entryStore, outDir, resFile);
|
decodeResFile(tableBlock, outDir, resFile);
|
||||||
}
|
}
|
||||||
decodeValues(entryStore, outDir, tableBlock);
|
decodeValues(tableBlock, outDir, tableBlock);
|
||||||
|
|
||||||
extractRootFiles(outDir);
|
extractRootFiles(outDir);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.apk.APKLogger;
|
import com.reandroid.apk.APKLogger;
|
||||||
|
import com.reandroid.apk.FrameworkApk;
|
||||||
import com.reandroid.apk.ResourceIds;
|
import com.reandroid.apk.ResourceIds;
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
@ -282,6 +283,12 @@
|
|||||||
this.currentPackage = currentPackage;
|
this.currentPackage = currentPackage;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public EncodeMaterials addFramework(FrameworkApk frameworkApk) {
|
||||||
|
if(frameworkApk!=null){
|
||||||
|
addFramework(frameworkApk.getTableBlock());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public EncodeMaterials addFramework(FrameworkTable frameworkTable) {
|
public EncodeMaterials addFramework(FrameworkTable frameworkTable) {
|
||||||
frameworkTable.loadResourceNameMap();
|
frameworkTable.loadResourceNameMap();
|
||||||
this.frameworkTables.add(frameworkTable);
|
this.frameworkTables.add(frameworkTable);
|
||||||
@ -333,10 +340,16 @@
|
|||||||
ResourceIds resourceIds = new ResourceIds();
|
ResourceIds resourceIds = new ResourceIds();
|
||||||
resourceIds.loadPackageBlock(packageBlock);
|
resourceIds.loadPackageBlock(packageBlock);
|
||||||
ResourceIds.Table.Package packageId = resourceIds.getTable().listPackages().get(0);
|
ResourceIds.Table.Package packageId = resourceIds.getTable().listPackages().get(0);
|
||||||
return new EncodeMaterials()
|
EncodeMaterials encodeMaterials = new EncodeMaterials()
|
||||||
.addPackageIds(packageId)
|
.addPackageIds(packageId)
|
||||||
.setCurrentPackage(packageBlock)
|
.setCurrentPackage(packageBlock);
|
||||||
.addFramework(Frameworks.getAndroid());
|
TableBlock tableBlock = packageBlock.getTableBlock();
|
||||||
|
for(TableBlock frameworkTable:tableBlock.getFrameWorks()){
|
||||||
|
if(frameworkTable instanceof FrameworkTable){
|
||||||
|
encodeMaterials.addFramework((FrameworkTable) frameworkTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return encodeMaterials;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||||
import com.reandroid.common.Frameworks;
|
|
||||||
import com.reandroid.xml.XMLDocument;
|
import com.reandroid.xml.XMLDocument;
|
||||||
import com.reandroid.xml.XMLException;
|
import com.reandroid.xml.XMLException;
|
||||||
import com.reandroid.xml.source.XMLFileSource;
|
import com.reandroid.xml.source.XMLFileSource;
|
||||||
@ -162,12 +161,18 @@
|
|||||||
List<File> pubXmlFileList, EncodeMaterials encodeMaterials)
|
List<File> pubXmlFileList, EncodeMaterials encodeMaterials)
|
||||||
throws IOException, XMLException {
|
throws IOException, XMLException {
|
||||||
|
|
||||||
|
encodeMaterials.setAPKLogger(apkLogger);
|
||||||
|
|
||||||
Map<File, ResourceIds.Table.Package> results = new HashMap<>();
|
Map<File, ResourceIds.Table.Package> results = new HashMap<>();
|
||||||
|
|
||||||
String packageName=null;
|
String packageName=null;
|
||||||
for(File pubXmlFile:pubXmlFileList){
|
for(File pubXmlFile:pubXmlFileList){
|
||||||
if(packageName==null){
|
if(packageName==null){
|
||||||
packageName=readManifestPackageName(toAndroidManifest(pubXmlFile));
|
File manifestFile = toAndroidManifest(pubXmlFile);
|
||||||
|
packageName=readManifestPackageName(manifestFile);
|
||||||
|
FrameworkApk frameworkApk = getApkModule()
|
||||||
|
.initializeAndroidFramework(XMLDocument.load(manifestFile));
|
||||||
|
encodeMaterials.addFramework(frameworkApk);
|
||||||
}
|
}
|
||||||
ResourceIds resourceIds=new ResourceIds();
|
ResourceIds resourceIds=new ResourceIds();
|
||||||
resourceIds.fromXml(pubXmlFile);
|
resourceIds.fromXml(pubXmlFile);
|
||||||
@ -184,8 +189,7 @@
|
|||||||
results.put(pubXmlFile, pkg);
|
results.put(pubXmlFile, pkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeMaterials.addFramework(Frameworks.getAndroid())
|
encodeMaterials.setAPKLogger(apkLogger);
|
||||||
.setAPKLogger(apkLogger);
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
private String readManifestPackageName(File manifestFile) throws XMLException {
|
private String readManifestPackageName(File manifestFile) throws XMLException {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.ValueHeader;
|
import com.reandroid.arsc.value.ValueHeader;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ import com.reandroid.arsc.value.Entry;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void encodeStringValue(Entry entry, String value){
|
void encodeStringValue(Entry entry, String value){
|
||||||
throw new EncodeException("Unexpected value for id: "+value);
|
entry.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeNullValue(Entry entry){
|
void encodeNullValue(Entry entry){
|
||||||
|
@ -281,9 +281,7 @@ import java.util.*;
|
|||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static TableBlock loadWithAndroidFramework(InputStream inputStream) throws IOException{
|
public static TableBlock loadWithAndroidFramework(InputStream inputStream) throws IOException{
|
||||||
TableBlock tableBlock=load(inputStream);
|
return load(inputStream);
|
||||||
tableBlock.addFramework(Frameworks.getAndroid());
|
|
||||||
return tableBlock;
|
|
||||||
}
|
}
|
||||||
public static TableBlock load(File file) throws IOException{
|
public static TableBlock load(File file) throws IOException{
|
||||||
return load(new FileInputStream(file));
|
return load(new FileInputStream(file));
|
||||||
|
@ -26,6 +26,7 @@ import java.io.InputStream;
|
|||||||
public class Frameworks {
|
public class Frameworks {
|
||||||
private static FrameworkTable android_table;
|
private static FrameworkTable android_table;
|
||||||
private static boolean load_once;
|
private static boolean load_once;
|
||||||
|
@Deprecated
|
||||||
public static FrameworkTable getAndroid(){
|
public static FrameworkTable getAndroid(){
|
||||||
if(android_table!=null || load_once){
|
if(android_table!=null || load_once){
|
||||||
return android_table;
|
return android_table;
|
||||||
@ -33,21 +34,10 @@ public class Frameworks {
|
|||||||
load_once=true;
|
load_once=true;
|
||||||
FrameworkTable frameworkTable=null;
|
FrameworkTable frameworkTable=null;
|
||||||
try {
|
try {
|
||||||
frameworkTable = loadFramework(ANDROID_FRAMEWORK_33);
|
frameworkTable = AndroidFrameworks.getLatest().getTableBlock();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
android_table=frameworkTable;
|
android_table=frameworkTable;
|
||||||
return android_table;
|
return android_table;
|
||||||
}
|
}
|
||||||
private static FrameworkTable loadFramework(String name) throws IOException {
|
|
||||||
InputStream inputStream= Frameworks.class.getResourceAsStream(name);
|
|
||||||
if(inputStream==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FrameworkTable frameworkTable=new FrameworkTable();
|
|
||||||
frameworkTable.readBytes(inputStream);
|
|
||||||
return frameworkTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String ANDROID_FRAMEWORK_33 = "/fwk/android_resources_33.arsc";
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user