implement new AndroidFrameworks

This commit is contained in:
REAndroid 2023-03-13 14:33:10 -04:00
parent 26b7ead67f
commit d3ef84c59f
8 changed files with 111 additions and 55 deletions

View File

@ -38,7 +38,6 @@ javadoc {
jar {
exclude('com/reandroid/test/**')
exclude('com/reandroid/facebook/**')
}
task fatJar(type: Jar) {

View File

@ -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){

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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){

View File

@ -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));

View 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";
}