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