mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 14:24:25 +02:00
V1.0.4
This commit is contained in:
parent
661073d9b4
commit
b75cb1f163
93
README.md
93
README.md
@ -2,10 +2,93 @@
|
||||
## Android binary resources read/write library
|
||||
|
||||
```java
|
||||
import com.reandroid.lib.arsc.chunk.TableBlock;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.chunk.TableBlock;
|
||||
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.lib.arsc.chunk.xml.AndroidManifestBlock;
|
||||
import com.reandroid.lib.arsc.chunk.xml.ResXmlElement;
|
||||
import com.reandroid.lib.arsc.chunk.xml.ResXmlAttribute;
|
||||
|
||||
public static void example() throws IOException{
|
||||
public static void exampleManifest() throws IOException{
|
||||
File inFile=new File("AndroidManifest.xml");
|
||||
|
||||
// *** Loading AndroidManifest ***
|
||||
AndroidManifestBlock manifestBlock = AndroidManifestBlock.load(inFile);
|
||||
|
||||
System.out.println("Package name: "+manifestBlock.getPackageName());
|
||||
|
||||
List<String> usesPermissionList = manifestBlock.getUsesPermissions();
|
||||
for(String usesPermission:usesPermissionList){
|
||||
System.out.println("Uses permission: "+usesPermission);
|
||||
}
|
||||
|
||||
// *** Modifying AndroidManifest ***
|
||||
// Change package name
|
||||
manifestBlock.setPackageName("com.new.package-name");
|
||||
// Add uses-permission
|
||||
manifestBlock.addUsesPermission("android.permission.WRITE_EXTERNAL_STORAGE");
|
||||
// Modify version code
|
||||
manifestBlock.setVersionCode(904);
|
||||
// Modify version name
|
||||
manifestBlock.setVersionName("9.0.4");
|
||||
|
||||
// Modify xml attribute
|
||||
List<ResXmlElement> activityList = manifestBlock.listActivities();
|
||||
for(ResXmlElement activityElement:activityList){
|
||||
ResXmlAttribute attributeName = activityElement.searchAttributeByResourceId(AndroidManifestBlock.ID_name);
|
||||
System.out.println("Old activity name: "+attributeName.getValueAsString());
|
||||
attributeName.setValueAsString("com.app.MyActivity");
|
||||
System.out.println("New activity name: "+attributeName.getValueAsString());
|
||||
break;
|
||||
}
|
||||
|
||||
// Refresh to re-calculate offsets
|
||||
manifestBlock.refresh();
|
||||
// Save
|
||||
File outFile=new File("AndroidManifest_out.xml");
|
||||
manifestBlock.writeBytes(outFile);
|
||||
|
||||
System.out.println("Saved: "+outFile);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
```java
|
||||
public static void exampleResourceTable() throws IOException{
|
||||
File inFile=new File("resources.arsc");
|
||||
|
||||
// *** Loading resource table ***
|
||||
TableBlock tableBlock=TableBlock.load(inFile);
|
||||
|
||||
Collection<PackageBlock> packageBlockList=tableBlock.listPackages();
|
||||
System.out.println("Packages count = "+packageBlockList.size());
|
||||
for(PackageBlock packageBlock:packageBlockList){
|
||||
System.out.println("Package id = "+packageBlock.getId()
|
||||
+", name = "+packageBlock.getName());
|
||||
}
|
||||
|
||||
// *** Modify resource table
|
||||
// Change package name
|
||||
for(PackageBlock packageBlock:packageBlockList){
|
||||
String name = packageBlock.getName();
|
||||
String newName = name + ".new-name";
|
||||
packageBlock.setName(newName);
|
||||
}
|
||||
|
||||
// Refresh to re-calculate offsets
|
||||
tableBlock.refresh();
|
||||
// Save
|
||||
File outFile=new File("resources_out.arsc");
|
||||
tableBlock.writeBytes(outFile);
|
||||
|
||||
System.out.println("Saved: "+outFile);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```java
|
||||
public static void exampleLoadApk() throws IOException{
|
||||
File inFile=new File("test.apk");
|
||||
File outDir=new File("test_out");
|
||||
|
||||
@ -15,7 +98,7 @@
|
||||
outDir=decoder.writeToDirectory(outDir);
|
||||
System.out.println("Decoded to: "+outDir);
|
||||
|
||||
// You can do any logical modification on any json files
|
||||
// You can do any logical modification on any json files here
|
||||
|
||||
// To convert back json to apk
|
||||
|
||||
@ -29,3 +112,5 @@
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
[Check implementation on APKEditor](https://github.com/REAndroid/APKEditor)
|
||||
|
@ -2,7 +2,7 @@
|
||||
apply plugin: 'java-library'
|
||||
|
||||
group 'com.reandroid.lib.arsc'
|
||||
version '1.0.3'
|
||||
version '1.0.4'
|
||||
|
||||
java {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
|
7
src/main/java/com/reandroid/lib/apk/APKLogger.java
Normal file
7
src/main/java/com/reandroid/lib/apk/APKLogger.java
Normal file
@ -0,0 +1,7 @@
|
||||
package com.reandroid.lib.apk;
|
||||
|
||||
public interface APKLogger {
|
||||
void logMessage(String msg);
|
||||
void logError(String msg, Throwable tr);
|
||||
void logVerbose(String msg);
|
||||
}
|
@ -14,6 +14,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
public class ApkModule {
|
||||
private final String moduleName;
|
||||
@ -22,6 +23,7 @@ public class ApkModule {
|
||||
private TableBlock mTableBlock;
|
||||
private AndroidManifestBlock mManifestBlock;
|
||||
private final UncompressedFiles mUncompressedFiles;
|
||||
private APKLogger apkLogger;
|
||||
ApkModule(String moduleName, APKArchive apkArchive){
|
||||
this.moduleName=moduleName;
|
||||
this.apkArchive=apkArchive;
|
||||
@ -72,6 +74,34 @@ public class ApkModule {
|
||||
public void removeDir(String dirName){
|
||||
getApkArchive().removeDir(dirName);
|
||||
}
|
||||
public void validateResourcesDir() throws IOException {
|
||||
List<ResFile> resFileList = listResFiles();
|
||||
Set<String> existPaths=new HashSet<>();
|
||||
List<InputSource> sourceList = getApkArchive().listInputSources();
|
||||
for(InputSource inputSource:sourceList){
|
||||
existPaths.add(inputSource.getAlias());
|
||||
}
|
||||
for(ResFile resFile:resFileList){
|
||||
String path=resFile.getFilePath();
|
||||
String pathNew=resFile.validateTypeDirectoryName();
|
||||
if(pathNew==null || pathNew.equals(path)){
|
||||
continue;
|
||||
}
|
||||
if(existPaths.contains(pathNew)){
|
||||
continue;
|
||||
}
|
||||
existPaths.remove(path);
|
||||
existPaths.add(pathNew);
|
||||
resFile.setFilePath(pathNew);
|
||||
if(resFile.getInputSource().getMethod() == ZipEntry.STORED){
|
||||
getUncompressedFiles().replacePath(path, pathNew);
|
||||
}
|
||||
logVerbose("Dir validated: '"+path+"' -> '"+pathNew+"'");
|
||||
}
|
||||
TableStringPool stringPool= getTableBlock().getTableStringPool();
|
||||
stringPool.refreshUniqueIdMap();
|
||||
getTableBlock().refresh();
|
||||
}
|
||||
public void setResourcesRootDir(String dirName) throws IOException {
|
||||
List<ResFile> resFileList = listResFiles();
|
||||
Set<String> existPaths=new HashSet<>();
|
||||
@ -88,9 +118,14 @@ public class ApkModule {
|
||||
existPaths.remove(path);
|
||||
existPaths.add(pathNew);
|
||||
resFile.setFilePath(pathNew);
|
||||
if(resFile.getInputSource().getMethod() == ZipEntry.STORED){
|
||||
getUncompressedFiles().replacePath(path, pathNew);
|
||||
}
|
||||
logVerbose("Root changed: '"+path+"' -> '"+pathNew+"'");
|
||||
}
|
||||
TableStringPool stringPool= getTableBlock().getTableStringPool();
|
||||
stringPool.refreshUniqueIdMap();
|
||||
getTableBlock().refresh();
|
||||
}
|
||||
public List<ResFile> listResFiles() throws IOException {
|
||||
List<ResFile> results=new ArrayList<>();
|
||||
@ -123,7 +158,7 @@ public class ApkModule {
|
||||
if(pkg==null){
|
||||
return null;
|
||||
}
|
||||
return pkg.getPackageName();
|
||||
return pkg.getName();
|
||||
}
|
||||
public void setPackageName(String name) throws IOException {
|
||||
String old=getPackageName();
|
||||
@ -137,13 +172,13 @@ public class ApkModule {
|
||||
PackageArray pkgArray = tableBlock.getPackageArray();
|
||||
for(PackageBlock pkg:pkgArray.listItems()){
|
||||
if(pkgArray.childesCount()==1){
|
||||
pkg.setPackageName(name);
|
||||
pkg.setName(name);
|
||||
continue;
|
||||
}
|
||||
String pkgName=pkg.getPackageName();
|
||||
String pkgName=pkg.getName();
|
||||
if(pkgName.startsWith(old)){
|
||||
pkgName=pkgName.replace(old, name);
|
||||
pkg.setPackageName(pkgName);
|
||||
pkg.setName(pkgName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -211,6 +246,24 @@ public class ApkModule {
|
||||
this.loadDefaultFramework = loadDefaultFramework;
|
||||
}
|
||||
|
||||
public void setAPKLogger(APKLogger logger) {
|
||||
this.apkLogger = logger;
|
||||
}
|
||||
private void logMessage(String msg) {
|
||||
if(apkLogger!=null){
|
||||
apkLogger.logMessage(msg);
|
||||
}
|
||||
}
|
||||
private void logError(String msg, Throwable tr) {
|
||||
if(apkLogger!=null){
|
||||
apkLogger.logError(msg, tr);
|
||||
}
|
||||
}
|
||||
private void logVerbose(String msg) {
|
||||
if(apkLogger!=null){
|
||||
apkLogger.logVerbose(msg);
|
||||
}
|
||||
}
|
||||
public static ApkModule loadApkFile(File apkFile) throws IOException {
|
||||
return loadApkFile(apkFile, ApkUtil.DEF_MODULE_NAME);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.reandroid.lib.apk;
|
||||
|
||||
import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.lib.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.lib.arsc.chunk.xml.ResXmlBlock;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.json.JSONObject;
|
||||
@ -18,6 +19,51 @@ public class ResFile {
|
||||
this.inputSource=inputSource;
|
||||
this.entryBlockList=entryBlockList;
|
||||
}
|
||||
public String validateTypeDirectoryName(){
|
||||
EntryBlock entryBlock=pickOne();
|
||||
if(entryBlock==null){
|
||||
return null;
|
||||
}
|
||||
String path=getFilePath();
|
||||
String root="";
|
||||
int i=path.indexOf('/');
|
||||
if(i>0){
|
||||
i++;
|
||||
root=path.substring(0, i);
|
||||
path=path.substring(i);
|
||||
}
|
||||
String name=path;
|
||||
i=path.lastIndexOf('/');
|
||||
if(i>0){
|
||||
i++;
|
||||
name=path.substring(i);
|
||||
}
|
||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
||||
String typeName=typeBlock.getTypeName()+typeBlock.getResConfig().getQualifiers();
|
||||
return root+typeName+"/"+name;
|
||||
}
|
||||
private EntryBlock pickOne(){
|
||||
List<EntryBlock> entryList = entryBlockList;
|
||||
if(entryList.size()==0){
|
||||
return null;
|
||||
}
|
||||
for(EntryBlock entryBlock:entryList){
|
||||
if(!entryBlock.isNull() && entryBlock.isDefault()){
|
||||
return entryBlock;
|
||||
}
|
||||
}
|
||||
for(EntryBlock entryBlock:entryList){
|
||||
if(!entryBlock.isNull()){
|
||||
return entryBlock;
|
||||
}
|
||||
}
|
||||
for(EntryBlock entryBlock:entryList){
|
||||
if(entryBlock.isDefault()){
|
||||
return entryBlock;
|
||||
}
|
||||
}
|
||||
return entryList.get(0);
|
||||
}
|
||||
public String getFilePath(){
|
||||
return getInputSource().getAlias();
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ public class ResourceIds {
|
||||
return;
|
||||
}
|
||||
if(pkg.id!=this.id){
|
||||
throw new IllegalArgumentException("Different package id: "+this.id+"!="+pkg.id);
|
||||
throw new DuplicateException("Different package id: "+this.id+"!="+pkg.id);
|
||||
}
|
||||
if(pkg.name!=null){
|
||||
this.name = pkg.name;
|
||||
@ -277,7 +277,7 @@ public class ResourceIds {
|
||||
return;
|
||||
}
|
||||
if(entry.getPackageId()!=this.id){
|
||||
throw new IllegalArgumentException("Different package id: "+entry);
|
||||
throw new DuplicateException("Different package id: "+entry);
|
||||
}
|
||||
byte typeId=entry.getTypeId();
|
||||
Type type=typeMap.get(typeId);
|
||||
@ -400,7 +400,7 @@ public class ResourceIds {
|
||||
return;
|
||||
}
|
||||
if(this.id!= type.id){
|
||||
throw new IllegalArgumentException("Different type ids: "+id+"!="+type.id);
|
||||
throw new DuplicateException("Different type ids: "+id+"!="+type.id);
|
||||
}
|
||||
if(type.name!=null){
|
||||
this.name=type.name;
|
||||
@ -427,7 +427,7 @@ public class ResourceIds {
|
||||
return;
|
||||
}
|
||||
if(entry.getTypeId()!=this.id){
|
||||
throw new IllegalArgumentException("Different type id: "+entry);
|
||||
throw new DuplicateException("Different type id: "+entry);
|
||||
}
|
||||
short key=entry.getEntryId();
|
||||
Entry exist=entryMap.get(key);
|
||||
@ -435,7 +435,7 @@ public class ResourceIds {
|
||||
if(Objects.equals(exist.name, entry.name)){
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("Duplicate entry exist: "+exist+", entry: "+entry);
|
||||
throw new DuplicateException("Duplicate entry exist: "+exist+", entry: "+entry);
|
||||
}
|
||||
if(name == null){
|
||||
this.name = entry.typeName;
|
||||
@ -652,10 +652,10 @@ public class ResourceIds {
|
||||
matcher= pattern.matcher(element);
|
||||
}
|
||||
if(id==0){
|
||||
throw new IllegalArgumentException("Missing id: "+xmlElement);
|
||||
throw new DuplicateException("Missing id: "+xmlElement);
|
||||
}
|
||||
if(name==null){
|
||||
throw new IllegalArgumentException("Missing name: "+xmlElement);
|
||||
throw new DuplicateException("Missing name: "+xmlElement);
|
||||
}
|
||||
return new Entry(id, type, name);
|
||||
}
|
||||
@ -684,6 +684,17 @@ public class ResourceIds {
|
||||
| (entryId & 0xffff);
|
||||
}
|
||||
}
|
||||
public static class DuplicateException extends IllegalArgumentException{
|
||||
public DuplicateException(String message){
|
||||
super(message);
|
||||
}
|
||||
public DuplicateException(String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
public DuplicateException(Throwable cause) {
|
||||
super(cause.getMessage(), cause);
|
||||
}
|
||||
}
|
||||
|
||||
public static final String JSON_FILE_NAME ="resource-ids.json";
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class TableBlockJson {
|
||||
File infoFile=new File(pkgDir, PackageBlock.JSON_FILE_NAME);
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(PackageBlock.NAME_package_id, packageBlock.getId());
|
||||
jsonObject.put(PackageBlock.NAME_package_name, packageBlock.getPackageName());
|
||||
jsonObject.put(PackageBlock.NAME_package_name, packageBlock.getName());
|
||||
jsonObject.write(infoFile);
|
||||
for(SpecTypePair specTypePair: packageBlock.listAllSpecTypePair()){
|
||||
for(TypeBlock typeBlock:specTypePair.getTypeBlockArray().listItems()){
|
||||
@ -52,7 +52,7 @@ public class TableBlockJson {
|
||||
private String getDirName(PackageBlock packageBlock){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(String.format("0x%02x", packageBlock.getId()));
|
||||
String name= packageBlock.getPackageName();
|
||||
String name= packageBlock.getName();
|
||||
if(name!=null){
|
||||
builder.append('-');
|
||||
builder.append(name);
|
||||
|
@ -70,6 +70,10 @@ public class UncompressedFiles implements JSONConvert<JSONObject> {
|
||||
return mExtensionList.contains(extension.substring(1));
|
||||
}
|
||||
public boolean containsPath(String path){
|
||||
path=sanitizePath(path);
|
||||
if(path==null){
|
||||
return false;
|
||||
}
|
||||
return mPathList.contains(path);
|
||||
}
|
||||
public void addPath(ZipArchive zipArchive){
|
||||
@ -84,15 +88,31 @@ public class UncompressedFiles implements JSONConvert<JSONObject> {
|
||||
addPath(inputSource.getAlias());
|
||||
}
|
||||
public void addPath(String path){
|
||||
if(path==null || path.length()==0){
|
||||
path=sanitizePath(path);
|
||||
if(path==null){
|
||||
return;
|
||||
}
|
||||
path=path.replace(File.separatorChar, '/').trim();
|
||||
while (path.startsWith("/")){
|
||||
path=path.substring(1);
|
||||
}
|
||||
mPathList.add(path);
|
||||
}
|
||||
public void removePath(String path){
|
||||
path=sanitizePath(path);
|
||||
if(path==null){
|
||||
return;
|
||||
}
|
||||
mPathList.remove(path);
|
||||
}
|
||||
public void replacePath(String path, String rep){
|
||||
path=sanitizePath(path);
|
||||
rep=sanitizePath(rep);
|
||||
if(path==null||rep==null){
|
||||
return;
|
||||
}
|
||||
if(!mPathList.contains(path)){
|
||||
return;
|
||||
}
|
||||
mPathList.remove(path);
|
||||
mPathList.add(rep);
|
||||
}
|
||||
public void addCommonExtensions(){
|
||||
for(String ext:COMMON_EXTENSIONS){
|
||||
addExtension(ext);
|
||||
@ -146,6 +166,19 @@ public class UncompressedFiles implements JSONConvert<JSONObject> {
|
||||
JSONObject jsonObject=new JSONObject(new FileInputStream(jsonFile));
|
||||
fromJson(jsonObject);
|
||||
}
|
||||
private static String sanitizePath(String path){
|
||||
if(path==null || path.length()==0){
|
||||
return null;
|
||||
}
|
||||
path=path.replace(File.separatorChar, '/').trim();
|
||||
while (path.startsWith("/")){
|
||||
path=path.substring(1);
|
||||
}
|
||||
if(path.length()==0){
|
||||
return null;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
public static final String JSON_FILE = "uncompressed-files.json";
|
||||
public static final String NAME_paths = "paths";
|
||||
public static final String NAME_extensions = "extensions";
|
||||
|
@ -113,8 +113,6 @@ public class PackageBlock extends BaseChunk implements BlockLoad, JSONConvert<JS
|
||||
public void setName(String name){
|
||||
mPackageName.set(name);
|
||||
}
|
||||
|
||||
|
||||
public TableBlock getTableBlock(){
|
||||
Block parent=getParent();
|
||||
while(parent!=null){
|
||||
@ -125,13 +123,6 @@ public class PackageBlock extends BaseChunk implements BlockLoad, JSONConvert<JS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public String getPackageName(){
|
||||
return mPackageName.get();
|
||||
}
|
||||
public void setPackageName(String name){
|
||||
mPackageName.set(name);
|
||||
}
|
||||
|
||||
public TypeStringPool getTypeStringPool(){
|
||||
return mTypeStringPool;
|
||||
}
|
||||
|
@ -143,6 +143,9 @@ public class TableBlock extends BaseChunk implements JSONConvert<JSONObject> {
|
||||
tableBlock.addFramework(Frameworks.getAndroid());
|
||||
return tableBlock;
|
||||
}
|
||||
public static TableBlock load(File file) throws IOException{
|
||||
return load(new FileInputStream(file));
|
||||
}
|
||||
public static TableBlock load(InputStream inputStream) throws IOException{
|
||||
TableBlock tableBlock=new TableBlock();
|
||||
tableBlock.readBytes(inputStream);
|
||||
|
@ -248,6 +248,16 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
builder.append("}");
|
||||
return builder.toString();
|
||||
}
|
||||
public static boolean isAndroidManifestBlock(ResXmlBlock xmlBlock){
|
||||
if(xmlBlock==null){
|
||||
return false;
|
||||
}
|
||||
ResXmlElement root = xmlBlock.getResXmlElement();
|
||||
if(root==null){
|
||||
return false;
|
||||
}
|
||||
return TAG_manifest.equals(root.getTag());
|
||||
}
|
||||
public static AndroidManifestBlock load(File file) throws IOException {
|
||||
return load(new FileInputStream(file));
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
super(7);
|
||||
mNamespaceReference =new IntegerItem(-1);
|
||||
mNameReference =new IntegerItem();
|
||||
mValueStringReference =new IntegerItem();
|
||||
mValueStringReference =new IntegerItem(-1);
|
||||
mNameType=new ShortItem((short) 0x0008);
|
||||
mReserved =new ByteItem();
|
||||
mValueTypeByte=new ByteItem();
|
||||
@ -42,7 +42,7 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
int getNamespaceReference(){
|
||||
return mNamespaceReference.get();
|
||||
}
|
||||
void setNamespaceReference(int ref){
|
||||
public void setNamespaceReference(int ref){
|
||||
mNamespaceReference.set(ref);
|
||||
}
|
||||
int getNameReference(){
|
||||
@ -112,7 +112,7 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
}
|
||||
return startNamespace.getPrefix();
|
||||
}
|
||||
ResXmlStartNamespace getStartNamespace(){
|
||||
public ResXmlStartNamespace getStartNamespace(){
|
||||
ResXmlElement xmlElement=getParentResXmlElement();
|
||||
if(xmlElement==null){
|
||||
return null;
|
||||
@ -131,6 +131,7 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
setValueStringReference(ref);
|
||||
if(getValueType()==ValueType.STRING){
|
||||
setRawValue(ref);
|
||||
setValueStringReference(ref);
|
||||
}
|
||||
return resXmlString;
|
||||
}
|
||||
@ -280,7 +281,7 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
}
|
||||
public void setValueAsBoolean(boolean val){
|
||||
setValueType(ValueType.INT_BOOLEAN);
|
||||
int ref=val?0xffff:0;
|
||||
int ref=val?0xffffffff:0;
|
||||
setRawValue(ref);
|
||||
setValueStringReference(-1);
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ public class ResXmlElement extends FixedBlockContainer implements JSONConvert<JS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public Collection<ResXmlAttribute> listResXmlAttributes(){
|
||||
public Collection<ResXmlAttribute> listAttributes(){
|
||||
ResXmlStartElement startElement=getStartElement();
|
||||
if(startElement!=null){
|
||||
return startElement.listResXmlAttributes();
|
||||
|
@ -31,6 +31,14 @@ public class ResXmlStartElement extends BaseXmlChunk {
|
||||
addChild(mClassAttribute);
|
||||
addChild(mAttributeArray);
|
||||
}
|
||||
public ResXmlAttribute getAttribute(int resourceId){
|
||||
for(ResXmlAttribute attribute:listResXmlAttributes()){
|
||||
if(resourceId==attribute.getNameResourceID()){
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ResXmlAttribute getAttribute(String uri, String name){
|
||||
if(name==null){
|
||||
return null;
|
||||
|
@ -25,8 +25,8 @@ public class ValueDecoder {
|
||||
}
|
||||
String prefix=null;
|
||||
if(currentPackage!=null){
|
||||
String name=currentPackage.getPackageName();
|
||||
String other=entryBlock.getPackageBlock().getPackageName();
|
||||
String name=currentPackage.getName();
|
||||
String other=entryBlock.getPackageBlock().getName();
|
||||
if(!name.equals(other)){
|
||||
prefix=other+":";
|
||||
}
|
||||
@ -67,7 +67,7 @@ public class ValueDecoder {
|
||||
is_attribute=true;
|
||||
}
|
||||
if(is_reference || is_attribute){
|
||||
String ref=buildReferenceValue(store, valueType, currentPackage.getPackageName(), data);
|
||||
String ref=buildReferenceValue(store, valueType, currentPackage.getName(), data);
|
||||
if(ref!=null){
|
||||
return ref;
|
||||
}
|
||||
@ -286,7 +286,7 @@ public class ValueDecoder {
|
||||
return null;
|
||||
}
|
||||
for(PackageBlock packageBlock:allPkg){
|
||||
String name=packageBlock.getPackageName();
|
||||
String name=packageBlock.getName();
|
||||
if(name!=null){
|
||||
return name;
|
||||
}
|
||||
@ -307,7 +307,7 @@ public class ValueDecoder {
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
return packageBlock.getPackageName();
|
||||
return packageBlock.getName();
|
||||
}
|
||||
private static EntryGroup searchEntryGroup(EntryStore store, EntryBlock entryBlock, int resourceId){
|
||||
EntryGroup entryGroup=searchEntryGroup(entryBlock, resourceId);
|
||||
|
@ -3,6 +3,7 @@ package com.reandroid.lib.arsc.io;
|
||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
|
||||
public class BlockReader extends InputStream {
|
||||
@ -317,6 +318,9 @@ public class BlockReader extends InputStream {
|
||||
while((len=in.read(buff))>0){
|
||||
result=add(result, buff, len);
|
||||
}
|
||||
if(!(in instanceof ZipInputStream)){
|
||||
in.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private static byte[] add(byte[] arr1, byte[] arr2, int len){
|
||||
@ -331,7 +335,7 @@ public class BlockReader extends InputStream {
|
||||
}
|
||||
public static HeaderBlock readHeaderBlock(InputStream inputStream) throws IOException{
|
||||
byte[] buffer=new byte[8];
|
||||
inputStream.read(buffer);
|
||||
inputStream.read(buffer, 0, 8);
|
||||
inputStream.close();
|
||||
BlockReader reader=new BlockReader(buffer);
|
||||
return reader.readHeaderBlock();
|
||||
|
@ -273,7 +273,7 @@ public class FrameworkTable extends TableBlock {
|
||||
for(PackageBlock packageBlock:allPkg){
|
||||
builder.append("\n ");
|
||||
builder.append(String.format("0x%02x", packageBlock.getId()));
|
||||
builder.append(":").append(packageBlock.getPackageName());
|
||||
builder.append(":").append(packageBlock.getName());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
return packageBlock.getPackageName();
|
||||
return packageBlock.getName();
|
||||
}
|
||||
public SpecString getSpecString(){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
|
Loading…
x
Reference in New Issue
Block a user