mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 06:14:25 +02:00
V1.0.2
This commit is contained in:
parent
6c4d425a79
commit
4fe4657f9f
@ -2,7 +2,7 @@
|
||||
apply plugin: 'java-library'
|
||||
|
||||
group 'com.reandroid.lib.arsc'
|
||||
version '1.0.1'
|
||||
version '1.0.2'
|
||||
|
||||
java {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
|
@ -4,8 +4,6 @@ import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
public class EntryBlockArray extends OffsetBlockArray<EntryBlock> {
|
||||
public EntryBlockArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){
|
||||
@ -22,7 +20,9 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> {
|
||||
if(entryBlock!=null){
|
||||
return entryBlock;
|
||||
}
|
||||
ensureSize(entryId+1);
|
||||
int count=entryId+1;
|
||||
ensureSize(count);
|
||||
refreshCount();
|
||||
return get(entryId);
|
||||
}
|
||||
public EntryBlock getEntry(short entryId){
|
||||
|
@ -105,7 +105,7 @@ public abstract class OffsetBlockArray<T extends Block> extends BlockArray<T> im
|
||||
refreshCount();
|
||||
refreshStart();
|
||||
}
|
||||
private void refreshCount(){
|
||||
void refreshCount(){
|
||||
mItemCount.set(childesCount());
|
||||
}
|
||||
private void refreshStart(){
|
||||
|
@ -5,9 +5,7 @@ import com.reandroid.lib.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class SpecTypePairArray extends BlockArray<SpecTypePair> {
|
||||
public SpecTypePairArray(){
|
||||
@ -114,4 +112,32 @@ public class SpecTypePairArray extends BlockArray<SpecTypePair> {
|
||||
protected void onRefreshed() {
|
||||
|
||||
}
|
||||
@Override
|
||||
protected void onPreRefreshRefresh(){
|
||||
validateEntryCounts();
|
||||
}
|
||||
// For android API < 26, it is required to have equal entry count on all SpecTypePair
|
||||
private void validateEntryCounts(){
|
||||
Map<Byte, Integer> entryCountMap=mapHighestEntryCount();
|
||||
for(Map.Entry<Byte, Integer> entry:entryCountMap.entrySet()){
|
||||
byte id=entry.getKey();
|
||||
int count=entry.getValue();
|
||||
SpecTypePair pair=getPair(id);
|
||||
pair.getSpecBlock().setEntryCount(count);
|
||||
pair.getTypeBlockArray().setEntryCount(count);
|
||||
}
|
||||
}
|
||||
private Map<Byte, Integer> mapHighestEntryCount(){
|
||||
Map<Byte, Integer> results=new HashMap<>();
|
||||
SpecTypePair[] childes=getChildes();
|
||||
for (SpecTypePair pair:childes){
|
||||
int count=pair.getHighestEntryCount();
|
||||
byte id=pair.getTypeId();
|
||||
Integer exist=results.get(id);
|
||||
if(exist==null || count>exist){
|
||||
results.put(id, count);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import java.util.List;
|
||||
|
||||
public abstract class StringArray<T extends StringItem> extends OffsetBlockArray<T>{
|
||||
private boolean mUtf8;
|
||||
|
||||
public StringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) {
|
||||
super(offsets, itemCount, itemStart);
|
||||
this.mUtf8=is_utf8;
|
||||
|
@ -7,6 +7,7 @@ import com.reandroid.lib.arsc.chunk.SpecBlock;
|
||||
import com.reandroid.lib.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
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;
|
||||
|
||||
@ -207,4 +208,28 @@ public class TypeBlockArray extends BlockArray<TypeBlock> {
|
||||
typeBlock.readBytes(reader);
|
||||
return reader.getPosition()>pos;
|
||||
}
|
||||
public int getHighestEntryCount(){
|
||||
int result=0;
|
||||
for(TypeBlock typeBlock:getChildes()){
|
||||
int count=typeBlock.getEntryCount();
|
||||
if(count>result){
|
||||
result=count;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public void setEntryCount(int count){
|
||||
for(TypeBlock typeBlock:getChildes()){
|
||||
typeBlock.setEntryCount(count);
|
||||
}
|
||||
}
|
||||
public TypeString getTypeString(){
|
||||
for(TypeBlock typeBlock:getChildes()){
|
||||
TypeString typeString=typeBlock.getTypeString();
|
||||
if(typeString!=null){
|
||||
return typeString;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,17 @@ import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.TypeString;
|
||||
|
||||
public class TypeStringArray extends StringArray<TypeString> {
|
||||
private int lastCreateIndex;
|
||||
public TypeStringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) {
|
||||
super(offsets, itemCount, itemStart, is_utf8);
|
||||
}
|
||||
@Override
|
||||
public TypeString newInstance() {
|
||||
return new TypeString(isUtf8());
|
||||
TypeString typeString=new TypeString(isUtf8());
|
||||
//create default name
|
||||
this.lastCreateIndex++;
|
||||
typeString.set("type-"+lastCreateIndex);
|
||||
return typeString;
|
||||
}
|
||||
@Override
|
||||
public TypeString[] newInstance(int len) {
|
||||
|
@ -157,7 +157,7 @@ public abstract class BlockArray<T extends Block> extends BlockContainer<T> impl
|
||||
int result=-1;
|
||||
for(int i=0;i<len;i++){
|
||||
if(block==items[i]){
|
||||
result=-1;
|
||||
result=i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -20,12 +20,16 @@ public abstract class BlockContainer<T extends Block> extends Block{
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
protected void onPreRefreshRefresh(){
|
||||
|
||||
}
|
||||
protected abstract void onRefreshed();
|
||||
public final void refresh(){
|
||||
if(isNull()){
|
||||
return;
|
||||
}
|
||||
onPreRefreshRefresh();
|
||||
refreshChildes();
|
||||
onRefreshed();
|
||||
}
|
||||
@ -36,7 +40,7 @@ public abstract class BlockContainer<T extends Block> extends Block{
|
||||
for(int i=0;i<max;i++){
|
||||
T item=childes[i];
|
||||
if(item instanceof BlockContainer){
|
||||
BlockContainer container=(BlockContainer)item;
|
||||
BlockContainer<?> container=(BlockContainer<?>)item;
|
||||
container.refresh();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import com.reandroid.lib.arsc.group.EntryGroup;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.PackageName;
|
||||
import com.reandroid.lib.arsc.item.ReferenceItem;
|
||||
import com.reandroid.lib.arsc.item.TypeString;
|
||||
import com.reandroid.lib.arsc.pool.SpecStringPool;
|
||||
import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||
import com.reandroid.lib.arsc.pool.TypeStringPool;
|
||||
|
@ -50,13 +50,6 @@ public class TableBlock extends BaseChunk {
|
||||
refreshPackageCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onWriteBytes(OutputStream stream) throws IOException{
|
||||
int result=super.onWriteBytes(stream);
|
||||
stream.flush();
|
||||
stream.close();
|
||||
return result;
|
||||
}
|
||||
public void readBytes(File file) throws IOException{
|
||||
BlockReader reader=new BlockReader(file);
|
||||
super.readBytes(reader);
|
||||
@ -74,7 +67,9 @@ public class TableBlock extends BaseChunk {
|
||||
dir.mkdirs();
|
||||
}
|
||||
OutputStream outputStream=new FileOutputStream(file);
|
||||
return super.writeBytes(outputStream);
|
||||
int length = super.writeBytes(outputStream);
|
||||
outputStream.close();
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,13 +107,6 @@ public class ResXmlBlock extends BaseChunk {
|
||||
@Override
|
||||
protected void onChunkRefreshed() {
|
||||
|
||||
}
|
||||
@Override
|
||||
public int onWriteBytes(OutputStream stream) throws IOException{
|
||||
int result=super.onWriteBytes(stream);
|
||||
stream.flush();
|
||||
stream.close();
|
||||
return result;
|
||||
}
|
||||
public void readBytes(File file) throws IOException{
|
||||
BlockReader reader=new BlockReader(file);
|
||||
@ -132,7 +125,9 @@ public class ResXmlBlock extends BaseChunk {
|
||||
dir.mkdirs();
|
||||
}
|
||||
OutputStream outputStream=new FileOutputStream(file);
|
||||
return super.writeBytes(outputStream);
|
||||
int length = super.writeBytes(outputStream);
|
||||
outputStream.close();
|
||||
return length;
|
||||
}
|
||||
|
||||
public static boolean isResXmlBlock(File file){
|
||||
|
@ -9,6 +9,7 @@ import com.reandroid.lib.arsc.chunk.SpecBlock;
|
||||
import com.reandroid.lib.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
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;
|
||||
|
||||
@ -128,5 +129,15 @@ public class SpecTypePair extends BlockContainer<Block> {
|
||||
private void readUnexpectedNonSpecBlock(BlockReader reader, HeaderBlock headerBlock) throws IOException{
|
||||
throw new IOException("Unexpected block: "+headerBlock.toString()+", Should be: "+ChunkType.SPEC);
|
||||
}
|
||||
|
||||
public int getHighestEntryCount(){
|
||||
int specEntryCount=getSpecBlock().getEntryCount();
|
||||
int typeEntryCount=getTypeBlockArray().getHighestEntryCount();
|
||||
if(specEntryCount>typeEntryCount){
|
||||
return specEntryCount;
|
||||
}
|
||||
return typeEntryCount;
|
||||
}
|
||||
public TypeString getTypeString(){
|
||||
return getTypeBlockArray().getTypeString();
|
||||
}
|
||||
}
|
||||
|
@ -306,7 +306,9 @@ public class BlockReader extends InputStream {
|
||||
|
||||
private static byte[] loadBuffer(File file) throws IOException {
|
||||
FileInputStream in=new FileInputStream(file);
|
||||
return loadBuffer(in);
|
||||
byte[] result = loadBuffer(in);
|
||||
in.close();
|
||||
return result;
|
||||
}
|
||||
private static byte[] loadBuffer(InputStream in) throws IOException {
|
||||
byte[] result=new byte[0];
|
||||
|
@ -2,6 +2,7 @@ package com.reandroid.lib.arsc.pool;
|
||||
|
||||
import com.reandroid.lib.arsc.array.StringArray;
|
||||
import com.reandroid.lib.arsc.array.TypeStringArray;
|
||||
import com.reandroid.lib.arsc.group.StringGroup;
|
||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.TypeString;
|
||||
@ -13,6 +14,12 @@ public class TypeStringPool extends BaseStringPool<TypeString> {
|
||||
public TypeString getById(int id){
|
||||
return super.get(id-1);
|
||||
}
|
||||
public TypeString getOrCreate(int typeId, String typeName){
|
||||
getStringsArray().ensureSize(typeId);
|
||||
TypeString typeString=getById(typeId);
|
||||
typeString.set(typeName);
|
||||
return typeString;
|
||||
}
|
||||
@Override
|
||||
StringArray<TypeString> newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) {
|
||||
return new TypeStringArray(offsets, itemCount, itemStart, is_utf8);
|
||||
|
@ -1,22 +1,14 @@
|
||||
package com.reandroid.lib.arsc.value;
|
||||
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.lib.arsc.chunk.TableBlock;
|
||||
import com.reandroid.lib.arsc.item.BlockItem;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.ReferenceItem;
|
||||
import com.reandroid.lib.arsc.pool.SpecStringPool;
|
||||
import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BaseResValue extends BlockItem {
|
||||
BaseResValue(int bytesLength){
|
||||
super(bytesLength);
|
||||
}
|
||||
|
||||
|
||||
public EntryBlock getEntryBlock(){
|
||||
Block parent=getParent();
|
||||
while(parent!=null){
|
||||
@ -27,7 +19,6 @@ public abstract class BaseResValue extends BlockItem {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean removeSpecReference(ReferenceItem ref){
|
||||
EntryBlock entryBlock=getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
@ -56,15 +47,10 @@ public abstract class BaseResValue extends BlockItem {
|
||||
}
|
||||
entryBlock.addTableReference(ref);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onBytesChanged() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
int getInt(int offset){
|
||||
byte[] bts = getBytesInternal();
|
||||
return bts[offset] & 0xff |
|
||||
@ -83,7 +69,6 @@ public abstract class BaseResValue extends BlockItem {
|
||||
bts[offset]= (byte) (val & 0xff);
|
||||
onBytesChanged();
|
||||
}
|
||||
|
||||
void setShort(int offset, short val){
|
||||
if(val==getShort(offset)){
|
||||
return;
|
||||
|
@ -17,7 +17,7 @@ import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EntryBlock extends Block {
|
||||
public class EntryBlock extends Block{
|
||||
private ShortItem mHeaderSize;
|
||||
private ShortItem mFlags;
|
||||
private IntegerItem mSpecReference;
|
||||
@ -189,9 +189,13 @@ public class EntryBlock extends Block {
|
||||
|
||||
public void setFlagComplex(boolean is_complex){
|
||||
if(is_complex){
|
||||
setFlags(FLAG_COMPLEX);
|
||||
if(!isFlagsComplex()){
|
||||
setFlags(FLAG_COMPLEX);
|
||||
}
|
||||
}else {
|
||||
setFlags(FLAG_INT);
|
||||
if(isFlagsComplex()){
|
||||
setFlags(FLAG_INT);
|
||||
}
|
||||
}
|
||||
refreshHeaderSize();
|
||||
}
|
||||
@ -437,7 +441,14 @@ public class EntryBlock extends Block {
|
||||
if(isNull()){
|
||||
return 0;
|
||||
}
|
||||
return 8+mResValue.countBytes();
|
||||
/*
|
||||
mHeaderSize -> 2 bytes
|
||||
mFlags -> 2 bytes
|
||||
mSpecReference -> 4 bytes
|
||||
-------
|
||||
Total = 8 bytes, thus this value is always fixed no need to re-count
|
||||
*/
|
||||
return 8 + mResValue.countBytes();
|
||||
}
|
||||
@Override
|
||||
public void onCountUpTo(BlockCounter counter) {
|
||||
@ -514,6 +525,7 @@ public class EntryBlock extends Block {
|
||||
updatePackage();
|
||||
updateSpecRef();
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
@ -566,9 +578,10 @@ public class EntryBlock extends Block {
|
||||
|
||||
private final static short FLAG_COMPLEX_MASK = 0x0001;
|
||||
|
||||
private final static short FLAG_COMPLEX = 0x0003;
|
||||
private final static short FLAG_INT = 0x0002;
|
||||
private final static short FLAG_COMPLEX = 0x0001;
|
||||
private final static short FLAG_INT = 0x0000;
|
||||
|
||||
private final static short HEADER_COMPLEX=0x0010;
|
||||
private final static short HEADER_INT=0x0008;
|
||||
|
||||
}
|
||||
|
@ -2,8 +2,6 @@ package com.reandroid.lib.arsc.value;
|
||||
|
||||
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.ReferenceItem;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user