mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-01 06:34:26 +02:00
V1.0.3 (to/from json convert)
This commit is contained in:
parent
8cbbc2fdad
commit
625baa03f1
@ -23,6 +23,7 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
compile(files("$rootProject.projectDir/libs/ArchiveUtil.jar"))
|
||||
compile(files("$rootProject.projectDir/libs/json.jar"))
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
Binary file not shown.
BIN
libs/json.jar
Executable file
BIN
libs/json.jar
Executable file
Binary file not shown.
10
src/main/java/com/reandroid/lib/apk/ApkEntry.java
Normal file
10
src/main/java/com/reandroid/lib/apk/ApkEntry.java
Normal file
@ -0,0 +1,10 @@
|
||||
package com.reandroid.lib.apk;
|
||||
|
||||
import com.reandroid.archive.InputSource;
|
||||
|
||||
public class ApkEntry {
|
||||
private InputSource mInputSource;
|
||||
public ApkEntry(InputSource inputSource){
|
||||
this.mInputSource=inputSource;
|
||||
}
|
||||
}
|
170
src/main/java/com/reandroid/lib/apk/ApkModule.java
Normal file
170
src/main/java/com/reandroid/lib/apk/ApkModule.java
Normal file
@ -0,0 +1,170 @@
|
||||
package com.reandroid.lib.apk;
|
||||
|
||||
import com.reandroid.archive.APKArchive;
|
||||
import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.lib.arsc.array.PackageArray;
|
||||
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.lib.arsc.chunk.TableBlock;
|
||||
import com.reandroid.lib.arsc.chunk.xml.AndroidManifestBlock;
|
||||
import com.reandroid.lib.arsc.group.StringGroup;
|
||||
import com.reandroid.lib.arsc.item.TableString;
|
||||
import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
public class ApkModule {
|
||||
private final APKArchive apkArchive;
|
||||
private boolean loadDefaultFramework = true;
|
||||
private TableBlock mTableBlock;
|
||||
private AndroidManifestBlock mManifestBlock;
|
||||
private ApkModule(APKArchive apkArchive){
|
||||
this.apkArchive=apkArchive;
|
||||
}
|
||||
public void writeTo(File file) throws IOException {
|
||||
APKArchive archive=getApkArchive();
|
||||
archive.writeApk(file);
|
||||
}
|
||||
public void removeDir(String dirName){
|
||||
getApkArchive().removeDir(dirName);
|
||||
}
|
||||
public void setResourcesRootDir(String dirName) 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=ApkUtil.replaceRootDir(path, dirName);
|
||||
if(existPaths.contains(pathNew)){
|
||||
continue;
|
||||
}
|
||||
existPaths.remove(path);
|
||||
existPaths.add(pathNew);
|
||||
resFile.setFilePath(pathNew);
|
||||
}
|
||||
TableStringPool stringPool= getTableBlock().getTableStringPool();
|
||||
stringPool.refreshUniqueIdMap();
|
||||
}
|
||||
public List<ResFile> listResFiles() throws IOException {
|
||||
List<ResFile> results=new ArrayList<>();
|
||||
TableBlock tableBlock=getTableBlock();
|
||||
TableStringPool stringPool= tableBlock.getTableStringPool();
|
||||
for(InputSource inputSource:getApkArchive().listInputSources()){
|
||||
String name=inputSource.getAlias();
|
||||
StringGroup<TableString> groupTableString = stringPool.get(name);
|
||||
if(groupTableString==null){
|
||||
continue;
|
||||
}
|
||||
for(TableString tableString:groupTableString.listItems()){
|
||||
List<EntryBlock> entryBlockList = tableString.listReferencedEntries();
|
||||
ResFile resFile=new ResFile(inputSource, entryBlockList);
|
||||
results.add(resFile);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
public String getPackageName() throws IOException {
|
||||
if(hasAndroidManifestBlock()){
|
||||
return getAndroidManifestBlock().getPackageName();
|
||||
}
|
||||
if(!hasTableBlock()){
|
||||
return null;
|
||||
}
|
||||
TableBlock tableBlock=getTableBlock();
|
||||
PackageArray pkgArray = tableBlock.getPackageArray();
|
||||
PackageBlock pkg = pkgArray.get(0);
|
||||
if(pkg==null){
|
||||
return null;
|
||||
}
|
||||
return pkg.getPackageName();
|
||||
}
|
||||
public void setPackageName(String name) throws IOException {
|
||||
String old=getPackageName();
|
||||
if(hasAndroidManifestBlock()){
|
||||
getAndroidManifestBlock().setPackageName(name);
|
||||
}
|
||||
if(!hasTableBlock()){
|
||||
return;
|
||||
}
|
||||
TableBlock tableBlock=getTableBlock();
|
||||
PackageArray pkgArray = tableBlock.getPackageArray();
|
||||
for(PackageBlock pkg:pkgArray.listItems()){
|
||||
if(pkgArray.childesCount()==1){
|
||||
pkg.setPackageName(name);
|
||||
continue;
|
||||
}
|
||||
String pkgName=pkg.getPackageName();
|
||||
if(pkgName.startsWith(old)){
|
||||
pkgName=pkgName.replace(old, name);
|
||||
pkg.setPackageName(pkgName);
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean hasAndroidManifestBlock(){
|
||||
return mManifestBlock!=null
|
||||
|| getApkArchive().getInputSource(AndroidManifestBlock.FILE_NAME)!=null;
|
||||
}
|
||||
public AndroidManifestBlock getAndroidManifestBlock() throws IOException {
|
||||
if(mManifestBlock!=null){
|
||||
return mManifestBlock;
|
||||
}
|
||||
APKArchive archive=getApkArchive();
|
||||
InputSource inputSource = archive.getInputSource(AndroidManifestBlock.FILE_NAME);
|
||||
if(inputSource==null){
|
||||
throw new IOException("Entry not found: "+AndroidManifestBlock.FILE_NAME);
|
||||
}
|
||||
InputStream inputStream = inputSource.openStream();
|
||||
AndroidManifestBlock manifestBlock=AndroidManifestBlock.load(inputStream);
|
||||
inputStream.close();
|
||||
BlockInputSource<AndroidManifestBlock> blockInputSource=new BlockInputSource<>(inputSource.getName(),manifestBlock);
|
||||
blockInputSource.setSort(inputSource.getSort());
|
||||
blockInputSource.setMethod(inputSource.getMethod());
|
||||
archive.add(blockInputSource);
|
||||
mManifestBlock=manifestBlock;
|
||||
return mManifestBlock;
|
||||
}
|
||||
public boolean hasTableBlock(){
|
||||
return mTableBlock!=null
|
||||
|| getApkArchive().getInputSource(TableBlock.FILE_NAME)!=null;
|
||||
}
|
||||
public TableBlock getTableBlock() throws IOException {
|
||||
if(mTableBlock!=null){
|
||||
return mTableBlock;
|
||||
}
|
||||
APKArchive archive=getApkArchive();
|
||||
InputSource inputSource = archive.getInputSource(TableBlock.FILE_NAME);
|
||||
if(inputSource==null){
|
||||
throw new IOException("Entry not found: "+TableBlock.FILE_NAME);
|
||||
}
|
||||
TableBlock tableBlock;
|
||||
InputStream inputStream = inputSource.openStream();
|
||||
if(loadDefaultFramework){
|
||||
tableBlock=TableBlock.loadWithAndroidFramework(inputStream);
|
||||
}else {
|
||||
tableBlock=TableBlock.load(inputStream);
|
||||
}
|
||||
inputStream.close();
|
||||
mTableBlock=tableBlock;
|
||||
BlockInputSource<TableBlock> blockInputSource=new BlockInputSource<>(inputSource.getName(),tableBlock);
|
||||
blockInputSource.setMethod(inputSource.getMethod());
|
||||
blockInputSource.setSort(inputSource.getSort());
|
||||
archive.add(blockInputSource);
|
||||
return mTableBlock;
|
||||
}
|
||||
public APKArchive getApkArchive() {
|
||||
return apkArchive;
|
||||
}
|
||||
public void setLoadDefaultFramework(boolean loadDefaultFramework) {
|
||||
this.loadDefaultFramework = loadDefaultFramework;
|
||||
}
|
||||
public static ApkModule loadApkFile(File apkFile) throws IOException {
|
||||
APKArchive archive=APKArchive.loadZippedApk(apkFile);
|
||||
return new ApkModule(archive);
|
||||
}
|
||||
}
|
15
src/main/java/com/reandroid/lib/apk/ApkUtil.java
Normal file
15
src/main/java/com/reandroid/lib/apk/ApkUtil.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.reandroid.lib.apk;
|
||||
|
||||
public class ApkUtil {
|
||||
public static String replaceRootDir(String path, String dirName){
|
||||
int i=path.indexOf('/')+1;
|
||||
path=path.substring(i);
|
||||
if(dirName != null && dirName.length()>0){
|
||||
if(!dirName.endsWith("/")){
|
||||
dirName=dirName+"/";
|
||||
}
|
||||
path=dirName+path;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
24
src/main/java/com/reandroid/lib/apk/BlockInputSource.java
Normal file
24
src/main/java/com/reandroid/lib/apk/BlockInputSource.java
Normal file
@ -0,0 +1,24 @@
|
||||
package com.reandroid.lib.apk;
|
||||
|
||||
import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.lib.arsc.chunk.BaseChunk;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class BlockInputSource<T extends BaseChunk> extends InputSource {
|
||||
private final T mBlock;
|
||||
public BlockInputSource(String name, T block) {
|
||||
super(name);
|
||||
this.mBlock=block;
|
||||
}
|
||||
public T getBlock() {
|
||||
return mBlock;
|
||||
}
|
||||
@Override
|
||||
public InputStream openStream(){
|
||||
T block=getBlock();
|
||||
block.refresh();
|
||||
return new ByteArrayInputStream(block.getBytes());
|
||||
}
|
||||
}
|
33
src/main/java/com/reandroid/lib/apk/ResFile.java
Normal file
33
src/main/java/com/reandroid/lib/apk/ResFile.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.reandroid.lib.apk;
|
||||
|
||||
import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ResFile {
|
||||
private final List<EntryBlock> entryBlockList;
|
||||
private final InputSource inputSource;
|
||||
public ResFile(InputSource inputSource, List<EntryBlock> entryBlockList){
|
||||
this.inputSource=inputSource;
|
||||
this.entryBlockList=entryBlockList;
|
||||
}
|
||||
public String getFilePath(){
|
||||
return getInputSource().getAlias();
|
||||
}
|
||||
public void setFilePath(String filePath){
|
||||
getInputSource().setAlias(filePath);
|
||||
for(EntryBlock entryBlock:entryBlockList){
|
||||
entryBlock.getValueAsTableString().set(filePath);
|
||||
}
|
||||
}
|
||||
public InputSource getInputSource() {
|
||||
return inputSource;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return getFilePath();
|
||||
}
|
||||
|
||||
public static final String DIR_NAME="res";
|
||||
}
|
@ -3,9 +3,12 @@ package com.reandroid.lib.arsc.array;
|
||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
||||
public class EntryBlockArray extends OffsetBlockArray<EntryBlock> {
|
||||
public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JsonItem<JSONArray> {
|
||||
public EntryBlockArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){
|
||||
super(offsets, itemCount, itemStart);
|
||||
}
|
||||
@ -38,4 +41,42 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> {
|
||||
return new EntryBlock[len];
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int index=0;
|
||||
for(EntryBlock entryBlock:listItems()){
|
||||
JSONObject childObject = entryBlock.toJson();
|
||||
if(childObject==null){
|
||||
continue;
|
||||
}
|
||||
childObject.put(NAME_id, entryBlock.getIndex());
|
||||
jsonArray.put(index, childObject);
|
||||
index++;
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
clearChildes();
|
||||
int length=json.length();
|
||||
ensureSize(length);
|
||||
for(int i=0;i<length;i++){
|
||||
JSONObject jsonObject= json.getJSONObject(i);
|
||||
if(jsonObject==null){
|
||||
continue;
|
||||
}
|
||||
int id=jsonObject.getInt(NAME_id);
|
||||
ensureSize(id+1);
|
||||
EntryBlock entryBlock=get(id);
|
||||
entryBlock.fromJson(jsonObject);
|
||||
}
|
||||
refreshCountAndStart();
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return toJson().toString(4);
|
||||
}
|
||||
private static final String NAME_id="id";
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
package com.reandroid.lib.arsc.array;
|
||||
|
||||
import com.reandroid.lib.arsc.base.BlockArray;
|
||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.value.LibraryInfo;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class LibraryInfoArray extends BlockArray<LibraryInfo> {
|
||||
public class LibraryInfoArray extends BlockArray<LibraryInfo> implements JsonItem<JSONArray> {
|
||||
private final IntegerItem mInfoCount;
|
||||
public LibraryInfoArray(IntegerItem infoCount){
|
||||
this.mInfoCount=infoCount;
|
||||
@ -30,4 +34,32 @@ public class LibraryInfoArray extends BlockArray<LibraryInfo> {
|
||||
setChildesCount(mInfoCount.get());
|
||||
super.onReadBytes(reader);
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int i=0;
|
||||
for(LibraryInfo libraryInfo:listItems()){
|
||||
JSONObject jsonObject= libraryInfo.toJson();
|
||||
if(jsonObject==null){
|
||||
continue;
|
||||
}
|
||||
jsonArray.put(i, jsonObject);
|
||||
i++;
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
clearChildes();
|
||||
if(json==null){
|
||||
return;
|
||||
}
|
||||
int length= json.length();
|
||||
ensureSize(length);
|
||||
for (int i=0;i<length;i++){
|
||||
JSONObject jsonObject=json.getJSONObject(i);
|
||||
LibraryInfo libraryInfo=get(i);
|
||||
libraryInfo.fromJson(jsonObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,18 @@ package com.reandroid.lib.arsc.array;
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.base.BlockArray;
|
||||
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||
import com.reandroid.lib.arsc.io.BlockLoad;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class PackageArray extends BlockArray<PackageBlock> implements BlockLoad {
|
||||
public class PackageArray extends BlockArray<PackageBlock> implements BlockLoad, JsonItem<JSONArray> {
|
||||
private final IntegerItem mPackageCount;
|
||||
public PackageArray(IntegerItem packageCount){
|
||||
this.mPackageCount=packageCount;
|
||||
@ -60,4 +64,29 @@ public class PackageArray extends BlockArray<PackageBlock> implements BlockLoad
|
||||
setChildesCount(mPackageCount.get());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int i=0;
|
||||
for(PackageBlock packageBlock:listItems()){
|
||||
JSONObject jsonObject= packageBlock.toJson();
|
||||
if(jsonObject==null){
|
||||
continue;
|
||||
}
|
||||
jsonArray.put(i, jsonObject);
|
||||
i++;
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
int length= json.length();
|
||||
clearChildes();
|
||||
ensureSize(length);
|
||||
for (int i=0;i<length;i++){
|
||||
JSONObject jsonObject=json.getJSONObject(i);
|
||||
PackageBlock packageBlock=get(i);
|
||||
packageBlock.fromJson(jsonObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ package com.reandroid.lib.arsc.array;
|
||||
|
||||
import com.reandroid.lib.arsc.base.BlockArray;
|
||||
import com.reandroid.lib.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
|
||||
public class ResValueBagItemArray extends BlockArray<ResValueBagItem> {
|
||||
public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements JsonItem<JSONArray> {
|
||||
public ResValueBagItemArray(){
|
||||
super();
|
||||
}
|
||||
@ -21,4 +23,28 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> {
|
||||
protected void onRefreshed() {
|
||||
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
if(isNull()){
|
||||
return jsonArray;
|
||||
}
|
||||
ResValueBagItem[] childes = getChildes();
|
||||
for(int i=0;i<childes.length;i++){
|
||||
jsonArray.put(i, childes[i].toJson());
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json){
|
||||
clearChildes();
|
||||
if(json==null){
|
||||
return;
|
||||
}
|
||||
int count=json.length();
|
||||
ensureSize(count);
|
||||
for(int i=0;i<count;i++){
|
||||
get(i).fromJson(json.getJSONObject(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,9 @@ import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.chunk.xml.ResXmlAttribute;
|
||||
import com.reandroid.lib.arsc.item.ShortItem;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -14,7 +17,8 @@ import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class ResXmlAttributeArray extends BlockArray<ResXmlAttribute> implements Comparator<ResXmlAttribute> {
|
||||
public class ResXmlAttributeArray extends BlockArray<ResXmlAttribute>
|
||||
implements Comparator<ResXmlAttribute>, JsonItem<JSONArray> {
|
||||
private final HeaderBlock mHeaderBlock;
|
||||
private final ShortItem mAttributeStart;
|
||||
private final ShortItem mAttributeCount;
|
||||
@ -70,4 +74,27 @@ public class ResXmlAttributeArray extends BlockArray<ResXmlAttribute> implements
|
||||
public int compare(ResXmlAttribute attr1, ResXmlAttribute attr2) {
|
||||
return attr1.compareTo(attr2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int i=0;
|
||||
for(ResXmlAttribute attr:listItems()){
|
||||
JSONObject jsonObject = attr.toJson();
|
||||
jsonArray.put(i, jsonObject);
|
||||
i++;
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
clearChildes();
|
||||
int length= json.length();
|
||||
ensureSize(length);
|
||||
for(int i=0;i<length;i++){
|
||||
ResXmlAttribute attribute=get(i);
|
||||
JSONObject jsonObject= json.getJSONObject(i);
|
||||
attribute.fromJson(jsonObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,15 @@ import com.reandroid.lib.arsc.base.BlockArray;
|
||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.ResXmlID;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ResXmlIDArray extends BlockArray<ResXmlID> {
|
||||
public class ResXmlIDArray extends BlockArray<ResXmlID> implements JsonItem<JSONArray> {
|
||||
private final HeaderBlock mHeaderBlock;
|
||||
private final Map<Integer, ResXmlID> mResIdMap;
|
||||
private boolean mUpdated;
|
||||
@ -86,4 +89,23 @@ public class ResXmlIDArray extends BlockArray<ResXmlID> {
|
||||
count=count/4;
|
||||
return count;
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
if(childesCount()==0){
|
||||
return null;
|
||||
}
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int i=0;
|
||||
for(ResXmlID xmlID:listItems()){
|
||||
JSONObject jsonObject=xmlID.toJson();
|
||||
jsonArray.put(i,jsonObject);
|
||||
i++;
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
//TODO
|
||||
throw new IllegalArgumentException("Not implemented yet");
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,13 @@ import com.reandroid.lib.arsc.base.BlockArray;
|
||||
import com.reandroid.lib.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SpecTypePairArray extends BlockArray<SpecTypePair> {
|
||||
public class SpecTypePairArray extends BlockArray<SpecTypePair> implements JsonItem<JSONArray> {
|
||||
public SpecTypePairArray(){
|
||||
super();
|
||||
}
|
||||
@ -140,4 +143,29 @@ public class SpecTypePairArray extends BlockArray<SpecTypePair> {
|
||||
}
|
||||
return results;
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int i=0;
|
||||
for(SpecTypePair specTypePair:listItems()){
|
||||
JSONObject jsonObject= specTypePair.toJson();
|
||||
if(jsonObject==null){
|
||||
continue;
|
||||
}
|
||||
jsonArray.put(i, jsonObject);
|
||||
i++;
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
int length= json.length();
|
||||
clearChildes();
|
||||
ensureSize(length);
|
||||
for (int i=0;i<length;i++){
|
||||
JSONObject jsonObject=json.getJSONObject(i);
|
||||
SpecTypePair specTypePair=get(i);
|
||||
specTypePair.fromJson(jsonObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,14 @@ package com.reandroid.lib.arsc.array;
|
||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.StringItem;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class StringArray<T extends StringItem> extends OffsetBlockArray<T>{
|
||||
public abstract class StringArray<T extends StringItem> extends OffsetBlockArray<T> implements JsonItem<JSONArray> {
|
||||
private boolean mUtf8;
|
||||
|
||||
public StringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) {
|
||||
@ -50,5 +53,48 @@ public abstract class StringArray<T extends StringItem> extends OffsetBlockArray
|
||||
protected void refreshChildes(){
|
||||
// Not required
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
return toJson(true);
|
||||
}
|
||||
public JSONArray toJson(boolean styledOnly) {
|
||||
if(childesCount()==0){
|
||||
return null;
|
||||
}
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int i=0;
|
||||
for(T item:listItems()){
|
||||
if(item.isNull()){
|
||||
continue;
|
||||
}
|
||||
if(styledOnly && !item.hasStyle()){
|
||||
continue;
|
||||
}
|
||||
JSONObject jsonObject= item.toJson();
|
||||
if(jsonObject==null){
|
||||
continue;
|
||||
}
|
||||
jsonArray.put(i, jsonObject);
|
||||
i++;
|
||||
}
|
||||
if(i==0){
|
||||
return null;
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
clearChildes();
|
||||
if(json==null){
|
||||
return;
|
||||
}
|
||||
int length = json.length();
|
||||
ensureSize(length);
|
||||
for(int i=0; i<length;i++){
|
||||
T item=get(i);
|
||||
JSONObject jsonObject = json.getJSONObject(i);
|
||||
item.fromJson(jsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,10 +5,12 @@ import com.reandroid.lib.arsc.item.ByteArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.StyleItem;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class StyleArray extends OffsetBlockArray<StyleItem> {
|
||||
public class StyleArray extends OffsetBlockArray<StyleItem> implements JsonItem<JSONArray> {
|
||||
public StyleArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart) {
|
||||
super(offsets, itemCount, itemStart);
|
||||
setEndBytes(END_BYTE);
|
||||
@ -51,5 +53,21 @@ public class StyleArray extends OffsetBlockArray<StyleItem> {
|
||||
public StyleItem[] newInstance(int len) {
|
||||
return new StyleItem[len];
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
if(childesCount()==0){
|
||||
return null;
|
||||
}
|
||||
int i=0;
|
||||
for(StyleItem styleItem:listItems()){
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
|
||||
}
|
||||
private static final byte END_BYTE= (byte) 0xFF;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.reandroid.lib.arsc.array;
|
||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.TableString;
|
||||
import org.json.JSONArray;
|
||||
|
||||
public class TableStringArray extends StringArray<TableString> {
|
||||
public TableStringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) {
|
||||
|
@ -10,13 +10,16 @@ import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.TypeString;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.arsc.value.ResConfig;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TypeBlockArray extends BlockArray<TypeBlock> {
|
||||
public class TypeBlockArray extends BlockArray<TypeBlock> implements JsonItem<JSONArray> {
|
||||
private byte mTypeId;
|
||||
public TypeBlockArray(){
|
||||
super();
|
||||
@ -232,4 +235,29 @@ public class TypeBlockArray extends BlockArray<TypeBlock> {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int i=0;
|
||||
for(TypeBlock typeBlock:listItems()){
|
||||
JSONObject jsonObject= typeBlock.toJson();
|
||||
if(jsonObject==null){
|
||||
continue;
|
||||
}
|
||||
jsonArray.put(i, jsonObject);
|
||||
i++;
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
int length= json.length();
|
||||
clearChildes();
|
||||
ensureSize(length);
|
||||
for (int i=0;i<length;i++){
|
||||
JSONObject jsonObject=json.getJSONObject(i);
|
||||
TypeBlock typeBlock=get(i);
|
||||
typeBlock.fromJson(jsonObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,15 @@ abstract class BaseTypeBlock extends BaseChunk {
|
||||
public void setTypeId(byte id){
|
||||
mTypeId.set(id);
|
||||
}
|
||||
public void setTypeName(String name){
|
||||
TypeStringPool typeStringPool=getTypeStringPool();
|
||||
byte id=getTypeId();
|
||||
TypeString typeString=typeStringPool.getById(id);
|
||||
if(typeString==null){
|
||||
typeString=typeStringPool.getOrCreate(id, name);
|
||||
}
|
||||
typeString.set(name);
|
||||
}
|
||||
public void setEntryCount(int count){
|
||||
if(count == mEntryCount.get()){
|
||||
return;
|
||||
|
@ -18,18 +18,14 @@ public class LibraryBlock extends BaseChunk {
|
||||
addToHeader(mLibCount);
|
||||
addChild(mLibraryInfoArray);
|
||||
}
|
||||
public LibraryInfo[] getAllInfo(){
|
||||
return mLibraryInfoArray.getChildes();
|
||||
public LibraryInfoArray getLibraryInfoArray(){
|
||||
return mLibraryInfoArray;
|
||||
}
|
||||
public void addLibraryInfo(LibraryBlock libraryBlock){
|
||||
if(libraryBlock==null){
|
||||
return;
|
||||
}
|
||||
LibraryInfo[] allInfo=libraryBlock.getAllInfo();
|
||||
if (allInfo==null){
|
||||
return;
|
||||
}
|
||||
for(LibraryInfo info:allInfo){
|
||||
for(LibraryInfo info:libraryBlock.getLibraryInfoArray().listItems()){
|
||||
addLibraryInfo(info);
|
||||
}
|
||||
}
|
||||
@ -37,11 +33,11 @@ public class LibraryBlock extends BaseChunk {
|
||||
if(info==null){
|
||||
return;
|
||||
}
|
||||
mLibraryInfoArray.add(info);
|
||||
getLibraryInfoArray().add(info);
|
||||
mLibCount.set(mLibraryInfoArray.childesCount());
|
||||
}
|
||||
public Collection<LibraryInfo> listLibraryInfo(){
|
||||
return mLibraryInfoArray.listItems();
|
||||
return getLibraryInfoArray().listItems();
|
||||
}
|
||||
@Override
|
||||
public boolean isNull(){
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.reandroid.lib.arsc.chunk;
|
||||
|
||||
import com.reandroid.lib.arsc.array.LibraryInfoArray;
|
||||
import com.reandroid.lib.arsc.array.SpecTypePairArray;
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.container.PackageLastBlocks;
|
||||
@ -14,11 +15,13 @@ import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||
import com.reandroid.lib.arsc.pool.TypeStringPool;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.arsc.value.LibraryInfo;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class PackageBlock extends BaseChunk {
|
||||
public class PackageBlock extends BaseChunk implements JsonItem<JSONObject> {
|
||||
private final IntegerItem mPackageId;
|
||||
private final PackageName mPackageName;
|
||||
|
||||
@ -157,11 +160,7 @@ public class PackageBlock extends BaseChunk {
|
||||
if(libraryBlock==null){
|
||||
return;
|
||||
}
|
||||
LibraryInfo[] allInfo=libraryBlock.getAllInfo();
|
||||
if (allInfo==null){
|
||||
return;
|
||||
}
|
||||
for(LibraryInfo info:allInfo){
|
||||
for(LibraryInfo info:libraryBlock.getLibraryInfoArray().listItems()){
|
||||
addLibraryInfo(info);
|
||||
}
|
||||
}
|
||||
@ -268,6 +267,26 @@ public class PackageBlock extends BaseChunk {
|
||||
refreshKeyStrings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_id, getId());
|
||||
jsonObject.put(NAME_name, getName());
|
||||
jsonObject.put(NAME_specs, getSpecTypePairArray().toJson());
|
||||
LibraryInfoArray libraryInfoArray = mLibraryBlock.getLibraryInfoArray();
|
||||
if(libraryInfoArray.childesCount()>0){
|
||||
jsonObject.put(NAME_libraries,libraryInfoArray.toJson());
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setId(json.getInt(NAME_id));
|
||||
setName(json.getString(NAME_name));
|
||||
getSpecTypePairArray().fromJson(json.getJSONArray(NAME_specs));
|
||||
LibraryInfoArray libraryInfoArray = mLibraryBlock.getLibraryInfoArray();
|
||||
libraryInfoArray.fromJson(json.optJSONArray(NAME_libraries));
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
@ -283,4 +302,9 @@ public class PackageBlock extends BaseChunk {
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final String NAME_id="id";
|
||||
private static final String NAME_name="name";
|
||||
private static final String NAME_specs="specs";
|
||||
private static final String NAME_libraries="libraries";
|
||||
}
|
||||
|
@ -7,10 +7,12 @@ import com.reandroid.lib.arsc.io.BlockLoad;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SpecBlock extends BaseTypeBlock implements BlockLoad {
|
||||
public class SpecBlock extends BaseTypeBlock implements BlockLoad , JsonItem<JSONObject> {
|
||||
private final IntegerArray mOffsets;
|
||||
public SpecBlock() {
|
||||
super(ChunkType.SPEC, 1);
|
||||
@ -51,4 +53,16 @@ public class SpecBlock extends BaseTypeBlock implements BlockLoad {
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put("id", getTypeId());
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setTypeId((byte) json.getInt("id"));
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,16 @@ import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||
import com.reandroid.lib.common.Frameworks;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class TableBlock extends BaseChunk {
|
||||
public class TableBlock extends BaseChunk implements JsonItem<JSONObject> {
|
||||
private final IntegerItem mPackageCount;
|
||||
private final TableStringPool mTableStringPool;
|
||||
private final PackageArray mPackageArray;
|
||||
@ -116,10 +119,33 @@ public class TableBlock extends BaseChunk {
|
||||
}
|
||||
mFrameWorks.add(tableBlock);
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_packages, getPackageArray().toJson());
|
||||
JSONArray jsonArray = getTableStringPool().toJson();
|
||||
if(jsonArray!=null){
|
||||
jsonObject.put(NAME_styled_strings, jsonArray);
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
JSONArray jsonArray= json.optJSONArray(NAME_styled_strings);
|
||||
if(jsonArray!=null){
|
||||
getTableStringPool().fromJson(jsonArray);
|
||||
}
|
||||
getPackageArray().fromJson(json.getJSONArray(NAME_packages));
|
||||
refresh();
|
||||
}
|
||||
public static TableBlock loadWithAndroidFramework(InputStream inputStream) throws IOException{
|
||||
TableBlock tableBlock=load(inputStream);
|
||||
tableBlock.addFramework(Frameworks.getAndroid());
|
||||
return tableBlock;
|
||||
}
|
||||
public static TableBlock load(InputStream inputStream) throws IOException{
|
||||
TableBlock tableBlock=new TableBlock();
|
||||
tableBlock.readBytes(inputStream);
|
||||
tableBlock.addFramework(Frameworks.getAndroid());
|
||||
return tableBlock;
|
||||
}
|
||||
|
||||
@ -164,4 +190,6 @@ public class TableBlock extends BaseChunk {
|
||||
}
|
||||
public static final String FILE_NAME="resources.arsc";
|
||||
|
||||
private static final String NAME_packages="packages";
|
||||
private static final String NAME_styled_strings="styled_strings";
|
||||
}
|
||||
|
@ -5,14 +5,17 @@ import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.TypeString;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.arsc.value.ResConfig;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class TypeBlock extends BaseTypeBlock {
|
||||
public class TypeBlock extends BaseTypeBlock implements JsonItem<JSONObject> {
|
||||
private final IntegerItem mEntriesStart;
|
||||
private final ResConfig mResConfig;
|
||||
private final IntegerArray mEntryOffsets;
|
||||
@ -113,6 +116,28 @@ public class TypeBlock extends BaseTypeBlock {
|
||||
super.onPreRefreshRefresh();
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put("id", getTypeId());
|
||||
TypeString typeString=getTypeString();
|
||||
if(typeString!=null){
|
||||
jsonObject.put("name", typeString.get());
|
||||
}
|
||||
jsonObject.put("config", getResConfig().toJson());
|
||||
jsonObject.put("entries", getEntryBlockArray().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setTypeId((byte) json.getInt("id"));
|
||||
String name= json.optString("name");
|
||||
if(name!=null){
|
||||
setTypeName(name);
|
||||
}
|
||||
getEntryBlockArray().fromJson(json.getJSONArray("entries"));
|
||||
getResConfig().fromJson(json.getJSONObject("config"));
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getResConfig().toString());
|
||||
|
@ -4,6 +4,10 @@ import com.reandroid.lib.arsc.item.ResXmlString;
|
||||
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
||||
import com.reandroid.lib.arsc.value.ValueType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -219,6 +223,14 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
builder.append("}");
|
||||
return builder.toString();
|
||||
}
|
||||
public static AndroidManifestBlock load(File file) throws IOException {
|
||||
return load(new FileInputStream(file));
|
||||
}
|
||||
public static AndroidManifestBlock load(InputStream inputStream) throws IOException {
|
||||
AndroidManifestBlock manifestBlock=new AndroidManifestBlock();
|
||||
manifestBlock.readBytes(inputStream);
|
||||
return manifestBlock;
|
||||
}
|
||||
public static final String TAG_manifest ="manifest";
|
||||
public static final String TAG_uses_permission="uses-permission";
|
||||
public static final String TAG_application ="application";
|
||||
|
@ -6,8 +6,11 @@ import com.reandroid.lib.arsc.container.FixedBlockContainer;
|
||||
import com.reandroid.lib.arsc.item.*;
|
||||
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
||||
import com.reandroid.lib.arsc.value.ValueType;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class ResXmlAttribute extends FixedBlockContainer implements Comparable<ResXmlAttribute>{
|
||||
public class ResXmlAttribute extends FixedBlockContainer
|
||||
implements Comparable<ResXmlAttribute>, JsonItem<JSONObject> {
|
||||
private final IntegerItem mNamespaceReference;
|
||||
private final IntegerItem mNameReference;
|
||||
private final IntegerItem mValueStringReference;
|
||||
@ -105,6 +108,17 @@ public class ResXmlAttribute extends FixedBlockContainer implements Comparable<R
|
||||
}
|
||||
return startNamespace.getPrefix();
|
||||
}
|
||||
public String getNamespace(){
|
||||
ResXmlElement xmlElement=getParentResXmlElement();
|
||||
if(xmlElement==null){
|
||||
return null;
|
||||
}
|
||||
ResXmlStartNamespace startNamespace=xmlElement.getStartNamespaceByUriRef(getNamespaceReference());
|
||||
if(startNamespace==null){
|
||||
return null;
|
||||
}
|
||||
return startNamespace.getUri();
|
||||
}
|
||||
public ResXmlStartNamespace getStartNamespace(){
|
||||
ResXmlElement xmlElement=getParentResXmlElement();
|
||||
if(xmlElement==null){
|
||||
@ -344,6 +358,43 @@ public class ResXmlAttribute extends FixedBlockContainer implements Comparable<R
|
||||
return getCompareName().compareTo(other.getCompareName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_name, getName());
|
||||
jsonObject.put(NAME_id, getNameResourceID());
|
||||
jsonObject.put(NAME_namespace_uri, getNamespace());
|
||||
jsonObject.put(NAME_namespace_prefix, getNamePrefix());
|
||||
ValueType valueType=getValueType();
|
||||
jsonObject.put(NAME_value_type, valueType.name());
|
||||
if(valueType==ValueType.STRING){
|
||||
jsonObject.put(NAME_data, getValueAsString());
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||
}else {
|
||||
jsonObject.put(NAME_data, getRawValue());
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
String name = json.getString(NAME_name);
|
||||
int id = json.optInt(NAME_id);
|
||||
setName(name, id);
|
||||
String uri= json.optString(NAME_namespace_uri);
|
||||
String prefix= json.optString(NAME_namespace_prefix);
|
||||
ResXmlStartNamespace ns = getParentResXmlElement().getOrCreateNamespace(uri, prefix);
|
||||
setNamespaceReference(ns.getUriReference());
|
||||
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
||||
if(valueType==ValueType.STRING){
|
||||
setValueAsString(json.getString(NAME_data));
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||
}else {
|
||||
setValueType(valueType);
|
||||
setRawValue(json.getInt(NAME_data));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
String fullName=getFullName();
|
||||
@ -372,4 +423,10 @@ public class ResXmlAttribute extends FixedBlockContainer implements Comparable<R
|
||||
builder.append("}");
|
||||
return builder.toString();
|
||||
}
|
||||
private static final String NAME_id="id";
|
||||
private static final String NAME_value_type="value_type";
|
||||
private static final String NAME_name="name";
|
||||
private static final String NAME_namespace_uri ="namespace_uri";
|
||||
private static final String NAME_namespace_prefix ="namespace_name";
|
||||
private static final String NAME_data="data";
|
||||
}
|
||||
|
@ -6,10 +6,13 @@ import com.reandroid.lib.arsc.container.SingleBlockContainer;
|
||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class ResXmlBlock extends BaseChunk {
|
||||
public class ResXmlBlock extends BaseChunk implements JsonItem<JSONObject> {
|
||||
private final ResXmlStringPool mResXmlStringPool;
|
||||
private final ResXmlIDMap mResXmlIDMap;
|
||||
private ResXmlElement mResXmlElement;
|
||||
@ -129,6 +132,26 @@ public class ResXmlBlock extends BaseChunk {
|
||||
outputStream.close();
|
||||
return length;
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_element, getResXmlElement().toJson());
|
||||
JSONArray pool =getStringPool().toJson();
|
||||
if(pool!=null){
|
||||
jsonObject.put(NAME_styled_strings, getResXmlElement().toJson());
|
||||
}
|
||||
JSONArray idArray = getResXmlIDMap().getResXmlIDArray().toJson();
|
||||
if(idArray!=null){
|
||||
jsonObject.put("resource_ids", idArray);
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
// TODO
|
||||
throw new IllegalArgumentException("Not implemented yet");
|
||||
}
|
||||
|
||||
public static boolean isResXmlBlock(File file){
|
||||
if(file==null){
|
||||
@ -167,4 +190,6 @@ public class ResXmlBlock extends BaseChunk {
|
||||
ChunkType chunkType=headerBlock.getChunkType();
|
||||
return chunkType==ChunkType.XML;
|
||||
}
|
||||
private static final String NAME_element ="element";
|
||||
private static final String NAME_styled_strings="styled_strings";
|
||||
}
|
||||
|
@ -9,6 +9,9 @@ import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.ResXmlString;
|
||||
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
@ -16,7 +19,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ResXmlElement extends FixedBlockContainer {
|
||||
public class ResXmlElement extends FixedBlockContainer implements JsonItem<JSONObject> {
|
||||
private final BlockList<ResXmlStartNamespace> mStartNamespaceList;
|
||||
private final SingleBlockContainer<ResXmlStartElement> mStartElementContainer;
|
||||
private final BlockList<ResXmlElement> mBody;
|
||||
@ -492,6 +495,55 @@ public class ResXmlElement extends FixedBlockContainer {
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
ResXmlStartElement start = getStartElement();
|
||||
jsonObject.put(NAME_line, start.getLineNumber());
|
||||
int i=0;
|
||||
JSONArray nsList=new JSONArray();
|
||||
for(ResXmlStartNamespace namespace:getStartNamespaceList()){
|
||||
JSONObject ns=new JSONObject();
|
||||
ns.put(NAME_namespace_uri, namespace.getUri());
|
||||
ns.put(NAME_namespace_prefix, namespace.getPrefix());
|
||||
nsList.put(i, ns);
|
||||
i++;
|
||||
}
|
||||
if(i>0){
|
||||
jsonObject.put(NAME_namespaces, nsList);
|
||||
}
|
||||
jsonObject.put(NAME_name, start.getName());
|
||||
String uri=start.getUri();
|
||||
if(uri!=null){
|
||||
jsonObject.put(NAME_namespace_uri, uri);
|
||||
jsonObject.put(NAME_namespace_prefix, start.getPrefix());
|
||||
}
|
||||
JSONArray attrArray=start.getResXmlAttributeArray().toJson();
|
||||
jsonObject.put(NAME_attributes, attrArray);
|
||||
i=0;
|
||||
JSONArray childes=new JSONArray();
|
||||
for(ResXmlElement element:listElements()){
|
||||
childes.put(i, element.toJson());
|
||||
i++;
|
||||
}
|
||||
if(i>0){
|
||||
jsonObject.put(NAME_childes, childes);
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
ResXmlStartElement start = getStartElement();
|
||||
start.setLineNumber(json.getInt(NAME_line));
|
||||
String uri= json.optString(NAME_namespace_uri);
|
||||
String prefix= json.optString(NAME_namespace_prefix);
|
||||
if(uri!=null && prefix!=null){
|
||||
ResXmlStartNamespace ns = getOrCreateNamespace(uri, prefix);
|
||||
start.setNamespaceReference(ns.getUriReference());
|
||||
}
|
||||
JSONArray attributes = json.getJSONArray(NAME_attributes);
|
||||
start.getResXmlAttributeArray().fromJson(attributes);
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
ResXmlStartElement start = getStartElement();
|
||||
if(start!=null){
|
||||
@ -524,4 +576,12 @@ public class ResXmlElement extends FixedBlockContainer {
|
||||
|
||||
public static final String NS_ANDROID_URI = "http://schemas.android.com/apk/res/android";
|
||||
public static final String NS_ANDROID_PREFIX = "android";
|
||||
|
||||
private static final String NAME_name = "name";
|
||||
private static final String NAME_namespaces = "namespaces";
|
||||
private static final String NAME_namespace_uri = "namespace_uri";
|
||||
private static final String NAME_namespace_prefix = "namespace_name";
|
||||
private static final String NAME_line = "line";
|
||||
private static final String NAME_attributes = "attributes";
|
||||
private static final String NAME_childes = "childes";
|
||||
}
|
||||
|
@ -74,6 +74,19 @@ public class ResXmlStartElement extends BaseXmlChunk {
|
||||
public ResXmlAttributeArray getResXmlAttributeArray(){
|
||||
return mAttributeArray;
|
||||
}
|
||||
|
||||
public String getUri(){
|
||||
int uriRef=getNamespaceReference();
|
||||
if(uriRef<0){
|
||||
return null;
|
||||
}
|
||||
ResXmlElement parentElement=getParentResXmlElement();
|
||||
ResXmlStartNamespace startNamespace=parentElement.getStartNamespaceByUriRef(uriRef);
|
||||
if(startNamespace!=null){
|
||||
return startNamespace.getUri();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public String getPrefix(){
|
||||
int uriRef=getNamespaceReference();
|
||||
if(uriRef<0){
|
||||
|
@ -12,6 +12,8 @@ import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.TypeString;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.arsc.value.ResConfig;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -19,7 +21,7 @@ import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class SpecTypePair extends BlockContainer<Block> {
|
||||
public class SpecTypePair extends BlockContainer<Block> implements JsonItem<JSONObject> {
|
||||
private final Block[] mChildes;
|
||||
private final SpecBlock mSpecBlock;
|
||||
private final TypeBlockArray mTypeBlockArray;
|
||||
@ -140,4 +142,17 @@ public class SpecTypePair extends BlockContainer<Block> {
|
||||
public TypeString getTypeString(){
|
||||
return getTypeBlockArray().getTypeString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put("id", getSpecBlock().getTypeId());
|
||||
jsonObject.put("types", getTypeBlockArray().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
getSpecBlock().setTypeId((byte) json.getInt("id"));
|
||||
getTypeBlockArray().fromJson(json.getJSONArray("types"));
|
||||
}
|
||||
}
|
||||
|
@ -28,13 +28,28 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
if(specStringPool==null){
|
||||
return false;
|
||||
}
|
||||
String oldName=getSpecName();
|
||||
if(name.equals(oldName)){
|
||||
return false;
|
||||
if(isAllSameSpec()){
|
||||
String oldName=getSpecName();
|
||||
if(name.equals(oldName)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
SpecString specString=specStringPool.getOrCreate(name);
|
||||
return renameSpec(specString.getIndex());
|
||||
}
|
||||
private boolean isAllSameSpec(){
|
||||
EntryBlock first=null;
|
||||
for(EntryBlock entryBlock:listItems()){
|
||||
if(first==null){
|
||||
first=entryBlock;
|
||||
continue;
|
||||
}
|
||||
if(first.getSpecReference()!=entryBlock.getSpecReference()){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public boolean renameSpec(int specReference){
|
||||
EntryBlock[] items=getItems();
|
||||
if(items==null){
|
||||
|
@ -1,10 +1,16 @@
|
||||
package com.reandroid.lib.arsc.item;
|
||||
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.chunk.xml.ResXmlBlock;
|
||||
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ResXmlID extends IntegerItem {
|
||||
public class ResXmlID extends IntegerItem implements JsonItem<JSONObject> {
|
||||
private final List<ReferenceItem> mReferencedList;
|
||||
public ResXmlID(int resId){
|
||||
super(resId);
|
||||
@ -47,6 +53,29 @@ public class ResXmlID extends IntegerItem {
|
||||
public void onIndexChanged(int oldIndex, int newIndex){
|
||||
reUpdateReferences(newIndex);
|
||||
}
|
||||
|
||||
private ResXmlStringPool getXmlStringPool(){
|
||||
Block parent=this;
|
||||
while (parent!=null){
|
||||
if(parent instanceof ResXmlBlock){
|
||||
return ((ResXmlBlock)parent).getStringPool();
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put("id", get());
|
||||
jsonObject.put("name", getXmlStringPool().get(getIndex()).getHtml());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
//TODO
|
||||
throw new IllegalArgumentException("Not implemented yet");
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return getIndex()+": "+String.format("0x%08x", get());
|
||||
|
@ -3,6 +3,8 @@ package com.reandroid.lib.arsc.item;
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.pool.BaseStringPool;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
@ -15,7 +17,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class StringItem extends BlockItem {
|
||||
public class StringItem extends BlockItem implements JsonItem<JSONObject> {
|
||||
private String mCache;
|
||||
private boolean mUtf8;
|
||||
private final List<ReferenceItem> mReferencedList;
|
||||
@ -166,27 +168,54 @@ public class StringItem extends BlockItem {
|
||||
return new String(allStringBytes, offLen[0], offLen[1], StandardCharsets.UTF_16LE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean hasStyle(){
|
||||
StyleItem styleItem=getStyle();
|
||||
if(styleItem==null){
|
||||
return false;
|
||||
}
|
||||
return !styleItem.isNull();
|
||||
}
|
||||
public StyleItem getStyle(){
|
||||
BaseStringPool stringPool=getStringPool();
|
||||
BaseStringPool<?> stringPool=getStringPool();
|
||||
if(stringPool==null){
|
||||
return null;
|
||||
}
|
||||
int index=getIndex();
|
||||
return stringPool.getStyle(index);
|
||||
}
|
||||
private BaseStringPool getStringPool(){
|
||||
private BaseStringPool<?> getStringPool(){
|
||||
Block parent=getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof BaseStringPool){
|
||||
return (BaseStringPool)parent;
|
||||
return (BaseStringPool<?>)parent;
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_string, get());
|
||||
StyleItem styleItem=getStyle();
|
||||
if(styleItem!=null){
|
||||
JSONObject styleJson=styleItem.toJson();
|
||||
if(styleJson!=null){
|
||||
jsonObject.put(NAME_style, styleJson);
|
||||
}
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
String str = json.getString(NAME_string);
|
||||
set(str);
|
||||
throw new IllegalArgumentException("Not implemented");
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
String str=get();
|
||||
if(str==null){
|
||||
@ -332,4 +361,7 @@ public class StringItem extends BlockItem {
|
||||
|
||||
private final CharsetDecoder UTF16LE_DECODER = StandardCharsets.UTF_16LE.newDecoder();
|
||||
private final CharsetDecoder UTF8_DECODER = StandardCharsets.UTF_8.newDecoder();
|
||||
|
||||
private static final String NAME_string="string";
|
||||
private static final String NAME_style="style";
|
||||
}
|
||||
|
@ -4,16 +4,19 @@ import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.model.StyleSpanInfo;
|
||||
import com.reandroid.lib.arsc.pool.BaseStringPool;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class StyleItem extends IntegerArray{
|
||||
private List<int[]> mStyleList;
|
||||
public class StyleItem extends IntegerArray implements JsonItem<JSONObject> {
|
||||
private List<StyleSpanInfo> mSpanInfoList;
|
||||
public StyleItem() {
|
||||
super();
|
||||
mStyleList=createStyleList();
|
||||
}
|
||||
private void setEndValue(int negOne){
|
||||
super.put(size()-1, negOne);
|
||||
@ -22,54 +25,67 @@ public class StyleItem extends IntegerArray{
|
||||
return super.get(size()-1);
|
||||
}
|
||||
final Integer getStringRef(int index){
|
||||
int i=index*STYLE_PIECE_COUNT+STRING_REF;
|
||||
int i=index * INTEGERS_COUNT + INDEX_STRING_REF;
|
||||
return super.get(i);
|
||||
}
|
||||
final void setStringRef(int index, int val){
|
||||
int i=index*STYLE_PIECE_COUNT+STRING_REF;
|
||||
int i=index * INTEGERS_COUNT + INDEX_STRING_REF;
|
||||
super.put(i, val);
|
||||
}
|
||||
final Integer getFirstChar(int index){
|
||||
int i=index*STYLE_PIECE_COUNT+CHAR_FIRST;
|
||||
int i=index * INTEGERS_COUNT + INDEX_CHAR_FIRST;
|
||||
return super.get(i);
|
||||
}
|
||||
final void setFirstChar(int index, int val){
|
||||
int i=index*STYLE_PIECE_COUNT+CHAR_FIRST;
|
||||
int i=index * INTEGERS_COUNT + INDEX_CHAR_FIRST;
|
||||
super.put(i, val);
|
||||
}
|
||||
final Integer getLastChar(int index){
|
||||
int i=index*STYLE_PIECE_COUNT+CHAR_LAST;
|
||||
int i=index * INTEGERS_COUNT + INDEX_CHAR_LAST;
|
||||
return super.get(i);
|
||||
}
|
||||
final void setLastChar(int index, int val){
|
||||
int i=index*STYLE_PIECE_COUNT+CHAR_LAST;
|
||||
int i=index * INTEGERS_COUNT + INDEX_CHAR_LAST;
|
||||
super.put(i, val);
|
||||
}
|
||||
public void addStylePiece(String tag, int firstChar, int lastChar){
|
||||
BaseStringPool<?> stringPool = getStringPool();
|
||||
if(stringPool==null){
|
||||
throw new IllegalArgumentException("Null string pool, must be added to parent StyleArray first");
|
||||
}
|
||||
StringItem stringItem=stringPool.getOrCreate(tag);
|
||||
addStylePiece(stringItem.getIndex(), firstChar, lastChar);
|
||||
}
|
||||
public void addStylePiece(int refString, int firstChar, int lastChar){
|
||||
int index=getStylePieceCount();
|
||||
setStylePieceCount(index+1);
|
||||
setStylePiece(index, refString, firstChar, lastChar);
|
||||
}
|
||||
final void setStylePiece(int index, int refString, int firstChar, int lastChar){
|
||||
int i=index*STYLE_PIECE_COUNT;
|
||||
super.put(i+STRING_REF, refString);
|
||||
super.put(i+CHAR_FIRST, firstChar);
|
||||
super.put(i+CHAR_LAST, lastChar);
|
||||
int i=index * INTEGERS_COUNT;
|
||||
super.put(i+ INDEX_STRING_REF, refString);
|
||||
super.put(i+ INDEX_CHAR_FIRST, firstChar);
|
||||
super.put(i+ INDEX_CHAR_LAST, lastChar);
|
||||
}
|
||||
final int[] getStylePiece(int index){
|
||||
if(index<0||index>= getStylePieceCount()){
|
||||
return null;
|
||||
}
|
||||
int[] result=new int[STYLE_PIECE_COUNT];
|
||||
int i=index*STYLE_PIECE_COUNT;
|
||||
result[STRING_REF]=super.get(i);
|
||||
result[CHAR_FIRST]=super.get(i+CHAR_FIRST);
|
||||
result[CHAR_LAST]=super.get(i+CHAR_LAST);
|
||||
int[] result=new int[INTEGERS_COUNT];
|
||||
int i=index * INTEGERS_COUNT;
|
||||
result[INDEX_STRING_REF]=super.get(i);
|
||||
result[INDEX_CHAR_FIRST]=super.get(i+ INDEX_CHAR_FIRST);
|
||||
result[INDEX_CHAR_LAST]=super.get(i+ INDEX_CHAR_LAST);
|
||||
return result;
|
||||
}
|
||||
final void setStylePiece(int index, int[] three){
|
||||
if(three==null || three.length<STYLE_PIECE_COUNT){
|
||||
if(three==null || three.length< INTEGERS_COUNT){
|
||||
return;
|
||||
}
|
||||
int i=index*STYLE_PIECE_COUNT;
|
||||
super.put(i+STRING_REF, three[STRING_REF]);
|
||||
super.put(i+CHAR_FIRST, three[CHAR_FIRST]);
|
||||
super.put(i+CHAR_LAST, three[CHAR_LAST]);
|
||||
int i = index * INTEGERS_COUNT;
|
||||
super.put(i + INDEX_STRING_REF, three[INDEX_STRING_REF]);
|
||||
super.put(i + INDEX_CHAR_FIRST, three[INDEX_CHAR_FIRST]);
|
||||
super.put(i + INDEX_CHAR_LAST, three[INDEX_CHAR_LAST]);
|
||||
}
|
||||
final void ensureStylePieceCount(int count){
|
||||
if(count<0){
|
||||
@ -84,23 +100,23 @@ public class StyleItem extends IntegerArray{
|
||||
if(sz<0){
|
||||
sz=0;
|
||||
}
|
||||
return sz/STYLE_PIECE_COUNT;
|
||||
return sz/ INTEGERS_COUNT;
|
||||
}
|
||||
final void setStylePieceCount(int count){
|
||||
if(count<0){
|
||||
count=0;
|
||||
}
|
||||
int cur= getStylePieceCount();
|
||||
int cur = getStylePieceCount();
|
||||
if(count==cur){
|
||||
return;
|
||||
}
|
||||
int max=count*STYLE_PIECE_COUNT+1;
|
||||
int max=count * INTEGERS_COUNT + 1;
|
||||
if(size()==0 || count==0){
|
||||
super.setSize(max);
|
||||
setEndValue(END_VALUE);
|
||||
return;
|
||||
}
|
||||
List<int[]> copy=new ArrayList<>(mStyleList);
|
||||
List<int[]> copy=new ArrayList<>(getIntSpanInfoList());
|
||||
Integer end= getEndValue();
|
||||
if(end==null){
|
||||
end=END_VALUE;
|
||||
@ -117,42 +133,54 @@ public class StyleItem extends IntegerArray{
|
||||
}
|
||||
setEndValue(end);
|
||||
}
|
||||
final List<int[]> getStyleList(){
|
||||
return mStyleList;
|
||||
private List<int[]> getIntSpanInfoList(){
|
||||
return new AbstractList<int[]>() {
|
||||
@Override
|
||||
public int[] get(int i) {
|
||||
return StyleItem.this.getStylePiece(i);
|
||||
}
|
||||
@Override
|
||||
public int size() {
|
||||
return StyleItem.this.getStylePieceCount();
|
||||
}
|
||||
};
|
||||
}
|
||||
private List<int[]> createStyleList(){
|
||||
List<int[]> results=new ArrayList<>();
|
||||
int max=getStylePieceCount();
|
||||
for(int i=0;i<max;i++){
|
||||
results.add(getStylePiece(i));
|
||||
final List<StyleSpanInfo> getSpanInfoList(){
|
||||
if(mSpanInfoList!=null){
|
||||
return mSpanInfoList;
|
||||
}
|
||||
return results;
|
||||
mSpanInfoList = new AbstractList<StyleSpanInfo>() {
|
||||
@Override
|
||||
public StyleSpanInfo get(int i) {
|
||||
int ref=getStringRef(i);
|
||||
return new StyleSpanInfo(
|
||||
getStringFromPool(ref),
|
||||
getFirstChar(i),
|
||||
getLastChar(i));
|
||||
}
|
||||
@Override
|
||||
public int size() {
|
||||
return getStylePieceCount();
|
||||
}
|
||||
};
|
||||
return mSpanInfoList;
|
||||
}
|
||||
final List<StyleSpanInfo> getSpanInfo(){
|
||||
BaseStringPool stringPool= getStringPool();
|
||||
private String getStringFromPool(int ref){
|
||||
BaseStringPool<?> stringPool = getStringPool();
|
||||
if(stringPool==null){
|
||||
return null;
|
||||
}
|
||||
List<int[]> allPiece=getStyleList();
|
||||
List<StyleSpanInfo> results=new ArrayList<>();
|
||||
for(int[] piece:allPiece){
|
||||
StringItem stringItem=stringPool.get(piece[STRING_REF]);
|
||||
if(stringItem==null){
|
||||
return null;
|
||||
}
|
||||
StyleSpanInfo info=new StyleSpanInfo(stringItem.get(), piece[CHAR_FIRST], piece[CHAR_LAST]);
|
||||
results.add(info);
|
||||
}
|
||||
if(results.size()==0){
|
||||
StringItem stringItem = stringPool.get(ref);
|
||||
if(stringItem==null){
|
||||
return null;
|
||||
}
|
||||
return results;
|
||||
return stringItem.get();
|
||||
}
|
||||
private BaseStringPool getStringPool(){
|
||||
private BaseStringPool<?> getStringPool(){
|
||||
Block parent=getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof BaseStringPool){
|
||||
return (BaseStringPool)parent;
|
||||
return (BaseStringPool<?>)parent;
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
@ -163,8 +191,8 @@ public class StyleItem extends IntegerArray{
|
||||
if(str==null){
|
||||
return null;
|
||||
}
|
||||
List<StyleSpanInfo> allInfo=getSpanInfo();
|
||||
if(allInfo==null){
|
||||
List<StyleSpanInfo> spanInfoList = getSpanInfoList();
|
||||
if(spanInfoList.size()==0){
|
||||
return str;
|
||||
}
|
||||
StringBuilder builder=new StringBuilder();
|
||||
@ -173,9 +201,9 @@ public class StyleItem extends IntegerArray{
|
||||
for(int i=0;i<max;i++){
|
||||
char ch=allChars[i];
|
||||
boolean lastAppend=false;
|
||||
for(StyleSpanInfo info:allInfo){
|
||||
boolean isLast=(info.LAST==i);
|
||||
if(info.FIRST==i || isLast){
|
||||
for(StyleSpanInfo info:spanInfoList){
|
||||
boolean isLast=(info.getLast()==i);
|
||||
if(info.getFirst()==i || isLast){
|
||||
if(isLast && !lastAppend){
|
||||
builder.append(ch);
|
||||
lastAppend=true;
|
||||
@ -195,7 +223,6 @@ public class StyleItem extends IntegerArray{
|
||||
}
|
||||
@Override
|
||||
public void onBytesChanged() {
|
||||
mStyleList=createStyleList();
|
||||
}
|
||||
@Override
|
||||
public void setNull(boolean is_null){
|
||||
@ -216,11 +243,57 @@ public class StyleItem extends IntegerArray{
|
||||
reader.readFully(bts);
|
||||
onBytesChanged();
|
||||
}
|
||||
private static final int STRING_REF=0;
|
||||
private static final int CHAR_FIRST=1;
|
||||
private static final int CHAR_LAST=2;
|
||||
public void addSpanInfo(String tag, int first, int last){
|
||||
int index=getStylePieceCount();
|
||||
setStylePieceCount(index+1);
|
||||
BaseStringPool<?> stringPool = getStringPool();
|
||||
if(stringPool==null){
|
||||
throw new IllegalArgumentException("Null string pool, must be added to parent StyleArray first");
|
||||
}
|
||||
StringItem stringItem=stringPool.getOrCreate(tag);
|
||||
setStylePiece(index, stringItem.getIndex(), first, last);
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int i=0;
|
||||
for(StyleSpanInfo spanInfo:getSpanInfoList()){
|
||||
JSONObject jsonObjectSpan=spanInfo.toJson();
|
||||
jsonArray.put(i, jsonObjectSpan);
|
||||
i++;
|
||||
}
|
||||
jsonObject.put(NAME_spans, jsonArray);
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setNull(true);
|
||||
if(json==null){
|
||||
return;
|
||||
}
|
||||
JSONArray jsonArray= json.getJSONArray(NAME_spans);
|
||||
int length = jsonArray.length();
|
||||
for(int i=0;i<length;i++){
|
||||
JSONObject jsonObject=jsonArray.getJSONObject(i);
|
||||
StyleSpanInfo spanInfo=new StyleSpanInfo(null, 0, 0);
|
||||
spanInfo.fromJson(jsonObject);
|
||||
addSpanInfo(spanInfo.getTag(), spanInfo.getFirst(), spanInfo.getLast());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Spans count = "+getSpanInfoList().size();
|
||||
}
|
||||
private static final int INDEX_STRING_REF = 0;
|
||||
private static final int INDEX_CHAR_FIRST = 1;
|
||||
private static final int INDEX_CHAR_LAST = 2;
|
||||
|
||||
private static final int STYLE_PIECE_COUNT=3;
|
||||
private static final int INTEGERS_COUNT = 3;
|
||||
|
||||
private static final int END_VALUE=0xFFFFFFFF;
|
||||
private static final String NAME_spans="spans";
|
||||
}
|
||||
|
@ -1,11 +1,29 @@
|
||||
package com.reandroid.lib.arsc.item;
|
||||
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.arsc.value.ResValueReference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TableString extends StringItem {
|
||||
public TableString(boolean utf8) {
|
||||
super(utf8);
|
||||
}
|
||||
public List<EntryBlock> listReferencedEntries(){
|
||||
List<EntryBlock> results=new ArrayList<>();
|
||||
for(ReferenceItem ref:getReferencedList()){
|
||||
if(!(ref instanceof ResValueReference)){
|
||||
continue;
|
||||
}
|
||||
EntryBlock entryBlock=((ResValueReference)ref).getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
continue;
|
||||
}
|
||||
results.add(entryBlock);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
List<ReferenceItem> refList = getReferencedList();
|
||||
|
@ -1,44 +1,84 @@
|
||||
package com.reandroid.lib.arsc.model;
|
||||
|
||||
public class StyleSpanInfo {
|
||||
public final String TAG;
|
||||
public final int FIRST;
|
||||
public final int LAST;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class StyleSpanInfo implements JsonItem<JSONObject> {
|
||||
private String mTag;
|
||||
private int mFirst;
|
||||
private int mLast;
|
||||
public StyleSpanInfo(String tag, int first, int last){
|
||||
this.TAG=tag;
|
||||
this.FIRST=first;
|
||||
this.LAST=last;
|
||||
this.mTag = tag;
|
||||
this.mFirst = first;
|
||||
this.mLast = last;
|
||||
}
|
||||
public int getFirst() {
|
||||
return mFirst;
|
||||
}
|
||||
public void setFirst(int first) {
|
||||
this.mFirst = first;
|
||||
}
|
||||
public int getLast() {
|
||||
return mLast;
|
||||
}
|
||||
public void setLast(int last) {
|
||||
this.mLast = last;
|
||||
}
|
||||
public String getTag() {
|
||||
return mTag;
|
||||
}
|
||||
public void setTag(String tag) {
|
||||
this.mTag = tag;
|
||||
}
|
||||
|
||||
public String getStartTag(){
|
||||
int i=TAG.indexOf(';');
|
||||
int i= mTag.indexOf(';');
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append('<');
|
||||
if(i<0){
|
||||
builder.append(TAG);
|
||||
builder.append(mTag);
|
||||
}else {
|
||||
builder.append(TAG, 0, i);
|
||||
builder.append(mTag, 0, i);
|
||||
builder.append(' ');
|
||||
builder.append(TAG.substring(i+1));
|
||||
builder.append(mTag.substring(i+1));
|
||||
}
|
||||
builder.append('>');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String getEndTag(){
|
||||
int i=TAG.indexOf(';');
|
||||
int i= mTag.indexOf(';');
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append('<');
|
||||
builder.append('/');
|
||||
if(i<0){
|
||||
builder.append(TAG);
|
||||
builder.append(mTag);
|
||||
}else {
|
||||
builder.append(TAG, 0, i);
|
||||
builder.append(mTag, 0, i);
|
||||
}
|
||||
builder.append('>');
|
||||
return builder.toString();
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return TAG+" ("+FIRST+", "+LAST+")";
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_tag, mTag);
|
||||
jsonObject.put(NAME_first, mFirst);
|
||||
jsonObject.put(NAME_last, mLast);
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setTag(json.getString(NAME_tag));
|
||||
setFirst(json.getInt(NAME_first));
|
||||
setLast(json.getInt(NAME_last));
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return mTag +" ("+ mFirst +", "+ mLast +")";
|
||||
}
|
||||
|
||||
private static final String NAME_tag="tag";
|
||||
private static final String NAME_first="first";
|
||||
private static final String NAME_last="last";
|
||||
}
|
||||
|
@ -10,12 +10,14 @@ import com.reandroid.lib.arsc.io.BlockLoad;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.*;
|
||||
import com.reandroid.lib.arsc.pool.builder.StyleBuilder;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public abstract class BaseStringPool<T extends StringItem> extends BaseChunk implements BlockLoad {
|
||||
public abstract class BaseStringPool<T extends StringItem> extends BaseChunk implements BlockLoad, JsonItem<JSONArray> {
|
||||
private final IntegerItem mCountStrings;
|
||||
private final IntegerItem mCountStyles;
|
||||
private final ShortItem mFlagUtf8;
|
||||
@ -64,6 +66,10 @@ public abstract class BaseStringPool<T extends StringItem> extends BaseChunk imp
|
||||
mUniqueMap=new HashMap<>();
|
||||
|
||||
}
|
||||
// call this after modifying string values
|
||||
public void refreshUniqueIdMap(){
|
||||
reUpdateUniqueMap();
|
||||
}
|
||||
public void recreateStyles(){
|
||||
StyleArray styleArray = getStyleArray();
|
||||
//styleArray.clearChildes();
|
||||
@ -249,6 +255,16 @@ public abstract class BaseStringPool<T extends StringItem> extends BaseChunk imp
|
||||
mArrayStrings.setUtf8(isUtf8Flag());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
return getStringsArray().toJson();
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
getStringsArray().fromJson(json);
|
||||
refreshUniqueIdMap();
|
||||
refresh();
|
||||
}
|
||||
private static final short UTF8_FLAG_VALUE=0x0100;
|
||||
|
||||
private static final short FLAG_UTF8 = 0x0100;
|
||||
|
@ -6,6 +6,7 @@ import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.ReferenceItem;
|
||||
import com.reandroid.lib.arsc.item.TableString;
|
||||
import org.json.JSONArray;
|
||||
|
||||
public class TableStringPool extends BaseStringPool<TableString> {
|
||||
public TableStringPool(boolean is_utf8) {
|
||||
|
@ -3,8 +3,10 @@ package com.reandroid.lib.arsc.value;
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.item.BlockItem;
|
||||
import com.reandroid.lib.arsc.item.ReferenceItem;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public abstract class BaseResValue extends BlockItem {
|
||||
public abstract class BaseResValue extends BlockItem implements JsonItem<JSONObject> {
|
||||
BaseResValue(int bytesLength){
|
||||
super(bytesLength);
|
||||
}
|
||||
@ -95,4 +97,10 @@ public abstract class BaseResValue extends BlockItem {
|
||||
byte getByte(int offset){
|
||||
return getBytesInternal()[offset];
|
||||
}
|
||||
|
||||
static final String NAME_data = "data";
|
||||
static final String NAME_value_type="value_type";
|
||||
static final String NAME_id="id";
|
||||
static final String NAME_parent="parent";
|
||||
static final String NAME_items="items";
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public abstract class BaseResValueItem extends BaseResValue implements ResValueI
|
||||
return null;
|
||||
}
|
||||
if(mReferenceItem==null){
|
||||
mReferenceItem=createReferenceItem();
|
||||
mReferenceItem=new ResValueReference(this);
|
||||
}
|
||||
return mReferenceItem;
|
||||
}
|
||||
@ -62,23 +62,6 @@ public abstract class BaseResValueItem extends BaseResValue implements ResValueI
|
||||
mReferenceItem=null;
|
||||
return entryBlock.removeTableReference(ref);
|
||||
}
|
||||
private ReferenceItem createReferenceItem(){
|
||||
return new ReferenceItem() {
|
||||
@Override
|
||||
public void set(int val) {
|
||||
if(getValueType()==ValueType.STRING){
|
||||
BaseResValueItem.this.setData(val);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int get() {
|
||||
if(getValueType()==ValueType.STRING){
|
||||
return BaseResValueItem.this.getData();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ValueType getValueType(){
|
||||
return ValueType.valueOf(getType());
|
||||
|
@ -10,6 +10,8 @@ import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.*;
|
||||
import com.reandroid.lib.arsc.pool.SpecStringPool;
|
||||
import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
@ -17,7 +19,7 @@ import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EntryBlock extends Block{
|
||||
public class EntryBlock extends Block implements JsonItem<JSONObject> {
|
||||
private ShortItem mHeaderSize;
|
||||
private ShortItem mFlags;
|
||||
private IntegerItem mSpecReference;
|
||||
@ -84,7 +86,18 @@ public class EntryBlock extends Block{
|
||||
resValueInt.setData(tableString.getIndex());
|
||||
return resValueInt;
|
||||
}
|
||||
public boolean getValueAsBoolean(){
|
||||
int data = ((ResValueInt)getResValue()).getData();
|
||||
return data!=0;
|
||||
}
|
||||
public String getValueAsString(){
|
||||
TableString tableString= getValueAsTableString();
|
||||
if(tableString==null){
|
||||
return null;
|
||||
}
|
||||
return tableString.getHtml();
|
||||
}
|
||||
public TableString getValueAsTableString(){
|
||||
TableStringPool stringPool=getTableStringPool();
|
||||
if(stringPool==null){
|
||||
return null;
|
||||
@ -98,7 +111,7 @@ public class EntryBlock extends Block{
|
||||
if(tableString==null){
|
||||
return null;
|
||||
}
|
||||
return tableString.getHtml();
|
||||
return tableString;
|
||||
}
|
||||
private TableStringPool getTableStringPool(){
|
||||
PackageBlock pkg=getPackageBlock();
|
||||
@ -298,6 +311,11 @@ public class EntryBlock extends Block{
|
||||
}
|
||||
return specString.get();
|
||||
}
|
||||
private void setName(String name){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
EntryGroup entryGroup = packageBlock.getEntryGroup(getResourceId());
|
||||
entryGroup.renameSpec(name);
|
||||
}
|
||||
public String getTypeName(){
|
||||
TypeString typeString=getTypeString();
|
||||
if(typeString==null){
|
||||
@ -479,6 +497,12 @@ public class EntryBlock extends Block{
|
||||
private boolean isFlagsComplex(){
|
||||
return ((mFlags.get() & FLAG_COMPLEX_MASK) != 0);
|
||||
}
|
||||
public boolean isArray(){
|
||||
return ((mFlags.get() & FLAG_COMPLEX_MASK) != 0);
|
||||
}
|
||||
public void setIsArray(boolean is_array){
|
||||
setFlagComplex(is_array);
|
||||
}
|
||||
@Override
|
||||
public void setNull(boolean is_null){
|
||||
if(is_null){
|
||||
@ -596,6 +620,35 @@ public class EntryBlock extends Block{
|
||||
updateSpecRef();
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_name, getSpecString().get());
|
||||
jsonObject.put(NAME_is_array, isArray());
|
||||
jsonObject.put(NAME_value, getResValue().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
if(json==null){
|
||||
setNull(true);
|
||||
return;
|
||||
}
|
||||
setName(json.getString(NAME_name));
|
||||
setNull(false);
|
||||
BaseResValue baseResValue;
|
||||
if(json.getBoolean(NAME_is_array)){
|
||||
baseResValue=new ResValueInt();
|
||||
}else {
|
||||
baseResValue=new ResValueBag();
|
||||
}
|
||||
setResValue(baseResValue);
|
||||
baseResValue.fromJson(json.getJSONObject(NAME_value));
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
@ -654,4 +707,8 @@ public class EntryBlock extends Block{
|
||||
private final static short HEADER_COMPLEX=0x0010;
|
||||
private final static short HEADER_INT=0x0008;
|
||||
|
||||
private static final String NAME_name="name";
|
||||
private static final String NAME_is_array="is_array";
|
||||
private static final String NAME_value="value";
|
||||
|
||||
}
|
||||
|
@ -5,11 +5,13 @@ import com.reandroid.lib.arsc.base.BlockCounter;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.PackageName;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class LibraryInfo extends Block {
|
||||
public class LibraryInfo extends Block implements JsonItem<JSONObject> {
|
||||
private final IntegerItem mPackageId;
|
||||
private final PackageName mPackageName;
|
||||
|
||||
@ -74,6 +76,18 @@ public class LibraryInfo extends Block {
|
||||
mPackageName.readBytes(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put("id", getPackageId());
|
||||
jsonObject.put("name", getPackageName());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setPackageId(json.getInt("id"));
|
||||
setPackageName(json.getString("name"));
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
|
@ -6,12 +6,13 @@ import com.reandroid.lib.arsc.io.BlockLoad;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.ByteArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.json.JsonItem;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
public class ResConfig extends FixedBlockContainer implements BlockLoad, JsonItem<JSONObject> {
|
||||
|
||||
private final IntegerItem configSize;
|
||||
private final ByteArray mValuesContainer;
|
||||
@ -156,7 +157,17 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_languageIn1);
|
||||
}
|
||||
public char[] getLanguage(){
|
||||
public String getLanguage(){
|
||||
return ResConfigHelper.decodeLanguage(getLanguageChars());
|
||||
}
|
||||
public void setLanguage(String language){
|
||||
char[] chs=new char[2];
|
||||
if(language!=null){
|
||||
chs=language.toCharArray();
|
||||
}
|
||||
setLanguage(chs);
|
||||
}
|
||||
public char[] getLanguageChars(){
|
||||
byte b0=getLanguageIn0();
|
||||
byte b1=getLanguageIn1();
|
||||
return unpackLanguageOrRegion(b0, b1, 'a');
|
||||
@ -201,7 +212,10 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_countryIn1);
|
||||
}
|
||||
public char[] getRegion(){
|
||||
public String getRegion(){
|
||||
return ResConfigHelper.decodeRegion(getRegionChars());
|
||||
}
|
||||
public char[] getRegionChars(){
|
||||
byte b0=getCountryIn0();
|
||||
byte b1=getCountryIn1();
|
||||
return unpackLanguageOrRegion(b0, b1, '0');
|
||||
@ -225,12 +239,18 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
mValuesContainer.put(OFFSET_orientation, b);
|
||||
}
|
||||
public byte getOrientation(){
|
||||
public byte getOrientationByte(){
|
||||
if(getConfigSize()<SIZE_16){
|
||||
return 0;
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_orientation);
|
||||
}
|
||||
public Orientation getOrientation(){
|
||||
return Orientation.fromValue(getOrientationByte());
|
||||
}
|
||||
public void setOrientation(Orientation orientation){
|
||||
setOrientation(orientation.getByteValue());
|
||||
}
|
||||
public void setTouchscreen(byte b){
|
||||
if(getConfigSize()<SIZE_16){
|
||||
if(b==0){
|
||||
@ -240,12 +260,18 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
mValuesContainer.put(OFFSET_touchscreen, b);
|
||||
}
|
||||
public byte getTouchscreen(){
|
||||
public byte getTouchscreenByte(){
|
||||
if(getConfigSize()<SIZE_16){
|
||||
return 0;
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_touchscreen);
|
||||
}
|
||||
public Touchscreen getTouchscreen(){
|
||||
return Touchscreen.fromValue(getTouchscreenByte());
|
||||
}
|
||||
public void setTouchscreen(Touchscreen touchscreen){
|
||||
setTouchscreen(touchscreen.getByteValue());
|
||||
}
|
||||
public void setDensity(short sh){
|
||||
if(getConfigSize()<SIZE_16){
|
||||
if(sh==0){
|
||||
@ -255,12 +281,18 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
mValuesContainer.putShort(OFFSET_density, sh);
|
||||
}
|
||||
public short getDensity(){
|
||||
public short getDensityValue(){
|
||||
if(getConfigSize()<SIZE_16){
|
||||
return 0;
|
||||
}
|
||||
return mValuesContainer.getShort(OFFSET_density);
|
||||
}
|
||||
public String getDensity(){
|
||||
return ResConfigHelper.decodeDensity(getDensityValue());
|
||||
}
|
||||
public void setDensity(String density){
|
||||
setDensity(ResConfigHelper.encodeDensity(density));
|
||||
}
|
||||
public void setKeyboard(byte b){
|
||||
if(getConfigSize()<SIZE_28){
|
||||
if(b==0){
|
||||
@ -270,12 +302,18 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
mValuesContainer.put(OFFSET_keyboard, b);
|
||||
}
|
||||
public byte getKeyboard(){
|
||||
public byte getKeyboardByte(){
|
||||
if(getConfigSize()<SIZE_28){
|
||||
return 0;
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_keyboard);
|
||||
}
|
||||
public Keyboard getKeyboard(){
|
||||
return Keyboard.fromValue(getKeyboardByte());
|
||||
}
|
||||
public void setKeyboard(Keyboard keyboard){
|
||||
setKeyboard(keyboard.getByteValue());
|
||||
}
|
||||
public void setNavigation(byte b){
|
||||
if(getConfigSize()<SIZE_28){
|
||||
if(b==0){
|
||||
@ -285,12 +323,18 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
mValuesContainer.put(OFFSET_navigation, b);
|
||||
}
|
||||
public byte getNavigation(){
|
||||
public byte getNavigationByte(){
|
||||
if(getConfigSize()<SIZE_28){
|
||||
return 0;
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_navigation);
|
||||
}
|
||||
public Navigation getNavigation(){
|
||||
return Navigation.fromValue(getNavigationByte());
|
||||
}
|
||||
public void setNavigation(Navigation navigation){
|
||||
setNavigation(navigation.getByteValue());
|
||||
}
|
||||
public void setInputFlags(byte b){
|
||||
if(getConfigSize()<SIZE_28){
|
||||
if(b==0){
|
||||
@ -300,12 +344,18 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
mValuesContainer.put(OFFSET_inputFlags, b);
|
||||
}
|
||||
public byte getInputFlags(){
|
||||
public byte getInputFlagsValue(){
|
||||
if(getConfigSize()<SIZE_28){
|
||||
return 0;
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_inputFlags);
|
||||
}
|
||||
public String getInputFlags(){
|
||||
return ResConfigHelper.decodeInputFlags(getInputFlagsValue());
|
||||
}
|
||||
public void setInputFlags(String inputFlags){
|
||||
setInputFlags(ResConfigHelper.encodeInputFlags(inputFlags));
|
||||
}
|
||||
public void setInputPad0(byte b){
|
||||
if(getConfigSize()<SIZE_28){
|
||||
if(b==0){
|
||||
@ -394,12 +444,18 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
mValuesContainer.put(OFFSET_screenLayout, b);
|
||||
}
|
||||
public byte getScreenLayout(){
|
||||
public byte getScreenLayoutValue(){
|
||||
if(getConfigSize()<SIZE_32){
|
||||
return 0;
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_screenLayout);
|
||||
}
|
||||
public String getScreenLayout(){
|
||||
return ResConfigHelper.decodeScreenLayout(getScreenLayoutValue());
|
||||
}
|
||||
public void setScreenLayout(String screenLayout){
|
||||
setScreenLayout(ResConfigHelper.encodeScreenLayout(screenLayout));
|
||||
}
|
||||
public void setUiMode(byte b){
|
||||
if(getConfigSize()<SIZE_32){
|
||||
if(b==0){
|
||||
@ -409,12 +465,18 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
}
|
||||
mValuesContainer.put(OFFSET_uiMode, b);
|
||||
}
|
||||
public byte getUiMode(){
|
||||
public byte getUiModeValue(){
|
||||
if(getConfigSize()<SIZE_32){
|
||||
return 0;
|
||||
}
|
||||
return mValuesContainer.get(OFFSET_uiMode);
|
||||
}
|
||||
public String getUiMode(){
|
||||
return ResConfigHelper.decodeUiMode(getUiModeValue());
|
||||
}
|
||||
public void setUiMode(String uiMode){
|
||||
setUiMode(ResConfigHelper.encodeUiMode(uiMode));
|
||||
}
|
||||
public void setSmallestScreenWidthDp(short sh){
|
||||
if(getConfigSize()<SIZE_32){
|
||||
if(sh==0){
|
||||
@ -562,6 +624,119 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
return isNull(mValuesContainer.getBytes());
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
if(isDefault()){
|
||||
return jsonObject;
|
||||
}
|
||||
int val=getMcc();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_mcc, val);
|
||||
}
|
||||
val=getMnc();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_mnc, val);
|
||||
}
|
||||
String str=getLanguage();
|
||||
if(str!=null){
|
||||
jsonObject.put(NAME_language, str);
|
||||
}
|
||||
str=getRegion();
|
||||
if(str!=null){
|
||||
jsonObject.put(NAME_region, str);
|
||||
}
|
||||
Orientation orientation=getOrientation();
|
||||
if(orientation!=Orientation.ANY){
|
||||
jsonObject.put(NAME_orientation, orientation.toString());
|
||||
}
|
||||
Touchscreen touchscreen=getTouchscreen();
|
||||
if(touchscreen!=Touchscreen.NONE){
|
||||
jsonObject.put(NAME_touchscreen, touchscreen.toString());
|
||||
}
|
||||
str = getDensity();
|
||||
if(str!=null){
|
||||
jsonObject.put(NAME_density, str);
|
||||
}
|
||||
Keyboard keyboard = getKeyboard();
|
||||
if(keyboard!=Keyboard.NONE){
|
||||
jsonObject.put(NAME_keyboard, keyboard.toString());
|
||||
}
|
||||
Navigation navigation = getNavigation();
|
||||
if(navigation!=Navigation.NONE){
|
||||
jsonObject.put(NAME_navigation, navigation.toString());
|
||||
}
|
||||
str = getInputFlags();
|
||||
if(str!=null){
|
||||
jsonObject.put(NAME_inputFlags, str);
|
||||
}
|
||||
val = getScreenWidth();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_screenWidth, val);
|
||||
}
|
||||
val = getScreenHeight();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_screenHeight, val);
|
||||
}
|
||||
val = getSdkVersion();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_sdkVersion, val);
|
||||
}
|
||||
val = getMinorVersion();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_minorVersion, val);
|
||||
}
|
||||
str = getScreenLayout();
|
||||
if(str!=null){
|
||||
jsonObject.put(NAME_screenLayout, str);
|
||||
}
|
||||
str = getUiMode();
|
||||
if(str!=null){
|
||||
jsonObject.put(NAME_uiMode, str);
|
||||
}
|
||||
val = getSmallestScreenWidthDp();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_smallestScreenWidthDp, val);
|
||||
}
|
||||
val = getScreenWidthDp();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_screenWidthDp, val);
|
||||
}
|
||||
val = getScreenHeightDp();
|
||||
if(val!=0){
|
||||
jsonObject.put(NAME_screenHeightDp, val);
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
if(json.isEmpty()){
|
||||
mValuesContainer.fill((byte) 0);
|
||||
return;
|
||||
}
|
||||
trimToSize(SIZE_64);
|
||||
|
||||
setMcc((short) json.optInt(NAME_mcc));
|
||||
setMnc((short) json.optInt(NAME_mnc));
|
||||
setLanguage(json.optString(NAME_language));
|
||||
setOrientation(Orientation.fromName(json.optString(NAME_orientation)));
|
||||
setTouchscreen(Touchscreen.fromName(json.optString(NAME_touchscreen)));
|
||||
setDensity(json.optString(NAME_density));
|
||||
setKeyboard(Keyboard.fromName(json.optString(NAME_keyboard)));
|
||||
setNavigation(Navigation.fromName(json.optString(NAME_navigation)));
|
||||
setInputFlags(json.optString(NAME_inputFlags));
|
||||
setScreenWidth((short) json.optInt(NAME_screenWidth));
|
||||
setScreenHeight((short) json.optInt(NAME_screenHeight));
|
||||
setSdkVersion((short) json.optInt(NAME_sdkVersion));
|
||||
setMinorVersion((short) json.optInt(NAME_minorVersion));
|
||||
setScreenLayout(json.optString(NAME_screenLayout));
|
||||
setUiMode(json.optString(NAME_uiMode));
|
||||
setSmallestScreenWidthDp((short) json.optInt(NAME_smallestScreenWidthDp));
|
||||
setScreenWidthDp((short) json.optInt(NAME_screenWidthDp));
|
||||
setScreenHeightDp((short) json.optInt(NAME_screenHeightDp));
|
||||
|
||||
trimToSize(SIZE_48);
|
||||
}
|
||||
@Override
|
||||
public int hashCode(){
|
||||
byte[] bts = ByteArray.trimTrailZeros(mValuesContainer.getBytes());
|
||||
return Arrays.hashCode(bts);
|
||||
@ -706,6 +881,161 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
System.arraycopy(bts, 0, result, 0, max);
|
||||
return result;
|
||||
}
|
||||
public enum Orientation{
|
||||
ANY((byte) 0),
|
||||
PORT((byte) 0x1),
|
||||
LAND((byte) 0x2),
|
||||
SQUARE((byte) 0x3);
|
||||
private final byte mByteValue;
|
||||
Orientation(byte b) {
|
||||
this.mByteValue=b;
|
||||
}
|
||||
public byte getByteValue() {
|
||||
return mByteValue;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return name().toLowerCase();
|
||||
}
|
||||
public static Orientation fromValue(byte b){
|
||||
for(Orientation orientation:values()){
|
||||
if(b==orientation.getByteValue()){
|
||||
return orientation;
|
||||
}
|
||||
}
|
||||
return ANY;
|
||||
}
|
||||
public static Orientation fromName(String name){
|
||||
if(name==null){
|
||||
return ANY;
|
||||
}
|
||||
name=name.trim().toUpperCase();
|
||||
for(Orientation orientation:values()){
|
||||
if(name.equals(orientation.name())){
|
||||
return orientation;
|
||||
}
|
||||
}
|
||||
return ANY;
|
||||
}
|
||||
}
|
||||
public enum Touchscreen{
|
||||
NONE((byte) 0x0),
|
||||
NOTOUCH((byte) 0x1),
|
||||
STYLUS((byte) 0x2),
|
||||
FINGER((byte) 0x3);
|
||||
private final byte mByteValue;
|
||||
Touchscreen(byte b) {
|
||||
this.mByteValue=b;
|
||||
}
|
||||
public byte getByteValue() {
|
||||
return mByteValue;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return name().toLowerCase();
|
||||
}
|
||||
public static Touchscreen fromValue(byte b){
|
||||
for(Touchscreen touchscreen:values()){
|
||||
if(b==touchscreen.getByteValue()){
|
||||
return touchscreen;
|
||||
}
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
public static Touchscreen fromName(String name){
|
||||
if(name==null){
|
||||
return NONE;
|
||||
}
|
||||
name=name.trim().toUpperCase();
|
||||
for(Touchscreen touchscreen:values()){
|
||||
if(name.equals(touchscreen.name())){
|
||||
return touchscreen;
|
||||
}
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
public enum Keyboard{
|
||||
NONE((byte) 0x0),
|
||||
NOKEYS((byte) 0x1),
|
||||
QWERTY((byte) 0x2),
|
||||
KEY12((byte) 0x3);
|
||||
private final byte mByteValue;
|
||||
Keyboard(byte b) {
|
||||
this.mByteValue=b;
|
||||
}
|
||||
public byte getByteValue() {
|
||||
return mByteValue;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
if(this==KEY12){
|
||||
return "12key";
|
||||
}
|
||||
return name().toLowerCase();
|
||||
}
|
||||
public static Keyboard fromValue(byte b){
|
||||
for(Keyboard keyboard:values()){
|
||||
if(b==keyboard.getByteValue()){
|
||||
return keyboard;
|
||||
}
|
||||
}
|
||||
return NOKEYS;
|
||||
}
|
||||
public static Keyboard fromName(String name){
|
||||
if(name==null){
|
||||
return NOKEYS;
|
||||
}
|
||||
name=name.trim().toUpperCase();
|
||||
if(name.equals("12KEY")){
|
||||
return KEY12;
|
||||
}
|
||||
for(Keyboard keyboard:values()){
|
||||
if(name.equals(keyboard.name())){
|
||||
return keyboard;
|
||||
}
|
||||
}
|
||||
return NOKEYS;
|
||||
}
|
||||
}
|
||||
public enum Navigation{
|
||||
NONE((byte) 0),
|
||||
NONAV((byte) 0x1),
|
||||
DPAD((byte) 0x2),
|
||||
TRACKBALL((byte) 0x3),
|
||||
WHEEL((byte) 0x4);
|
||||
private final byte mByteValue;
|
||||
Navigation(byte b) {
|
||||
this.mByteValue=b;
|
||||
}
|
||||
public byte getByteValue() {
|
||||
return mByteValue;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return name().toLowerCase();
|
||||
}
|
||||
public static Navigation fromValue(byte b){
|
||||
for(Navigation navigation:values()){
|
||||
if(b==navigation.getByteValue()){
|
||||
return navigation;
|
||||
}
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
public static Navigation fromName(String name){
|
||||
if(name==null){
|
||||
return NONE;
|
||||
}
|
||||
name=name.trim().toUpperCase();
|
||||
for(Navigation navigation:values()){
|
||||
if(name.equals(navigation.name())){
|
||||
return navigation;
|
||||
}
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int SIZE_16 = 16;
|
||||
public static final int SIZE_28 = 28;
|
||||
@ -753,4 +1083,34 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad {
|
||||
private static final int LEN_localeScript = 4;
|
||||
private static final int LEN_localeVariant = 8;
|
||||
|
||||
private static final String NAME_mcc = "mcc";
|
||||
private static final String NAME_mnc = "mnc";
|
||||
private static final String NAME_language = "language";
|
||||
private static final String NAME_region = "region";
|
||||
private static final String NAME_orientation = "orientation";
|
||||
private static final String NAME_touchscreen = "touchscreen";
|
||||
private static final String NAME_density = "density";
|
||||
//SIZE=16
|
||||
private static final String NAME_keyboard = "keyboard";
|
||||
private static final String NAME_navigation = "navigation";
|
||||
private static final String NAME_inputFlags = "inputFlags";
|
||||
private static final String NAME_inputPad0 = "inputPad0";
|
||||
private static final String NAME_screenWidth = "screenWidth";
|
||||
private static final String NAME_screenHeight = "screenHeight";
|
||||
private static final String NAME_sdkVersion = "sdkVersion";
|
||||
private static final String NAME_minorVersion = "minorVersion";
|
||||
//SIZE=28
|
||||
private static final String NAME_screenLayout = "screenLayout";
|
||||
private static final String NAME_uiMode = "uiMode";
|
||||
private static final String NAME_smallestScreenWidthDp = "smallestScreenWidthDp";
|
||||
//SIZE=32 = "";
|
||||
private static final String NAME_screenWidthDp = "screenWidthDp";
|
||||
private static final String NAME_screenHeightDp = "screenHeightDp";
|
||||
//SIZE=36
|
||||
private static final String NAME_localeScript = "localeScript";
|
||||
private static final String NAME_localeVariant = "localeVariant";
|
||||
private static final String NAME_screenLayout2 = "screenLayout2";
|
||||
private static final String NAME_colorMode = "colorMode";
|
||||
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ public class ResConfigHelper {
|
||||
ResConfig result=new ResConfig();
|
||||
result.setConfigSize(ResConfig.SIZE_64);
|
||||
parseQualifiers(result, qualifiers);
|
||||
result.refresh();
|
||||
return result;
|
||||
}
|
||||
static String toQualifier(ResConfig resConfig){
|
||||
@ -137,9 +138,29 @@ public class ResConfigHelper {
|
||||
char[] chs=country.toCharArray();
|
||||
resConfig.setRegion(chs);
|
||||
}
|
||||
public static String decodeLanguage(char[] language){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
if(language[0]!=0){
|
||||
builder.append(language[0]).append(language[1]);
|
||||
}
|
||||
if(builder.length()==0){
|
||||
return null;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
public static String decodeRegion(char[] region){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
if(region[0]!=0){
|
||||
builder.append(region[0]).append(region[1]);
|
||||
}
|
||||
if(builder.length()==0){
|
||||
return null;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
public static String decodeLocale(ResConfig resConfig){
|
||||
char[] region=resConfig.getRegion();
|
||||
char[] language=resConfig.getLanguage();
|
||||
char[] region=resConfig.getRegionChars();
|
||||
char[] language=resConfig.getLanguageChars();
|
||||
StringBuilder builder=new StringBuilder();
|
||||
if(language[0]!=0){
|
||||
builder.append(language[0]).append(language[1]);
|
||||
@ -159,8 +180,8 @@ public class ResConfigHelper {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
char[] localeVariant=resConfig.getLocaleVariant();
|
||||
char[] localeScript=resConfig.getLocaleScript();
|
||||
char[] region=resConfig.getRegion();
|
||||
char[] language=resConfig.getLanguage();
|
||||
char[] region=resConfig.getRegionChars();
|
||||
char[] language=resConfig.getLanguageChars();
|
||||
if (localeVariant == null && localeScript == null && (region[0] != '\00' || language[0] != '\00') &&
|
||||
region.length != 3) {
|
||||
builder.append("-").append(language);
|
||||
@ -217,7 +238,7 @@ public class ResConfigHelper {
|
||||
}
|
||||
private static String decodeNavigation(ResConfig resConfig){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
switch (resConfig.getNavigation()) {
|
||||
switch (resConfig.getNavigationByte()) {
|
||||
case NAVIGATION_NONAV:
|
||||
ret.append("-nonav");
|
||||
break;
|
||||
@ -265,9 +286,45 @@ public class ResConfigHelper {
|
||||
}
|
||||
resConfig.setInputFlags((byte)inputFlags);
|
||||
}
|
||||
public static byte encodeInputFlags(String inputFlags){
|
||||
if(inputFlags==null){
|
||||
return 0;
|
||||
}
|
||||
String[] split=inputFlags.split("-");
|
||||
int result=0;
|
||||
for(int i=0;i<split.length;i++){
|
||||
String s=split[i];
|
||||
if(s==null){
|
||||
continue;
|
||||
}
|
||||
int val;
|
||||
switch (s) {
|
||||
case "keysexposed":
|
||||
val = (KEYSHIDDEN_NO);
|
||||
break;
|
||||
case "keyshidden":
|
||||
val = (KEYSHIDDEN_YES);
|
||||
break;
|
||||
case "keyssoft":
|
||||
val = (KEYSHIDDEN_SOFT);
|
||||
break;
|
||||
case "navexposed":
|
||||
val = (NAVHIDDEN_NO);
|
||||
break;
|
||||
case "navhidden":
|
||||
val = (NAVHIDDEN_YES);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
result=(result | val);
|
||||
split[i]=null;
|
||||
}
|
||||
return (byte)result;
|
||||
}
|
||||
private static String decodeInputFlags(ResConfig resConfig){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
int inputFlags=resConfig.getInputFlags();
|
||||
int inputFlags=resConfig.getInputFlagsValue();
|
||||
switch (inputFlags & MASK_KEYSHIDDEN) {
|
||||
case KEYSHIDDEN_NO:
|
||||
ret.append("-keysexposed");
|
||||
@ -289,6 +346,32 @@ public class ResConfigHelper {
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
public static String decodeInputFlags(byte inputFlags){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
switch (inputFlags & MASK_KEYSHIDDEN) {
|
||||
case KEYSHIDDEN_NO:
|
||||
builder.append("-keysexposed");
|
||||
break;
|
||||
case KEYSHIDDEN_YES:
|
||||
builder.append("-keyshidden");
|
||||
break;
|
||||
case KEYSHIDDEN_SOFT:
|
||||
builder.append("-keyssoft");
|
||||
break;
|
||||
}
|
||||
switch (inputFlags & MASK_NAVHIDDEN) {
|
||||
case NAVHIDDEN_NO:
|
||||
builder.append("-navexposed");
|
||||
break;
|
||||
case NAVHIDDEN_YES:
|
||||
builder.append("-navhidden");
|
||||
break;
|
||||
}
|
||||
if(builder.length()==0){
|
||||
return null;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
private static void encodeKeyboard(ResConfig resConfig, String[] split){
|
||||
byte keyboard=0;
|
||||
for(int i=0;i<split.length;i++){
|
||||
@ -316,7 +399,7 @@ public class ResConfigHelper {
|
||||
}
|
||||
private static String decodeKeyboard(ResConfig resConfig){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
switch (resConfig.getKeyboard()) {
|
||||
switch (resConfig.getKeyboardByte()) {
|
||||
case KEYBOARD_NOKEYS:
|
||||
ret.append("-nokeys");
|
||||
break;
|
||||
@ -329,6 +412,39 @@ public class ResConfigHelper {
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
public static short encodeDensity(String densityName){
|
||||
short density=0;
|
||||
if(densityName==null){
|
||||
return density;
|
||||
}
|
||||
Matcher matcher=PATTERN_DENSITY.matcher(densityName);
|
||||
if(!matcher.find()){
|
||||
return density;
|
||||
}
|
||||
String d=matcher.group("A");
|
||||
if("l".equals(d)){
|
||||
density = DENSITY_LOW;
|
||||
}else if("m".equals(d)){
|
||||
density = DENSITY_MEDIUM;
|
||||
}else if("h".equals(d)){
|
||||
density = DENSITY_HIGH;
|
||||
}else if("tv".equals(d)){
|
||||
density = DENSITY_TV;
|
||||
}else if("xh".equals(d)){
|
||||
density = DENSITY_XHIGH;
|
||||
}else if("xxh".equals(d)){
|
||||
density = DENSITY_XXHIGH;
|
||||
}else if("xxxh".equals(d)){
|
||||
density = DENSITY_XXXHIGH;
|
||||
}else if("any".equals(d)){
|
||||
density = DENSITY_ANY;
|
||||
}else if("no".equals(d)){
|
||||
density = DENSITY_NONE;
|
||||
}else if(isDecimal(d)){
|
||||
density = (short) Integer.parseInt(d);
|
||||
}
|
||||
return density;
|
||||
}
|
||||
private static void encodeDensity(ResConfig resConfig, String[] split){
|
||||
int density=0;
|
||||
for(int i=0;i<split.length;i++){
|
||||
@ -371,7 +487,7 @@ public class ResConfigHelper {
|
||||
}
|
||||
private static String decodeDensity(ResConfig resConfig){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
int density=resConfig.getDensity();
|
||||
int density=resConfig.getDensityValue();
|
||||
switch (density) {
|
||||
case DENSITY_DEFAULT:
|
||||
break;
|
||||
@ -407,6 +523,32 @@ public class ResConfigHelper {
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
public static String decodeDensity(short density){
|
||||
switch (density) {
|
||||
case DENSITY_DEFAULT:
|
||||
return null;
|
||||
case DENSITY_LOW:
|
||||
return "ldpi";
|
||||
case DENSITY_MEDIUM:
|
||||
return "mdpi";
|
||||
case DENSITY_HIGH:
|
||||
return "hdpi";
|
||||
case DENSITY_TV:
|
||||
return "tvdpi";
|
||||
case DENSITY_XHIGH:
|
||||
return "xhdpi";
|
||||
case DENSITY_XXHIGH:
|
||||
return "xxhdpi";
|
||||
case DENSITY_XXXHIGH:
|
||||
return "xxxhdpi";
|
||||
case DENSITY_ANY:
|
||||
return "anydpi";
|
||||
case DENSITY_NONE:
|
||||
return "nodpi";
|
||||
default:
|
||||
return density+"dpi";
|
||||
}
|
||||
}
|
||||
private static void encodeTouchscreen(ResConfig resConfig, String[] split){
|
||||
byte touchscreen=0;
|
||||
for(int i=0;i<split.length;i++){
|
||||
@ -434,7 +576,7 @@ public class ResConfigHelper {
|
||||
}
|
||||
private static String decodeTouchscreen(ResConfig resConfig){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
byte touchscreen=resConfig.getTouchscreen();
|
||||
byte touchscreen=resConfig.getTouchscreenByte();
|
||||
switch (touchscreen) {
|
||||
case TOUCHSCREEN_NOTOUCH:
|
||||
ret.append("-notouch");
|
||||
@ -514,9 +656,129 @@ public class ResConfigHelper {
|
||||
}
|
||||
resConfig.setUiMode((byte)uiMode);
|
||||
}
|
||||
public static byte encodeUiMode(String uiMode){
|
||||
if(uiMode==null){
|
||||
return 0;
|
||||
}
|
||||
String[] split=uiMode.split("-");
|
||||
int result=0;
|
||||
for(int i=0;i<split.length;i++){
|
||||
String s=split[i];
|
||||
if(s==null){
|
||||
continue;
|
||||
}
|
||||
int val;
|
||||
switch (s) {
|
||||
case "car":
|
||||
val = (UI_MODE_TYPE_CAR);
|
||||
break;
|
||||
case "desk":
|
||||
val = (UI_MODE_TYPE_DESK);
|
||||
break;
|
||||
case "television":
|
||||
val = (UI_MODE_TYPE_TELEVISION);
|
||||
break;
|
||||
case "smallui":
|
||||
val = (UI_MODE_TYPE_SMALLUI);
|
||||
break;
|
||||
case "mediumui":
|
||||
val = (UI_MODE_TYPE_MEDIUMUI);
|
||||
break;
|
||||
case "largeui":
|
||||
val = (UI_MODE_TYPE_LARGEUI);
|
||||
break;
|
||||
case "godzillaui":
|
||||
val = (UI_MODE_TYPE_GODZILLAUI);
|
||||
break;
|
||||
case "hugeui":
|
||||
val = (UI_MODE_TYPE_HUGEUI);
|
||||
break;
|
||||
case "appliance":
|
||||
val = (UI_MODE_TYPE_APPLIANCE);
|
||||
break;
|
||||
case "watch":
|
||||
val = (UI_MODE_TYPE_WATCH);
|
||||
break;
|
||||
case "vrheadset":
|
||||
val = (UI_MODE_TYPE_VR_HEADSET);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
result=(result | val);
|
||||
split[i]=null;
|
||||
}
|
||||
for(int i=0;i<split.length;i++){
|
||||
String s=split[i];
|
||||
if(s==null){
|
||||
continue;
|
||||
}
|
||||
int val;
|
||||
if("night".equals(s)){
|
||||
val = (UI_MODE_NIGHT_YES);
|
||||
}else if("notnight".equals(s)){
|
||||
val = (UI_MODE_NIGHT_NO);
|
||||
}else {
|
||||
continue;
|
||||
}
|
||||
result=(result | val);
|
||||
split[i]=null;
|
||||
}
|
||||
return (byte)result;
|
||||
}
|
||||
public static String decodeUiMode(byte uiMode){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
switch (uiMode & MASK_UI_MODE_TYPE) {
|
||||
case UI_MODE_TYPE_CAR:
|
||||
ret.append("-car");
|
||||
break;
|
||||
case UI_MODE_TYPE_DESK:
|
||||
ret.append("-desk");
|
||||
break;
|
||||
case UI_MODE_TYPE_TELEVISION:
|
||||
ret.append("-television");
|
||||
break;
|
||||
case UI_MODE_TYPE_SMALLUI:
|
||||
ret.append("-smallui");
|
||||
break;
|
||||
case UI_MODE_TYPE_MEDIUMUI:
|
||||
ret.append("-mediumui");
|
||||
break;
|
||||
case UI_MODE_TYPE_LARGEUI:
|
||||
ret.append("-largeui");
|
||||
break;
|
||||
case UI_MODE_TYPE_GODZILLAUI:
|
||||
ret.append("-godzillaui");
|
||||
break;
|
||||
case UI_MODE_TYPE_HUGEUI:
|
||||
ret.append("-hugeui");
|
||||
break;
|
||||
case UI_MODE_TYPE_APPLIANCE:
|
||||
ret.append("-appliance");
|
||||
break;
|
||||
case UI_MODE_TYPE_WATCH:
|
||||
ret.append("-watch");
|
||||
break;
|
||||
case UI_MODE_TYPE_VR_HEADSET:
|
||||
ret.append("-vrheadset");
|
||||
break;
|
||||
}
|
||||
switch (uiMode & MASK_UI_MODE_NIGHT) {
|
||||
case UI_MODE_NIGHT_YES:
|
||||
ret.append("-night");
|
||||
break;
|
||||
case UI_MODE_NIGHT_NO:
|
||||
ret.append("-notnight");
|
||||
break;
|
||||
}
|
||||
if(ret.length()==0){
|
||||
return null;
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
private static String decodeUiMode(ResConfig resConfig){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
byte uiMode=resConfig.getUiMode();
|
||||
byte uiMode=resConfig.getUiModeValue();
|
||||
switch (uiMode & MASK_UI_MODE_TYPE) {
|
||||
case UI_MODE_TYPE_CAR:
|
||||
ret.append("-car");
|
||||
@ -583,7 +845,7 @@ public class ResConfigHelper {
|
||||
}
|
||||
private static String decodeOrientation(ResConfig resConfig){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
byte orientation=resConfig.getOrientation();
|
||||
byte orientation=resConfig.getOrientationByte();
|
||||
switch (orientation) {
|
||||
case ORIENTATION_PORT:
|
||||
ret.append("-port");
|
||||
@ -597,6 +859,17 @@ public class ResConfigHelper {
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
public static String decodeOrientation(byte orientation){
|
||||
switch (orientation) {
|
||||
case ORIENTATION_PORT:
|
||||
return "port";
|
||||
case ORIENTATION_LAND:
|
||||
return "land";
|
||||
case ORIENTATION_SQUARE:
|
||||
return "square";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static void encodeScreenLayout(ResConfig resConfig, String[] split){
|
||||
int screenLayout=0;
|
||||
for(int i=0;i<split.length;i++){
|
||||
@ -638,9 +911,54 @@ public class ResConfigHelper {
|
||||
}
|
||||
resConfig.setScreenLayout((byte) screenLayout);
|
||||
}
|
||||
public static byte encodeScreenLayout(String screenLayout){
|
||||
if(screenLayout==null){
|
||||
return 0;
|
||||
}
|
||||
String[] split=screenLayout.split("-");
|
||||
int result=0;
|
||||
for(int i=0;i<split.length;i++){
|
||||
String s=split[i];
|
||||
if(s==null){
|
||||
continue;
|
||||
}
|
||||
int val;
|
||||
switch (s) {
|
||||
case "ldrtl":
|
||||
val = (SCREENLAYOUT_LAYOUTDIR_RTL);
|
||||
break;
|
||||
case "ldltr":
|
||||
val = (SCREENLAYOUT_LAYOUTDIR_LTR);
|
||||
break;
|
||||
case "small":
|
||||
val = (SCREENSIZE_SMALL);
|
||||
break;
|
||||
case "normal":
|
||||
val = (SCREENSIZE_NORMAL);
|
||||
break;
|
||||
case "large":
|
||||
val = (SCREENSIZE_LARGE);
|
||||
break;
|
||||
case "xlarge":
|
||||
val = (SCREENSIZE_XLARGE);
|
||||
break;
|
||||
case "long":
|
||||
val = (SCREENLONG_YES);
|
||||
break;
|
||||
case "notlong":
|
||||
val = (SCREENLONG_NO);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
result = (result | val);
|
||||
split[i]=null;
|
||||
}
|
||||
return (byte) result;
|
||||
}
|
||||
private static String decodeScreenLayout(ResConfig resConfig){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
byte screenLayout=resConfig.getScreenLayout();
|
||||
byte screenLayout=resConfig.getScreenLayoutValue();
|
||||
switch (screenLayout & MASK_LAYOUTDIR) {
|
||||
case SCREENLAYOUT_LAYOUTDIR_RTL:
|
||||
ret.append("-ldrtl");
|
||||
@ -672,6 +990,42 @@ public class ResConfigHelper {
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
public static String decodeScreenLayout(byte screenLayout){
|
||||
StringBuilder ret=new StringBuilder();
|
||||
switch (screenLayout & MASK_LAYOUTDIR) {
|
||||
case SCREENLAYOUT_LAYOUTDIR_RTL:
|
||||
ret.append("-ldrtl");
|
||||
break;
|
||||
case SCREENLAYOUT_LAYOUTDIR_LTR:
|
||||
ret.append("-ldltr");
|
||||
}
|
||||
switch (screenLayout & MASK_SCREENSIZE) {
|
||||
case SCREENSIZE_SMALL:
|
||||
ret.append("-small");
|
||||
break;
|
||||
case SCREENSIZE_NORMAL:
|
||||
ret.append("-normal");
|
||||
break;
|
||||
case SCREENSIZE_LARGE:
|
||||
ret.append("-large");
|
||||
break;
|
||||
case SCREENSIZE_XLARGE:
|
||||
ret.append("-xlarge");
|
||||
break;
|
||||
}
|
||||
switch (screenLayout & MASK_SCREENLONG) {
|
||||
case SCREENLONG_YES:
|
||||
ret.append("-long");
|
||||
break;
|
||||
case SCREENLONG_NO:
|
||||
ret.append("-notlong");
|
||||
break;
|
||||
}
|
||||
if(ret.length()==0){
|
||||
return null;
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
private static void encodeScreenLayout2(ResConfig resConfig, String[] split){
|
||||
int screenLayout2=0;
|
||||
for(int i=0;i<split.length;i++){
|
||||
|
@ -6,6 +6,8 @@ import com.reandroid.lib.arsc.base.BlockCounter;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.ReferenceItem;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@ -127,9 +129,28 @@ public class ResValueBag extends BaseResValue {
|
||||
mResValueBagItemArray.setChildesCount(mCount.get());
|
||||
mResValueBagItemArray.readBytes(reader);
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_parent, getParentId());
|
||||
jsonObject.put(NAME_items, getResValueBagItemArray().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setParentId(json.getInt(NAME_parent));
|
||||
getResValueBagItemArray().fromJson(json.getJSONArray(NAME_items));
|
||||
refreshCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
if(getParent()!=null){
|
||||
return toJson().toString(4);
|
||||
}
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
builder.append(": parent=");
|
||||
@ -139,6 +160,4 @@ public class ResValueBag extends BaseResValue {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
private final static short HEADER_COMPLEX=0x0010;
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package com.reandroid.lib.arsc.value;
|
||||
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.item.ReferenceItem;
|
||||
import com.reandroid.lib.arsc.item.TableString;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class ResValueBagItem extends BaseResValueItem{
|
||||
|
||||
@ -9,6 +11,22 @@ public class ResValueBagItem extends BaseResValueItem{
|
||||
super(BYTES_COUNT);
|
||||
setHeaderSize(BYTES_SIZE);
|
||||
}
|
||||
public String getValueAsString(){
|
||||
return getTableString(getData()).getHtml();
|
||||
}
|
||||
public void setValueAsString(String str){
|
||||
setType(ValueType.STRING);
|
||||
TableString tableString=getTableStringPool().getOrCreate(str);
|
||||
setData(tableString.getIndex());
|
||||
}
|
||||
public boolean getValueAsBoolean(){
|
||||
return getData()!=0;
|
||||
}
|
||||
public void setValueAsBoolean(boolean val){
|
||||
setType(ValueType.INT_BOOLEAN);
|
||||
int data=val?0xffffffff:0;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
public ResValueBag getParentBag(){
|
||||
Block parent=getParent();
|
||||
@ -128,6 +146,37 @@ public class ResValueBagItem extends BaseResValueItem{
|
||||
setShort(OFFSET_DATA+2, val);
|
||||
afterDataValueChanged();
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
ValueType valueType=getValueType();
|
||||
jsonObject.put(NAME_value_type, valueType.name());
|
||||
jsonObject.put(NAME_id, getId());
|
||||
if(valueType==ValueType.STRING){
|
||||
jsonObject.put(NAME_data, getValueAsString());
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||
}else {
|
||||
jsonObject.put(NAME_data, getData());
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
||||
setType(valueType);
|
||||
setId(json.getInt(NAME_id));
|
||||
if(valueType==ValueType.STRING){
|
||||
setValueAsString(json.getString(NAME_data));
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||
}else {
|
||||
setData(json.getInt(NAME_data));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
|
@ -1,15 +1,30 @@
|
||||
package com.reandroid.lib.arsc.value;
|
||||
|
||||
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
|
||||
import java.io.IOException;
|
||||
import com.reandroid.lib.arsc.item.TableString;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class ResValueInt extends BaseResValueItem {
|
||||
public ResValueInt() {
|
||||
super(BYTES_COUNT);
|
||||
setHeaderSize(BYTES_SIZE);
|
||||
}
|
||||
public String getValueAsString(){
|
||||
return getString(getData());
|
||||
}
|
||||
public void setValueAsString(String str){
|
||||
setType(ValueType.STRING);
|
||||
TableString tableString=getTableStringPool().getOrCreate(str);
|
||||
setData(tableString.getIndex());
|
||||
}
|
||||
public void setValueAsBoolean(boolean val){
|
||||
setType(ValueType.INT_BOOLEAN);
|
||||
int data=val?0xffffffff:0;
|
||||
setData(data);
|
||||
}
|
||||
public boolean getValueAsBoolean(){
|
||||
return getData()!=0;
|
||||
}
|
||||
@Override
|
||||
public void setHeaderSize(short size) {
|
||||
setShort(OFFSET_SIZE, size);
|
||||
@ -58,11 +73,34 @@ public class ResValueInt extends BaseResValueItem {
|
||||
addTableReference(getTableStringReference());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onReadBytes(BlockReader reader) throws IOException {
|
||||
super.onReadBytes(reader);
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
ValueType valueType=getValueType();
|
||||
jsonObject.put(NAME_value_type, valueType.name());
|
||||
if(valueType==ValueType.STRING){
|
||||
jsonObject.put(NAME_data, getValueAsString());
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||
}else {
|
||||
jsonObject.put(NAME_data, getData());
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
||||
if(valueType==ValueType.STRING){
|
||||
setValueAsString(json.getString(NAME_data));
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||
}else {
|
||||
setType(valueType);
|
||||
setData(json.getInt(NAME_data));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
@ -97,6 +135,6 @@ public class ResValueInt extends BaseResValueItem {
|
||||
private static final int OFFSET_DATA=4;
|
||||
|
||||
private static final int BYTES_COUNT=8;
|
||||
|
||||
private static final short BYTES_SIZE=0x08;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.reandroid.lib.arsc.value;
|
||||
|
||||
import com.reandroid.lib.arsc.item.ReferenceItem;
|
||||
|
||||
public class ResValueReference implements ReferenceItem {
|
||||
private final BaseResValueItem resValueItem;
|
||||
public ResValueReference(BaseResValueItem resValueItem){
|
||||
this.resValueItem=resValueItem;
|
||||
}
|
||||
public EntryBlock getEntryBlock(){
|
||||
return resValueItem.getEntryBlock();
|
||||
}
|
||||
@Override
|
||||
public void set(int val) {
|
||||
resValueItem.setData(val);
|
||||
}
|
||||
@Override
|
||||
public int get() {
|
||||
return resValueItem.getData();
|
||||
}
|
||||
}
|
6
src/main/java/com/reandroid/lib/json/JsonItem.java
Normal file
6
src/main/java/com/reandroid/lib/json/JsonItem.java
Normal file
@ -0,0 +1,6 @@
|
||||
package com.reandroid.lib.json;
|
||||
|
||||
public interface JsonItem<T> {
|
||||
public T toJson();
|
||||
public void fromJson(T json);
|
||||
}
|
62
src/main/java/com/reandroid/lib/json/JsonUtil.java
Normal file
62
src/main/java/com/reandroid/lib/json/JsonUtil.java
Normal file
@ -0,0 +1,62 @@
|
||||
package com.reandroid.lib.json;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class JsonUtil {
|
||||
public static void writeJSONObject(JsonItem<JSONObject> jsonItem, File file) throws IOException{
|
||||
writeJSONObject(jsonItem, file, INDENT_FACTOR);
|
||||
}
|
||||
public static void writeJSONObject(JsonItem<JSONObject> jsonItem, File file, int indentFactor) throws IOException{
|
||||
File dir=file.getParentFile();
|
||||
if(dir!=null && !dir.exists()){
|
||||
dir.mkdirs();
|
||||
}
|
||||
FileOutputStream outputStream=new FileOutputStream(file);
|
||||
writeJSONObject(jsonItem, outputStream, indentFactor);
|
||||
}
|
||||
public static void writeJSONObject(JsonItem<JSONObject> jsonItem, OutputStream outputStream) throws IOException{
|
||||
writeJSONObject(jsonItem, outputStream, INDENT_FACTOR);
|
||||
}
|
||||
public static void writeJSONObject(JsonItem<JSONObject> jsonItem, OutputStream outputStream, int indentFactor) throws IOException{
|
||||
Writer writer=new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
|
||||
writer= writeJSONObject(jsonItem, writer, indentFactor);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
public static Writer writeJSONObject(JsonItem<JSONObject> jsonItem, Writer writer, int indentFactor){
|
||||
JSONObject jsonObject=jsonItem.toJson();
|
||||
return jsonObject.write(writer, indentFactor, 0);
|
||||
}
|
||||
|
||||
|
||||
public static void writeJSONArray(JsonItem<JSONArray> jsonItem, File file) throws IOException{
|
||||
writeJSONArray(jsonItem, file, INDENT_FACTOR);
|
||||
}
|
||||
public static void writeJSONArray(JsonItem<JSONArray> jsonItem, File file, int indentFactor) throws IOException{
|
||||
File dir=file.getParentFile();
|
||||
if(dir!=null && !dir.exists()){
|
||||
dir.mkdirs();
|
||||
}
|
||||
FileOutputStream outputStream=new FileOutputStream(file);
|
||||
writeJSONArray(jsonItem, outputStream, indentFactor);
|
||||
}
|
||||
public static void writeJSONArray(JsonItem<JSONArray> jsonItem, OutputStream outputStream) throws IOException{
|
||||
writeJSONArray(jsonItem, outputStream, INDENT_FACTOR);
|
||||
}
|
||||
public static void writeJSONArray(JsonItem<JSONArray> jsonItem, OutputStream outputStream, int indentFactor) throws IOException{
|
||||
Writer writer=new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
|
||||
writer= writeJSONArray(jsonItem, writer, indentFactor);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
public static Writer writeJSONArray(JsonItem<JSONArray> jsonItem, Writer writer, int indentFactor){
|
||||
JSONArray jsonArray=jsonItem.toJson();
|
||||
return jsonArray.write(writer, indentFactor, 0);
|
||||
}
|
||||
|
||||
private static final int INDENT_FACTOR=4;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user