mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-03 07:34:25 +02:00
define apk type
This commit is contained in:
parent
aac57842ed
commit
3919457f4b
@ -24,14 +24,13 @@ import com.reandroid.arsc.chunk.TableBlock;
|
|||||||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||||
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
||||||
import com.reandroid.arsc.container.SpecTypePair;
|
import com.reandroid.arsc.container.SpecTypePair;
|
||||||
|
import com.reandroid.arsc.decoder.Decoder;
|
||||||
import com.reandroid.arsc.group.StringGroup;
|
import com.reandroid.arsc.group.StringGroup;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.util.FrameworkTable;
|
import com.reandroid.arsc.util.FrameworkTable;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
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.XMLDocument;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
import com.reandroid.xml.XMLException;
|
import com.reandroid.xml.XMLException;
|
||||||
@ -47,17 +46,25 @@ public class ApkModule implements ApkFile {
|
|||||||
private final String moduleName;
|
private final String moduleName;
|
||||||
private final APKArchive apkArchive;
|
private final APKArchive apkArchive;
|
||||||
private boolean loadDefaultFramework = true;
|
private boolean loadDefaultFramework = true;
|
||||||
|
private boolean mDisableLoadFramework = false;
|
||||||
private TableBlock mTableBlock;
|
private TableBlock mTableBlock;
|
||||||
private AndroidManifestBlock mManifestBlock;
|
private AndroidManifestBlock mManifestBlock;
|
||||||
private final UncompressedFiles mUncompressedFiles;
|
private final UncompressedFiles mUncompressedFiles;
|
||||||
private APKLogger apkLogger;
|
private APKLogger apkLogger;
|
||||||
private TableEntryStore mEntryStore;
|
private Decoder mDecoder;
|
||||||
|
private ApkType mApkType;
|
||||||
public ApkModule(String moduleName, APKArchive apkArchive){
|
public ApkModule(String moduleName, APKArchive apkArchive){
|
||||||
this.moduleName=moduleName;
|
this.moduleName=moduleName;
|
||||||
this.apkArchive=apkArchive;
|
this.apkArchive=apkArchive;
|
||||||
this.mUncompressedFiles=new UncompressedFiles();
|
this.mUncompressedFiles=new UncompressedFiles();
|
||||||
this.mUncompressedFiles.addPath(apkArchive);
|
this.mUncompressedFiles.addPath(apkArchive);
|
||||||
}
|
}
|
||||||
|
public String getSplit(){
|
||||||
|
if(!hasAndroidManifestBlock()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getAndroidManifestBlock().getSplit();
|
||||||
|
}
|
||||||
public FrameworkApk initializeAndroidFramework() throws IOException {
|
public FrameworkApk initializeAndroidFramework() throws IOException {
|
||||||
if(!hasTableBlock()){
|
if(!hasTableBlock()){
|
||||||
return null;
|
return null;
|
||||||
@ -485,11 +492,15 @@ public class ApkModule implements ApkFile {
|
|||||||
archive.add(blockInputSource);
|
archive.add(blockInputSource);
|
||||||
manifestBlock.setApkFile(this);
|
manifestBlock.setApkFile(this);
|
||||||
mManifestBlock = manifestBlock;
|
mManifestBlock = manifestBlock;
|
||||||
|
onManifestBlockLoaded(manifestBlock);
|
||||||
} catch (IOException exception) {
|
} catch (IOException exception) {
|
||||||
throw new IllegalArgumentException(exception);
|
throw new IllegalArgumentException(exception);
|
||||||
}
|
}
|
||||||
return mManifestBlock;
|
return mManifestBlock;
|
||||||
}
|
}
|
||||||
|
private void onManifestBlockLoaded(AndroidManifestBlock manifestBlock){
|
||||||
|
initializeApkType(manifestBlock);
|
||||||
|
}
|
||||||
public TableBlock getTableBlock(boolean initFramework) {
|
public TableBlock getTableBlock(boolean initFramework) {
|
||||||
if(mTableBlock==null){
|
if(mTableBlock==null){
|
||||||
if(!hasTableBlock()){
|
if(!hasTableBlock()){
|
||||||
@ -509,7 +520,7 @@ public class ApkModule implements ApkFile {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public TableBlock getTableBlock() {
|
public TableBlock getTableBlock() {
|
||||||
return getTableBlock(true);
|
return getTableBlock(!mDisableLoadFramework);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public ResXmlDocument loadResXmlDocument(String path) throws IOException{
|
public ResXmlDocument loadResXmlDocument(String path) throws IOException{
|
||||||
@ -522,6 +533,38 @@ public class ApkModule implements ApkFile {
|
|||||||
resXmlDocument.readBytes(inputSource.openStream());
|
resXmlDocument.readBytes(inputSource.openStream());
|
||||||
return resXmlDocument;
|
return resXmlDocument;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public Decoder getDecoder(){
|
||||||
|
return mDecoder;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDecoder(Decoder decoder){
|
||||||
|
this.mDecoder = decoder;
|
||||||
|
}
|
||||||
|
public ApkType getApkType(){
|
||||||
|
if(mApkType!=null){
|
||||||
|
return mApkType;
|
||||||
|
}
|
||||||
|
return initializeApkType(mManifestBlock);
|
||||||
|
}
|
||||||
|
public void setApkType(ApkType apkType){
|
||||||
|
this.mApkType = apkType;
|
||||||
|
}
|
||||||
|
private ApkType initializeApkType(AndroidManifestBlock manifestBlock){
|
||||||
|
if(mApkType!=null){
|
||||||
|
return mApkType;
|
||||||
|
}
|
||||||
|
ApkType apkType = null;
|
||||||
|
if(manifestBlock!=null){
|
||||||
|
apkType = manifestBlock.guessApkType();
|
||||||
|
}
|
||||||
|
if(apkType != null){
|
||||||
|
mApkType = apkType;
|
||||||
|
}else {
|
||||||
|
apkType = ApkType.UNKNOWN;
|
||||||
|
}
|
||||||
|
return apkType;
|
||||||
|
}
|
||||||
|
|
||||||
// If we need TableStringPool only, this loads pool without
|
// If we need TableStringPool only, this loads pool without
|
||||||
// loading packages and other chunk blocks for faster and less memory usage
|
// loading packages and other chunk blocks for faster and less memory usage
|
||||||
@ -574,6 +617,7 @@ public class ApkModule implements ApkFile {
|
|||||||
}
|
}
|
||||||
public void setLoadDefaultFramework(boolean loadDefaultFramework) {
|
public void setLoadDefaultFramework(boolean loadDefaultFramework) {
|
||||||
this.loadDefaultFramework = loadDefaultFramework;
|
this.loadDefaultFramework = loadDefaultFramework;
|
||||||
|
this.mDisableLoadFramework = !loadDefaultFramework;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void merge(ApkModule module) throws IOException {
|
public void merge(ApkModule module) throws IOException {
|
||||||
|
@ -18,6 +18,7 @@ package com.reandroid.arsc;
|
|||||||
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.arsc.chunk.xml.ResXmlDocument;
|
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
||||||
|
import com.reandroid.arsc.decoder.Decoder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -25,4 +26,13 @@ public interface ApkFile {
|
|||||||
AndroidManifestBlock getAndroidManifestBlock();
|
AndroidManifestBlock getAndroidManifestBlock();
|
||||||
TableBlock getTableBlock();
|
TableBlock getTableBlock();
|
||||||
ResXmlDocument loadResXmlDocument(String path) throws IOException;
|
ResXmlDocument loadResXmlDocument(String path) throws IOException;
|
||||||
|
Decoder getDecoder();
|
||||||
|
void setDecoder(Decoder decoder);
|
||||||
|
|
||||||
|
enum ApkType {
|
||||||
|
BASE,
|
||||||
|
SPLIT,
|
||||||
|
CORE,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,6 +227,17 @@ import java.util.*;
|
|||||||
public List<TableBlock> getFrameWorks(){
|
public List<TableBlock> getFrameWorks(){
|
||||||
return mFrameWorks;
|
return mFrameWorks;
|
||||||
}
|
}
|
||||||
|
public boolean isAndroid(){
|
||||||
|
PackageBlock packageBlock = pickOne();
|
||||||
|
if(packageBlock == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return "android".equals(packageBlock.getName())
|
||||||
|
&& packageBlock.getId() == 0x01;
|
||||||
|
}
|
||||||
|
public boolean hasFramework(){
|
||||||
|
return getFrameWorks().size() != 0;
|
||||||
|
}
|
||||||
public void addFramework(TableBlock tableBlock){
|
public void addFramework(TableBlock tableBlock){
|
||||||
if(tableBlock==null||tableBlock==this){
|
if(tableBlock==null||tableBlock==this){
|
||||||
return;
|
return;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.chunk.xml;
|
package com.reandroid.arsc.chunk.xml;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.ApkFile;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -30,6 +31,33 @@ public class AndroidManifestBlock extends ResXmlDocument {
|
|||||||
super();
|
super();
|
||||||
super.getStringPool().setUtf8(false);
|
super.getStringPool().setUtf8(false);
|
||||||
}
|
}
|
||||||
|
public ApkFile.ApkType guessApkType(){
|
||||||
|
if(isSplit()){
|
||||||
|
return ApkFile.ApkType.SPLIT;
|
||||||
|
}
|
||||||
|
Boolean core = isCoreApp();
|
||||||
|
if(core!=null && core){
|
||||||
|
return ApkFile.ApkType.CORE;
|
||||||
|
}
|
||||||
|
if(getMainActivity()!=null){
|
||||||
|
return ApkFile.ApkType.BASE;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public Boolean isCoreApp(){
|
||||||
|
ResXmlElement manifest = getManifestElement();
|
||||||
|
if(manifest == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ResXmlAttribute attribute = manifest.searchAttributeByName(NAME_coreApp);
|
||||||
|
if(attribute == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if(attribute.getValueType() != ValueType.INT_BOOLEAN){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return attribute.getValueAsBoolean();
|
||||||
|
}
|
||||||
public boolean isSplit(){
|
public boolean isSplit(){
|
||||||
ResXmlElement manifest = getManifestElement();
|
ResXmlElement manifest = getManifestElement();
|
||||||
if(manifest == null){
|
if(manifest == null){
|
||||||
|
@ -35,6 +35,7 @@ import java.io.IOException;
|
|||||||
public class Decoder {
|
public class Decoder {
|
||||||
private final EntryStore entryStore;
|
private final EntryStore entryStore;
|
||||||
private int currentPackageId;
|
private int currentPackageId;
|
||||||
|
private ApkFile mApkFile;
|
||||||
public Decoder(EntryStore entryStore, int currentPackageId){
|
public Decoder(EntryStore entryStore, int currentPackageId){
|
||||||
this.entryStore = entryStore;
|
this.entryStore = entryStore;
|
||||||
this.currentPackageId = currentPackageId;
|
this.currentPackageId = currentPackageId;
|
||||||
@ -83,6 +84,15 @@ public class Decoder {
|
|||||||
public void setCurrentPackageId(int currentPackageId) {
|
public void setCurrentPackageId(int currentPackageId) {
|
||||||
this.currentPackageId = currentPackageId;
|
this.currentPackageId = currentPackageId;
|
||||||
}
|
}
|
||||||
|
public ApkFile getApkFile(){
|
||||||
|
return mApkFile;
|
||||||
|
}
|
||||||
|
public void setApkFile(ApkFile apkFile) {
|
||||||
|
this.mApkFile = apkFile;
|
||||||
|
}
|
||||||
|
public boolean isNullDecoder(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static Decoder create(ResXmlDocument resXmlDocument){
|
public static Decoder create(ResXmlDocument resXmlDocument){
|
||||||
MainChunk mainChunk = resXmlDocument.getMainChunk();
|
MainChunk mainChunk = resXmlDocument.getMainChunk();
|
||||||
@ -107,7 +117,7 @@ public class Decoder {
|
|||||||
return create(tableBlock);
|
return create(tableBlock);
|
||||||
}
|
}
|
||||||
public static Decoder create(TableBlock tableBlock){
|
public static Decoder create(TableBlock tableBlock){
|
||||||
if(tableBlock.getFrameWorks().size()==0){
|
if(!tableBlock.hasFramework() && !tableBlock.isAndroid()){
|
||||||
tableBlock.addFramework(getFramework());
|
tableBlock.addFramework(getFramework());
|
||||||
}
|
}
|
||||||
int currentPackageId;
|
int currentPackageId;
|
||||||
@ -121,7 +131,7 @@ public class Decoder {
|
|||||||
return create(tableBlock, currentPackageId);
|
return create(tableBlock, currentPackageId);
|
||||||
}
|
}
|
||||||
public static Decoder create(TableBlock tableBlock, int currentPackageId){
|
public static Decoder create(TableBlock tableBlock, int currentPackageId){
|
||||||
if(tableBlock.getFrameWorks().size()==0){
|
if(!tableBlock.hasFramework() && !tableBlock.isAndroid()){
|
||||||
TableBlock framework = getFramework();
|
TableBlock framework = getFramework();
|
||||||
if(framework!=null){
|
if(framework!=null){
|
||||||
PackageBlock packageBlock = framework.pickOne();
|
PackageBlock packageBlock = framework.pickOne();
|
||||||
@ -151,10 +161,19 @@ public class Decoder {
|
|||||||
return NULL_ENTRY_STORE_DECODER;
|
return NULL_ENTRY_STORE_DECODER;
|
||||||
}
|
}
|
||||||
synchronized (Decoder.class){
|
synchronized (Decoder.class){
|
||||||
Decoder decoder = new Decoder(getFramework(), 0x7f);
|
NullEntryDecoder decoder = new NullEntryDecoder(getFramework(), 0x7f);
|
||||||
NULL_ENTRY_STORE_DECODER = decoder;
|
NULL_ENTRY_STORE_DECODER = decoder;
|
||||||
return decoder;
|
return decoder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static Decoder NULL_ENTRY_STORE_DECODER;
|
static class NullEntryDecoder extends Decoder{
|
||||||
|
public NullEntryDecoder(EntryStore entryStore, int currentPackageId) {
|
||||||
|
super(entryStore, currentPackageId);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean isNullDecoder(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static NullEntryDecoder NULL_ENTRY_STORE_DECODER;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user