mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-08 09:44:26 +02:00
V1.0.3
This commit is contained in:
parent
6656786ecf
commit
7f6cc3123d
@ -30,6 +30,7 @@ public class ApkJsonDecoder {
|
|||||||
writeManifest(dir);
|
writeManifest(dir);
|
||||||
writeTable(dir);
|
writeTable(dir);
|
||||||
writeResourceIds(dir);
|
writeResourceIds(dir);
|
||||||
|
//writePublicXml(dir);
|
||||||
writeResources(dir);
|
writeResources(dir);
|
||||||
writeRootFiles(dir);
|
writeRootFiles(dir);
|
||||||
return new File(dir, apkModule.getModuleName());
|
return new File(dir, apkModule.getModuleName());
|
||||||
@ -117,6 +118,16 @@ public class ApkJsonDecoder {
|
|||||||
File file=toResourceIds(dir);
|
File file=toResourceIds(dir);
|
||||||
jsonObject.write(file);
|
jsonObject.write(file);
|
||||||
}
|
}
|
||||||
|
private void writePublicXml(File dir) throws IOException {
|
||||||
|
if(!apkModule.hasTableBlock()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TableBlock tableBlock = apkModule.getTableBlock();
|
||||||
|
ResourceIds resourceIds=new ResourceIds();
|
||||||
|
resourceIds.loadTableBlock(tableBlock);
|
||||||
|
File file=toResourceIdsXml(dir);
|
||||||
|
resourceIds.writeXml(file);
|
||||||
|
}
|
||||||
private void writeManifest(File dir) throws IOException {
|
private void writeManifest(File dir) throws IOException {
|
||||||
if(!apkModule.hasAndroidManifestBlock()){
|
if(!apkModule.hasAndroidManifestBlock()){
|
||||||
return;
|
return;
|
||||||
@ -146,6 +157,11 @@ public class ApkJsonDecoder {
|
|||||||
String name = ResourceIds.JSON_FILE_NAME;
|
String name = ResourceIds.JSON_FILE_NAME;
|
||||||
return new File(file, name);
|
return new File(file, name);
|
||||||
}
|
}
|
||||||
|
private File toResourceIdsXml(File dir){
|
||||||
|
File file=new File(dir, apkModule.getModuleName());
|
||||||
|
String name = "public.xml";
|
||||||
|
return new File(file, name);
|
||||||
|
}
|
||||||
private File toUncompressedJsonFile(File dir){
|
private File toUncompressedJsonFile(File dir){
|
||||||
File file = new File(dir, apkModule.getModuleName());
|
File file = new File(dir, apkModule.getModuleName());
|
||||||
return new File(file, UncompressedFiles.JSON_FILE);
|
return new File(file, UncompressedFiles.JSON_FILE);
|
||||||
|
@ -22,8 +22,25 @@ public class ApkJsonEncoder {
|
|||||||
scanRootDirs(moduleDir);
|
scanRootDirs(moduleDir);
|
||||||
ApkModule module=new ApkModule(moduleName, apkArchive);
|
ApkModule module=new ApkModule(moduleName, apkArchive);
|
||||||
loadUncompressed(module, moduleDir);
|
loadUncompressed(module, moduleDir);
|
||||||
|
applyResourceId(module, moduleDir);
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
private void applyResourceId(ApkModule apkModule, File moduleDir) {
|
||||||
|
if(!apkModule.hasTableBlock()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File pubXml=toResourceIdsXml(moduleDir);
|
||||||
|
if(!pubXml.isFile()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResourceIds resourceIds=new ResourceIds();
|
||||||
|
try {
|
||||||
|
resourceIds.fromXml(pubXml);
|
||||||
|
resourceIds.applyTo(apkModule.getTableBlock());
|
||||||
|
} catch (IOException exception) {
|
||||||
|
throw new IllegalArgumentException(exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
private void loadUncompressed(ApkModule module, File moduleDir){
|
private void loadUncompressed(ApkModule module, File moduleDir){
|
||||||
File jsonFile=toUncompressedJsonFile(moduleDir);
|
File jsonFile=toUncompressedJsonFile(moduleDir);
|
||||||
UncompressedFiles uf= module.getUncompressedFiles();
|
UncompressedFiles uf= module.getUncompressedFiles();
|
||||||
@ -95,6 +112,10 @@ public class ApkJsonEncoder {
|
|||||||
String name = AndroidManifestBlock.FILE_NAME + ApkUtil.JSON_FILE_EXTENSION;
|
String name = AndroidManifestBlock.FILE_NAME + ApkUtil.JSON_FILE_EXTENSION;
|
||||||
return new File(dir, name);
|
return new File(dir, name);
|
||||||
}
|
}
|
||||||
|
private File toResourceIdsXml(File dir){
|
||||||
|
String name = "public.xml";
|
||||||
|
return new File(dir, name);
|
||||||
|
}
|
||||||
private File toUncompressedJsonFile(File dir){
|
private File toUncompressedJsonFile(File dir){
|
||||||
return new File(dir, UncompressedFiles.JSON_FILE);
|
return new File(dir, UncompressedFiles.JSON_FILE);
|
||||||
}
|
}
|
||||||
|
@ -160,13 +160,19 @@ public class ApkModule {
|
|||||||
throw new IOException("Entry not found: "+TableBlock.FILE_NAME);
|
throw new IOException("Entry not found: "+TableBlock.FILE_NAME);
|
||||||
}
|
}
|
||||||
TableBlock tableBlock;
|
TableBlock tableBlock;
|
||||||
InputStream inputStream = inputSource.openStream();
|
if(inputSource instanceof SplitJsonTableInputSource){
|
||||||
if(loadDefaultFramework){
|
tableBlock=((SplitJsonTableInputSource)inputSource).getTableBlock();
|
||||||
tableBlock=TableBlock.loadWithAndroidFramework(inputStream);
|
}else if(inputSource instanceof SingleJsonTableInputSource){
|
||||||
|
tableBlock=((SingleJsonTableInputSource)inputSource).getTableBlock();
|
||||||
}else {
|
}else {
|
||||||
tableBlock=TableBlock.load(inputStream);
|
InputStream inputStream = inputSource.openStream();
|
||||||
|
if(loadDefaultFramework){
|
||||||
|
tableBlock=TableBlock.loadWithAndroidFramework(inputStream);
|
||||||
|
}else {
|
||||||
|
tableBlock=TableBlock.load(inputStream);
|
||||||
|
}
|
||||||
|
inputStream.close();
|
||||||
}
|
}
|
||||||
inputStream.close();
|
|
||||||
mTableBlock=tableBlock;
|
mTableBlock=tableBlock;
|
||||||
BlockInputSource<TableBlock> blockInputSource=new BlockInputSource<>(inputSource.getName(),tableBlock);
|
BlockInputSource<TableBlock> blockInputSource=new BlockInputSource<>(inputSource.getName(),tableBlock);
|
||||||
blockInputSource.setMethod(inputSource.getMethod());
|
blockInputSource.setMethod(inputSource.getMethod());
|
||||||
|
@ -4,6 +4,7 @@ import com.reandroid.archive.FileInputSource;
|
|||||||
import com.reandroid.archive.InputSource;
|
import com.reandroid.archive.InputSource;
|
||||||
import com.reandroid.lib.arsc.base.Block;
|
import com.reandroid.lib.arsc.base.Block;
|
||||||
import com.reandroid.lib.arsc.chunk.xml.ResXmlBlock;
|
import com.reandroid.lib.arsc.chunk.xml.ResXmlBlock;
|
||||||
|
import com.reandroid.lib.json.JSONException;
|
||||||
import com.reandroid.lib.json.JSONObject;
|
import com.reandroid.lib.json.JSONObject;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -31,9 +32,12 @@ public class JsonXmlInputSource extends InputSource {
|
|||||||
private ResXmlBlock getResXmlBlock() throws IOException{
|
private ResXmlBlock getResXmlBlock() throws IOException{
|
||||||
ResXmlBlock resXmlBlock=newInstance();
|
ResXmlBlock resXmlBlock=newInstance();
|
||||||
InputStream inputStream=inputSource.openStream();
|
InputStream inputStream=inputSource.openStream();
|
||||||
JSONObject jsonObject=new JSONObject(inputStream);
|
try{
|
||||||
resXmlBlock.fromJson(jsonObject);
|
JSONObject jsonObject=new JSONObject(inputStream);
|
||||||
inputStream.close();
|
resXmlBlock.fromJson(jsonObject);
|
||||||
|
}catch (JSONException ex){
|
||||||
|
throw new IOException(inputSource.getAlias()+": "+ex.getMessage());
|
||||||
|
}
|
||||||
return resXmlBlock;
|
return resXmlBlock;
|
||||||
}
|
}
|
||||||
ResXmlBlock newInstance(){
|
ResXmlBlock newInstance(){
|
||||||
|
@ -7,10 +7,9 @@ import com.reandroid.lib.arsc.group.EntryGroup;
|
|||||||
import com.reandroid.lib.json.JSONArray;
|
import com.reandroid.lib.json.JSONArray;
|
||||||
import com.reandroid.lib.json.JSONObject;
|
import com.reandroid.lib.json.JSONObject;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.io.*;
|
||||||
import java.util.HashMap;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -22,6 +21,12 @@ public class ResourceIds {
|
|||||||
public ResourceIds(){
|
public ResourceIds(){
|
||||||
this(new Table());
|
this(new Table());
|
||||||
}
|
}
|
||||||
|
public void applyTo(TableBlock tableBlock){
|
||||||
|
mTable.applyTo(tableBlock);
|
||||||
|
}
|
||||||
|
public void fromJson(JSONObject jsonObject){
|
||||||
|
mTable.fromJson(jsonObject);
|
||||||
|
}
|
||||||
public JSONObject toJson(){
|
public JSONObject toJson(){
|
||||||
return mTable.toJson();
|
return mTable.toJson();
|
||||||
}
|
}
|
||||||
@ -30,7 +35,7 @@ public class ResourceIds {
|
|||||||
loadPackageBlock(packageBlock);
|
loadPackageBlock(packageBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void loadPackageBlock(PackageBlock packageBlock){
|
private void loadPackageBlock(PackageBlock packageBlock){
|
||||||
Collection<EntryGroup> entryGroupList = packageBlock.listEntryGroup();
|
Collection<EntryGroup> entryGroupList = packageBlock.listEntryGroup();
|
||||||
String name= packageBlock.getName();
|
String name= packageBlock.getName();
|
||||||
for(EntryGroup entryGroup:entryGroupList){
|
for(EntryGroup entryGroup:entryGroupList){
|
||||||
@ -47,11 +52,39 @@ public class ResourceIds {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Table{
|
public void writeXml(File file) throws IOException {
|
||||||
|
mTable.writeXml(file);
|
||||||
|
}
|
||||||
|
public void writeXml(OutputStream outputStream) throws IOException {
|
||||||
|
mTable.writeXml(outputStream);
|
||||||
|
}
|
||||||
|
public void writeXml(Writer writer) throws IOException {
|
||||||
|
mTable.writeXml(writer);
|
||||||
|
}
|
||||||
|
public void fromXml(File file) throws IOException {
|
||||||
|
mTable.fromXml(file);
|
||||||
|
}
|
||||||
|
public void fromXml(InputStream inputStream) throws IOException {
|
||||||
|
mTable.fromXml(inputStream);
|
||||||
|
}
|
||||||
|
public void fromXml(Reader reader) throws IOException {
|
||||||
|
mTable.fromXml(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Table implements Comparator<Table.Package>{
|
||||||
public final Map<Byte, Package> packageMap;
|
public final Map<Byte, Package> packageMap;
|
||||||
public Table(){
|
public Table(){
|
||||||
this.packageMap = new HashMap<>();
|
this.packageMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
public void applyTo(TableBlock tableBlock){
|
||||||
|
for(PackageBlock packageBlock : tableBlock.listPackages()){
|
||||||
|
Package pkg=getPackage((byte) packageBlock.getId());
|
||||||
|
if(pkg!=null){
|
||||||
|
pkg.applyTo(packageBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tableBlock.refresh();
|
||||||
|
}
|
||||||
public void add(Package pkg){
|
public void add(Package pkg){
|
||||||
Package exist=this.packageMap.get(pkg.id);
|
Package exist=this.packageMap.get(pkg.id);
|
||||||
if(exist!=null){
|
if(exist!=null){
|
||||||
@ -99,6 +132,25 @@ public class ResourceIds {
|
|||||||
}
|
}
|
||||||
return pkg.getEntry(typeId, entryId);
|
return pkg.getEntry(typeId, entryId);
|
||||||
}
|
}
|
||||||
|
public List<Package> listPackages(){
|
||||||
|
List<Package> results=new ArrayList<>(packageMap.values());
|
||||||
|
results.sort(this);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
public List<Package.Type.Entry> listEntries(){
|
||||||
|
List<Package.Type.Entry> results=new ArrayList<>(countEntries());
|
||||||
|
for(Package pkg:packageMap.values()){
|
||||||
|
results.addAll(pkg.listEntries());
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
int countEntries(){
|
||||||
|
int result=0;
|
||||||
|
for(Package pkg:packageMap.values()){
|
||||||
|
result+=pkg.countEntries();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
public JSONObject toJson(){
|
public JSONObject toJson(){
|
||||||
JSONObject jsonObject=new JSONObject();
|
JSONObject jsonObject=new JSONObject();
|
||||||
JSONArray jsonArray=new JSONArray();
|
JSONArray jsonArray=new JSONArray();
|
||||||
@ -108,18 +160,65 @@ public class ResourceIds {
|
|||||||
jsonObject.put("packages", jsonArray);
|
jsonObject.put("packages", jsonArray);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
public static Table fromJson(JSONObject jsonObject){
|
public void fromJson(JSONObject jsonObject){
|
||||||
Table table=new Table();
|
|
||||||
JSONArray jsonArray= jsonObject.optJSONArray("packages");
|
JSONArray jsonArray= jsonObject.optJSONArray("packages");
|
||||||
if(jsonArray!=null){
|
if(jsonArray!=null){
|
||||||
int length= jsonArray.length();
|
int length= jsonArray.length();
|
||||||
for(int i=0;i<length;i++){
|
for(int i=0;i<length;i++){
|
||||||
table.add(Package.fromJson(jsonArray.getJSONObject(i)));
|
this.add(Package.fromJson(jsonArray.getJSONObject(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return table;
|
|
||||||
}
|
}
|
||||||
public static class Package {
|
public void writeXml(File file) throws IOException {
|
||||||
|
File dir=file.getParentFile();
|
||||||
|
if(dir!=null && !dir.exists()){
|
||||||
|
dir.mkdirs();
|
||||||
|
}
|
||||||
|
FileOutputStream outputStream=new FileOutputStream(file);
|
||||||
|
writeXml(outputStream);
|
||||||
|
}
|
||||||
|
public void writeXml(OutputStream outputStream) throws IOException {
|
||||||
|
OutputStreamWriter writer=new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
|
||||||
|
writeXml(writer);
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
public void writeXml(Writer writer) throws IOException {
|
||||||
|
writer.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
|
||||||
|
writer.write("\n<resources>");
|
||||||
|
for(Package pkg:listPackages()){
|
||||||
|
pkg.writeXml(writer);
|
||||||
|
}
|
||||||
|
writer.write("\n</resources>");
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
public void fromXml(File file) throws IOException {
|
||||||
|
FileInputStream inputStream=new FileInputStream(file);
|
||||||
|
fromXml(inputStream);
|
||||||
|
}
|
||||||
|
public void fromXml(InputStream inputStream) throws IOException {
|
||||||
|
InputStreamReader reader=new InputStreamReader(inputStream, StandardCharsets.UTF_8);
|
||||||
|
fromXml(reader);
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
public void fromXml(Reader reader) throws IOException {
|
||||||
|
BufferedReader bufferedReader;
|
||||||
|
if(reader instanceof BufferedReader){
|
||||||
|
bufferedReader=(BufferedReader) reader;
|
||||||
|
}else {
|
||||||
|
bufferedReader=new BufferedReader(reader);
|
||||||
|
}
|
||||||
|
String line;
|
||||||
|
while ((line=bufferedReader.readLine())!=null){
|
||||||
|
add(Package.Type.Entry.fromXml(line));
|
||||||
|
}
|
||||||
|
bufferedReader.close();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int compare(Package pkg1, Package pkg2) {
|
||||||
|
return pkg1.compareTo(pkg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Package implements Comparable<Package>, Comparator<Package.Type>{
|
||||||
public final byte id;
|
public final byte id;
|
||||||
public String name;
|
public String name;
|
||||||
public final Map<Byte, Type> typeMap;
|
public final Map<Byte, Type> typeMap;
|
||||||
@ -127,6 +226,21 @@ public class ResourceIds {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
this.typeMap = new HashMap<>();
|
this.typeMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
public void applyTo(PackageBlock packageBlock){
|
||||||
|
Map<Integer, EntryGroup> map = packageBlock.getEntriesGroupMap();
|
||||||
|
for(Map.Entry<Integer, EntryGroup> entry:map.entrySet()){
|
||||||
|
byte typeId=Table.toTypeId(entry.getKey());
|
||||||
|
Type type=typeMap.get(typeId);
|
||||||
|
if(type==null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EntryGroup entryGroup=entry.getValue();
|
||||||
|
if(entryGroup.getResourceId()==2131427339){
|
||||||
|
String junk="";
|
||||||
|
}
|
||||||
|
type.applyTo(entryGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
public void merge(Package pkg){
|
public void merge(Package pkg){
|
||||||
if(pkg==this||pkg==null){
|
if(pkg==this||pkg==null){
|
||||||
return;
|
return;
|
||||||
@ -193,6 +307,45 @@ public class ResourceIds {
|
|||||||
jsonObject.put("types", jsonArray);
|
jsonObject.put("types", jsonArray);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public int compareTo(Package pkg) {
|
||||||
|
return Integer.compare(id, pkg.id);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int compare(Type t1, Type t2) {
|
||||||
|
return t1.compareTo(t2);
|
||||||
|
}
|
||||||
|
public void writeXml(Writer writer) throws IOException {
|
||||||
|
writer.write("\n");
|
||||||
|
if(this.name!=null){
|
||||||
|
writer.write(" <!-- packageName=\"");
|
||||||
|
writer.write(this.name);
|
||||||
|
writer.write("\" -->");
|
||||||
|
}
|
||||||
|
for(Type type:listTypes()){
|
||||||
|
type.writeXml(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<Package.Type.Entry> listEntries(){
|
||||||
|
List<Package.Type.Entry> results=new ArrayList<>(countEntries());
|
||||||
|
for(Package.Type type:typeMap.values()){
|
||||||
|
results.addAll(type.listEntries());
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
public List<Type> listTypes(){
|
||||||
|
List<Type> results=new ArrayList<>(typeMap.values());
|
||||||
|
results.sort(this);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
int countEntries(){
|
||||||
|
int results=0;
|
||||||
|
for(Type type:typeMap.values()){
|
||||||
|
results+=type.countEntries();
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
@ -221,7 +374,7 @@ public class ResourceIds {
|
|||||||
return pkg;
|
return pkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Type{
|
public static class Type implements Comparable<Type>, Comparator<Type.Entry>{
|
||||||
public final byte id;
|
public final byte id;
|
||||||
public String name;
|
public String name;
|
||||||
public Package mPackage;
|
public Package mPackage;
|
||||||
@ -230,6 +383,15 @@ public class ResourceIds {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
this.entryMap = new HashMap<>();
|
this.entryMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
public void applyTo(EntryGroup entryGroup){
|
||||||
|
Entry entry=entryMap.get(entryGroup.getEntryId());
|
||||||
|
if(entry!=null){
|
||||||
|
entry.applyTo(entryGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public byte getId(){
|
||||||
|
return id;
|
||||||
|
}
|
||||||
public byte getPackageId(){
|
public byte getPackageId(){
|
||||||
if(mPackage!=null){
|
if(mPackage!=null){
|
||||||
return mPackage.id;
|
return mPackage.id;
|
||||||
@ -296,6 +458,28 @@ public class ResourceIds {
|
|||||||
jsonObject.put("entries", jsonArray);
|
jsonObject.put("entries", jsonArray);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
public void writeXml(Writer writer) throws IOException {
|
||||||
|
for(Entry entry:listEntries()){
|
||||||
|
writer.write("\n ");
|
||||||
|
entry.writeXml(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<Entry> listEntries(){
|
||||||
|
List<Entry> results=new ArrayList<>(entryMap.values());
|
||||||
|
results.sort(this);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
int countEntries(){
|
||||||
|
return entryMap.size();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int compareTo(Type type) {
|
||||||
|
return Integer.compare(id, type.id);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int compare(Entry entry1, Entry entry2) {
|
||||||
|
return entry1.compareTo(entry2);
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
@ -345,6 +529,9 @@ public class ResourceIds {
|
|||||||
public Entry(int resourceId, String name){
|
public Entry(int resourceId, String name){
|
||||||
this(resourceId, null, name);
|
this(resourceId, null, name);
|
||||||
}
|
}
|
||||||
|
public void applyTo(EntryGroup entryGroup){
|
||||||
|
entryGroup.renameSpec(this.name);
|
||||||
|
}
|
||||||
public String getTypeName(){
|
public String getTypeName(){
|
||||||
if(this.type!=null){
|
if(this.type!=null){
|
||||||
return this.type.name;
|
return this.type.name;
|
||||||
@ -379,7 +566,7 @@ public class ResourceIds {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Entry entry) {
|
public int compareTo(Entry entry) {
|
||||||
return Integer.compare(getResourceId(), entry.getResourceId());
|
return Integer.compare(getEntryId(), entry.getEntryId());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
@ -399,22 +586,36 @@ public class ResourceIds {
|
|||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
public String toXml(){
|
public String toXml(){
|
||||||
StringBuilder builder=new StringBuilder();
|
StringWriter writer=new StringWriter();
|
||||||
builder.append("<public");
|
try {
|
||||||
builder.append(" id=\"").append(getHexId()).append("\"");
|
writeXml(writer);
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
return writer.toString();
|
||||||
|
}
|
||||||
|
public void writeXml(Writer writer) throws IOException {
|
||||||
|
writer.write("<public");
|
||||||
|
writer.write(" id=\"");
|
||||||
|
writer.write(getHexId());
|
||||||
|
writer.write("\"");
|
||||||
String tn=getTypeName();
|
String tn=getTypeName();
|
||||||
if(tn !=null){
|
if(tn !=null){
|
||||||
builder.append(" type=\"").append(tn).append("\"");
|
writer.append(" type=\"");
|
||||||
|
writer.append(tn);
|
||||||
|
writer.append("\"");
|
||||||
}
|
}
|
||||||
if(name!=null){
|
if(name!=null){
|
||||||
builder.append(" name=\"").append(name).append("\"");
|
writer.write(" name=\"");
|
||||||
|
writer.append(name);
|
||||||
|
writer.append("\"");
|
||||||
}
|
}
|
||||||
builder.append("/>");
|
writer.append("/>");
|
||||||
return builder.toString();
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return toJson().toString();
|
return toXml();
|
||||||
}
|
}
|
||||||
public static Entry fromEntryGroup(EntryGroup entryGroup){
|
public static Entry fromEntryGroup(EntryGroup entryGroup){
|
||||||
return new Entry(entryGroup.getResourceId(),
|
return new Entry(entryGroup.getResourceId(),
|
||||||
@ -466,6 +667,25 @@ public class ResourceIds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
private static short toEntryId(int resourceId){
|
||||||
|
int i=resourceId&0xffff;
|
||||||
|
return (short) i;
|
||||||
|
}
|
||||||
|
static byte toTypeId(int resourceId){
|
||||||
|
int i=resourceId>>16;
|
||||||
|
i=i&0xff;
|
||||||
|
return (byte) i;
|
||||||
|
}
|
||||||
|
static byte toPackageId(int resourceId){
|
||||||
|
int i=resourceId>>24;
|
||||||
|
i=i&0xff;
|
||||||
|
return (byte) i;
|
||||||
|
}
|
||||||
|
static int toResourceId(byte pkgId, byte typeId, short entryId){
|
||||||
|
return (pkgId & 0xff)<<24
|
||||||
|
| (typeId & 0xff)<<16
|
||||||
|
| (entryId & 0xffff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String JSON_FILE_NAME ="resource-ids.json";
|
public static final String JSON_FILE_NAME ="resource-ids.json";
|
||||||
|
@ -3,6 +3,7 @@ package com.reandroid.lib.apk;
|
|||||||
import com.reandroid.archive.FileInputSource;
|
import com.reandroid.archive.FileInputSource;
|
||||||
import com.reandroid.archive.InputSource;
|
import com.reandroid.archive.InputSource;
|
||||||
import com.reandroid.lib.arsc.chunk.TableBlock;
|
import com.reandroid.lib.arsc.chunk.TableBlock;
|
||||||
|
import com.reandroid.lib.json.JSONException;
|
||||||
import com.reandroid.lib.json.JSONObject;
|
import com.reandroid.lib.json.JSONObject;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -28,17 +29,21 @@ public class SingleJsonTableInputSource extends InputSource {
|
|||||||
TableBlock tableBlock = getTableBlock();
|
TableBlock tableBlock = getTableBlock();
|
||||||
return tableBlock.countBytes();
|
return tableBlock.countBytes();
|
||||||
}
|
}
|
||||||
private TableBlock getTableBlock() throws IOException{
|
public TableBlock getTableBlock() throws IOException{
|
||||||
if(mCache!=null){
|
if(mCache!=null){
|
||||||
return mCache;
|
return mCache;
|
||||||
}
|
}
|
||||||
TableBlock tableBlock=newInstance();
|
TableBlock tableBlock=newInstance();
|
||||||
InputStream inputStream=inputSource.openStream();
|
InputStream inputStream=inputSource.openStream();
|
||||||
JSONObject jsonObject=new JSONObject(inputStream);
|
try{
|
||||||
StringPoolBuilder poolBuilder=new StringPoolBuilder();
|
StringPoolBuilder poolBuilder=new StringPoolBuilder();
|
||||||
poolBuilder.build(jsonObject);
|
JSONObject jsonObject=new JSONObject(inputStream);
|
||||||
poolBuilder.apply(tableBlock);
|
poolBuilder.build(jsonObject);
|
||||||
tableBlock.fromJson(jsonObject);
|
poolBuilder.apply(tableBlock);
|
||||||
|
tableBlock.fromJson(jsonObject);
|
||||||
|
}catch (JSONException ex){
|
||||||
|
throw new IOException(inputSource.getAlias()+": "+ex.getMessage());
|
||||||
|
}
|
||||||
mCache=tableBlock;
|
mCache=tableBlock;
|
||||||
return tableBlock;
|
return tableBlock;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ public class SplitJsonTableInputSource extends InputSource {
|
|||||||
TableBlock tableBlock = getTableBlock();
|
TableBlock tableBlock = getTableBlock();
|
||||||
return tableBlock.countBytes();
|
return tableBlock.countBytes();
|
||||||
}
|
}
|
||||||
private TableBlock getTableBlock() throws IOException {
|
public TableBlock getTableBlock() throws IOException {
|
||||||
if(mCache!=null){
|
if(mCache!=null){
|
||||||
return mCache;
|
return mCache;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import com.reandroid.lib.arsc.chunk.TableBlock;
|
|||||||
import com.reandroid.lib.arsc.pool.SpecStringPool;
|
import com.reandroid.lib.arsc.pool.SpecStringPool;
|
||||||
import com.reandroid.lib.arsc.pool.TableStringPool;
|
import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.lib.json.JSONArray;
|
import com.reandroid.lib.json.JSONArray;
|
||||||
|
import com.reandroid.lib.json.JSONException;
|
||||||
import com.reandroid.lib.json.JSONObject;
|
import com.reandroid.lib.json.JSONObject;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -34,7 +35,7 @@ public class StringPoolBuilder {
|
|||||||
stringPool.refresh();
|
stringPool.refresh();
|
||||||
}
|
}
|
||||||
private void applySpecString(SpecStringPool stringPool){
|
private void applySpecString(SpecStringPool stringPool){
|
||||||
byte pkgId= (byte) stringPool.getPackageBlock().getPackageId();
|
byte pkgId= (byte) stringPool.getPackageBlock().getId();
|
||||||
stringPool.addStrings(getSpecString(pkgId));
|
stringPool.addStrings(getSpecString(pkgId));
|
||||||
stringPool.refresh();
|
stringPool.refresh();
|
||||||
}
|
}
|
||||||
@ -54,9 +55,13 @@ public class StringPoolBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void scanFile(File jsonFile) throws IOException {
|
public void scanFile(File jsonFile) throws IOException {
|
||||||
FileInputStream inputStream=new FileInputStream(jsonFile);
|
try{
|
||||||
JSONObject jsonObject=new JSONObject(inputStream);
|
FileInputStream inputStream=new FileInputStream(jsonFile);
|
||||||
build(jsonObject);
|
JSONObject jsonObject=new JSONObject(inputStream);
|
||||||
|
build(jsonObject);
|
||||||
|
}catch (JSONException ex){
|
||||||
|
throw new IOException(jsonFile+": "+ex.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void build(JSONObject jsonObject){
|
public void build(JSONObject jsonObject){
|
||||||
scan(jsonObject);
|
scan(jsonObject);
|
||||||
|
@ -26,7 +26,7 @@ public class TableBlockJson {
|
|||||||
}
|
}
|
||||||
File infoFile=new File(pkgDir, PackageBlock.JSON_FILE_NAME);
|
File infoFile=new File(pkgDir, PackageBlock.JSON_FILE_NAME);
|
||||||
JSONObject jsonObject=new JSONObject();
|
JSONObject jsonObject=new JSONObject();
|
||||||
jsonObject.put(PackageBlock.NAME_package_id, packageBlock.getPackageId());
|
jsonObject.put(PackageBlock.NAME_package_id, packageBlock.getId());
|
||||||
jsonObject.put(PackageBlock.NAME_package_name, packageBlock.getPackageName());
|
jsonObject.put(PackageBlock.NAME_package_name, packageBlock.getPackageName());
|
||||||
jsonObject.write(infoFile);
|
jsonObject.write(infoFile);
|
||||||
for(SpecTypePair specTypePair: packageBlock.listAllSpecTypePair()){
|
for(SpecTypePair specTypePair: packageBlock.listAllSpecTypePair()){
|
||||||
@ -51,7 +51,7 @@ public class TableBlockJson {
|
|||||||
}
|
}
|
||||||
private String getDirName(PackageBlock packageBlock){
|
private String getDirName(PackageBlock packageBlock){
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(String.format("0x%02x", packageBlock.getPackageId()));
|
builder.append(String.format("0x%02x", packageBlock.getId()));
|
||||||
String name= packageBlock.getPackageName();
|
String name= packageBlock.getPackageName();
|
||||||
if(name!=null){
|
if(name!=null){
|
||||||
builder.append('-');
|
builder.append('-');
|
||||||
|
@ -35,6 +35,10 @@ public abstract class BaseChunk extends ExpandableBlockContainer {
|
|||||||
@Override
|
@Override
|
||||||
public void onReadBytes(BlockReader reader) throws IOException {
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
HeaderBlock headerBlock=reader.readHeaderBlock();
|
HeaderBlock headerBlock=reader.readHeaderBlock();
|
||||||
|
ChunkType chunkType = headerBlock.getChunkType();
|
||||||
|
if(chunkType==null || chunkType==ChunkType.NULL){
|
||||||
|
throw new IOException("Invalid chunk: "+headerBlock);
|
||||||
|
}
|
||||||
BlockReader chunkReader=reader.create(reader.getPosition(), headerBlock.getChunkSize());
|
BlockReader chunkReader=reader.create(reader.getPosition(), headerBlock.getChunkSize());
|
||||||
super.onReadBytes(chunkReader);
|
super.onReadBytes(chunkReader);
|
||||||
reader.offset(headerBlock.getChunkSize());
|
reader.offset(headerBlock.getChunkSize());
|
||||||
|
@ -125,12 +125,6 @@ public class PackageBlock extends BaseChunk implements BlockLoad, JSONConvert<JS
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public int getPackageId(){
|
|
||||||
return mPackageId.get();
|
|
||||||
}
|
|
||||||
public int setPackageId(){
|
|
||||||
return mPackageId.get();
|
|
||||||
}
|
|
||||||
public String getPackageName(){
|
public String getPackageName(){
|
||||||
return mPackageName.get();
|
return mPackageName.get();
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,11 @@ public class TableBlock extends BaseChunk implements JSONConvert<JSONObject> {
|
|||||||
protected void onChunkRefreshed() {
|
protected void onChunkRefreshed() {
|
||||||
refreshPackageCount();
|
refreshPackageCount();
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
|
super.onReadBytes(reader);
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
|
||||||
public void readBytes(File file) throws IOException{
|
public void readBytes(File file) throws IOException{
|
||||||
BlockReader reader=new BlockReader(file);
|
BlockReader reader=new BlockReader(file);
|
||||||
|
@ -39,13 +39,12 @@ public class ResXmlBlock extends BaseChunk implements JSONConvert<JSONObject> {
|
|||||||
if(headerBlock==null){
|
if(headerBlock==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BlockReader chunkReader=reader.create(reader.getPosition(), headerBlock.getChunkSize());
|
|
||||||
ChunkType chunkType=headerBlock.getChunkType();
|
ChunkType chunkType=headerBlock.getChunkType();
|
||||||
if(chunkType==ChunkType.XML){
|
if(chunkType!=ChunkType.XML){
|
||||||
getHeaderBlock().readBytes(chunkReader);
|
throw new IOException("Not ResXmlBlock: "+headerBlock);
|
||||||
}else {
|
|
||||||
throw new IOException("Not ResXmlBlock: "+reader+", Header="+headerBlock);
|
|
||||||
}
|
}
|
||||||
|
BlockReader chunkReader=reader.create(reader.getPosition(), headerBlock.getChunkSize());
|
||||||
|
getHeaderBlock().readBytes(chunkReader);
|
||||||
while (chunkReader.isAvailable()){
|
while (chunkReader.isAvailable()){
|
||||||
boolean readOk=readNext(chunkReader);
|
boolean readOk=readNext(chunkReader);
|
||||||
if(!readOk){
|
if(!readOk){
|
||||||
|
@ -37,6 +37,9 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
|||||||
SpecString specString=specStringPool.getOrCreate(name);
|
SpecString specString=specStringPool.getOrCreate(name);
|
||||||
return renameSpec(specString.getIndex());
|
return renameSpec(specString.getIndex());
|
||||||
}
|
}
|
||||||
|
public short getEntryId(){
|
||||||
|
return (short) (getResourceId() & 0xffff);
|
||||||
|
}
|
||||||
private boolean isAllSameSpec(){
|
private boolean isAllSameSpec(){
|
||||||
EntryBlock first=null;
|
EntryBlock first=null;
|
||||||
for(EntryBlock entryBlock:listItems()){
|
for(EntryBlock entryBlock:listItems()){
|
||||||
|
@ -272,7 +272,7 @@ public class FrameworkTable extends TableBlock {
|
|||||||
builder.append("\n PACKAGES=").append(allPkg.size());
|
builder.append("\n PACKAGES=").append(allPkg.size());
|
||||||
for(PackageBlock packageBlock:allPkg){
|
for(PackageBlock packageBlock:allPkg){
|
||||||
builder.append("\n ");
|
builder.append("\n ");
|
||||||
builder.append(String.format("0x%02x", packageBlock.getPackageId()));
|
builder.append(String.format("0x%02x", packageBlock.getId()));
|
||||||
builder.append(":").append(packageBlock.getPackageName());
|
builder.append(":").append(packageBlock.getPackageName());
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
|
@ -237,6 +237,13 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad, JSONCon
|
|||||||
setCountryIn0(bts[0]);
|
setCountryIn0(bts[0]);
|
||||||
setCountryIn1(bts[1]);
|
setCountryIn1(bts[1]);
|
||||||
}
|
}
|
||||||
|
public void setRegion(String region){
|
||||||
|
char[] chs=new char[2];
|
||||||
|
if(region!=null){
|
||||||
|
chs=region.toCharArray();
|
||||||
|
}
|
||||||
|
setRegion(chs);
|
||||||
|
}
|
||||||
public void setOrientation(byte b){
|
public void setOrientation(byte b){
|
||||||
if(getConfigSize()<SIZE_16){
|
if(getConfigSize()<SIZE_16){
|
||||||
if(b==0){
|
if(b==0){
|
||||||
@ -725,6 +732,7 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad, JSONCon
|
|||||||
setMcc((short) json.optInt(NAME_mcc));
|
setMcc((short) json.optInt(NAME_mcc));
|
||||||
setMnc((short) json.optInt(NAME_mnc));
|
setMnc((short) json.optInt(NAME_mnc));
|
||||||
setLanguage(json.optString(NAME_language));
|
setLanguage(json.optString(NAME_language));
|
||||||
|
setRegion(json.optString(NAME_region));
|
||||||
setOrientation(Orientation.fromName(json.optString(NAME_orientation)));
|
setOrientation(Orientation.fromName(json.optString(NAME_orientation)));
|
||||||
setTouchscreen(Touchscreen.fromName(json.optString(NAME_touchscreen)));
|
setTouchscreen(Touchscreen.fromName(json.optString(NAME_touchscreen)));
|
||||||
setDensity(json.optString(NAME_density));
|
setDensity(json.optString(NAME_density));
|
||||||
@ -742,6 +750,7 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad, JSONCon
|
|||||||
setScreenHeightDp((short) json.optInt(NAME_screenHeightDp));
|
setScreenHeightDp((short) json.optInt(NAME_screenHeightDp));
|
||||||
|
|
||||||
trimToSize(SIZE_48);
|
trimToSize(SIZE_48);
|
||||||
|
valuesChanged();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int hashCode(){
|
public int hashCode(){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user