mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-04 16:14:24 +02:00
V1.0.3
This commit is contained in:
parent
1cf9ed2535
commit
0b2f3815db
@ -38,7 +38,8 @@ public class ApkJsonDecoder {
|
||||
private void writeUncompressed(File dir) throws IOException {
|
||||
File file=toUncompressedJsonFile(dir);
|
||||
UncompressedFiles uncompressedFiles=new UncompressedFiles();
|
||||
uncompressedFiles.add(apkModule.getApkArchive());
|
||||
uncompressedFiles.addCommonExtensions();
|
||||
uncompressedFiles.addPath(apkModule.getApkArchive());
|
||||
uncompressedFiles.toJson().write(file);
|
||||
}
|
||||
private void writeResources(File dir) throws IOException {
|
||||
|
@ -29,7 +29,19 @@ public class ApkModule {
|
||||
this.moduleName=moduleName;
|
||||
this.apkArchive=apkArchive;
|
||||
this.mUncompressedFiles=new UncompressedFiles();
|
||||
this.mUncompressedFiles.add(apkArchive);
|
||||
this.mUncompressedFiles.addPath(apkArchive);
|
||||
}
|
||||
public boolean isBaseModule(){
|
||||
if(!hasAndroidManifestBlock()){
|
||||
return false;
|
||||
}
|
||||
AndroidManifestBlock manifestBlock;
|
||||
try {
|
||||
manifestBlock=getAndroidManifestBlock();
|
||||
} catch (IOException ignored) {
|
||||
return false;
|
||||
}
|
||||
return manifestBlock.getMainActivity()!=null;
|
||||
}
|
||||
public String getModuleName(){
|
||||
return moduleName;
|
||||
@ -38,7 +50,19 @@ public class ApkModule {
|
||||
ZipArchive archive=new ZipArchive();
|
||||
archive.addAll(getApkArchive().listInputSources());
|
||||
UncompressedFiles uf=getUncompressedFiles();
|
||||
uf.setResRawDir("res/raw/");
|
||||
uf.apply(archive);
|
||||
int i=1;
|
||||
for(InputSource inputSource:archive.listInputSources()){
|
||||
if(inputSource.getSort()==0){
|
||||
inputSource.setSort(i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
InputSource manifest=archive.getInputSource(AndroidManifestBlock.FILE_NAME);
|
||||
if(manifest!=null){
|
||||
manifest.setSort(0);
|
||||
}
|
||||
ZipSerializer serializer=new ZipSerializer(archive.listInputSources(), false);
|
||||
serializer.writeZip(file);
|
||||
}
|
||||
|
@ -112,4 +112,7 @@ public class ApkUtil {
|
||||
public static final String PACKAGE_JSON_FILE="package.json";
|
||||
public static final String SPLIT_JSON_DIRECTORY="resources";
|
||||
public static final String DEF_MODULE_NAME="base";
|
||||
public static final String NAME_value_type="value_type";
|
||||
public static final String NAME_data="data";
|
||||
public static final String NAME_is_array="is_array";
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import com.reandroid.lib.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.lib.arsc.chunk.TableBlock;
|
||||
import com.reandroid.lib.arsc.pool.SpecStringPool;
|
||||
import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||
import com.reandroid.lib.arsc.value.ValueType;
|
||||
import com.reandroid.lib.json.JSONArray;
|
||||
import com.reandroid.lib.json.JSONException;
|
||||
import com.reandroid.lib.json.JSONObject;
|
||||
@ -73,12 +74,12 @@ public class StringPoolBuilder {
|
||||
return mSpecNameMap.get(pkgId);
|
||||
}
|
||||
private void scan(JSONObject jsonObject){
|
||||
if(jsonObject.has("is_array")){
|
||||
if(jsonObject.has(ApkUtil.NAME_is_array)){
|
||||
addSpecName(jsonObject.optString("name"));
|
||||
}
|
||||
if(jsonObject.has("value_type")){
|
||||
if("STRING".equals(jsonObject.getString("value_type"))){
|
||||
String data= jsonObject.getString("data");
|
||||
if(jsonObject.has(ApkUtil.NAME_value_type)){
|
||||
if(ValueType.STRING.name().equals(jsonObject.getString(ApkUtil.NAME_value_type))){
|
||||
String data= jsonObject.getString(ApkUtil.NAME_data);
|
||||
addTableString(data);
|
||||
}
|
||||
return;
|
||||
|
@ -4,6 +4,7 @@ import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.archive.ZipArchive;
|
||||
import com.reandroid.lib.json.JSONArray;
|
||||
import com.reandroid.lib.json.JSONConvert;
|
||||
import com.reandroid.lib.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -12,10 +13,16 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
public class UncompressedFiles implements JSONConvert<JSONArray> {
|
||||
public class UncompressedFiles implements JSONConvert<JSONObject> {
|
||||
private final Set<String> mPathList;
|
||||
private final Set<String> mExtensionList;
|
||||
private String mResRawDir;
|
||||
public UncompressedFiles(){
|
||||
this.mPathList=new HashSet<>();
|
||||
this.mExtensionList=new HashSet<>();
|
||||
}
|
||||
public void setResRawDir(String resRawDir){
|
||||
this.mResRawDir=resRawDir;
|
||||
}
|
||||
public void apply(ZipArchive archive){
|
||||
for(InputSource inputSource:archive.listInputSources()){
|
||||
@ -23,27 +30,60 @@ public class UncompressedFiles implements JSONConvert<JSONArray> {
|
||||
}
|
||||
}
|
||||
public void apply(InputSource inputSource){
|
||||
if(contains(inputSource.getName()) || contains(inputSource.getAlias())){
|
||||
if(isUncompressed(inputSource.getAlias()) || isUncompressed(inputSource.getName())){
|
||||
inputSource.setMethod(ZipEntry.STORED);
|
||||
}else {
|
||||
inputSource.setMethod(ZipEntry.DEFLATED);
|
||||
}
|
||||
}
|
||||
public boolean contains(String path){
|
||||
public boolean isUncompressed(String path){
|
||||
if(path==null){
|
||||
return false;
|
||||
}
|
||||
if(containsPath(path)||containsExtension(path)||isResRawDir(path)){
|
||||
return true;
|
||||
}
|
||||
int i=path.indexOf('.');
|
||||
if(i<0){
|
||||
return false;
|
||||
}
|
||||
String extension=path.substring(i);
|
||||
return containsExtension(extension);
|
||||
}
|
||||
private boolean isResRawDir(String path){
|
||||
String dir=mResRawDir;
|
||||
if(dir==null||dir.length()==0){
|
||||
return false;
|
||||
}
|
||||
return path.startsWith(dir);
|
||||
}
|
||||
public boolean containsExtension(String extension){
|
||||
if(extension==null){
|
||||
return false;
|
||||
}
|
||||
if(mExtensionList.contains(extension)){
|
||||
return true;
|
||||
}
|
||||
if(!extension.startsWith(".")){
|
||||
return mExtensionList.contains("."+extension);
|
||||
}
|
||||
return mExtensionList.contains(extension.substring(1));
|
||||
}
|
||||
public boolean containsPath(String path){
|
||||
return mPathList.contains(path);
|
||||
}
|
||||
public void add(ZipArchive zipArchive){
|
||||
public void addPath(ZipArchive zipArchive){
|
||||
for(InputSource inputSource: zipArchive.listInputSources()){
|
||||
add(inputSource);
|
||||
addPath(inputSource);
|
||||
}
|
||||
}
|
||||
public void add(InputSource inputSource){
|
||||
public void addPath(InputSource inputSource){
|
||||
if(inputSource.getMethod()!=ZipEntry.STORED){
|
||||
return;
|
||||
}
|
||||
add(inputSource.getAlias());
|
||||
addPath(inputSource.getAlias());
|
||||
}
|
||||
public void add(String path){
|
||||
public void addPath(String path){
|
||||
if(path==null || path.length()==0){
|
||||
return;
|
||||
}
|
||||
@ -53,29 +93,68 @@ public class UncompressedFiles implements JSONConvert<JSONArray> {
|
||||
}
|
||||
mPathList.add(path);
|
||||
}
|
||||
public void clear(){
|
||||
public void addCommonExtensions(){
|
||||
for(String ext:COMMON_EXTENSIONS){
|
||||
addExtension(ext);
|
||||
}
|
||||
}
|
||||
public void addExtension(String extension){
|
||||
if(extension==null || extension.length()==0){
|
||||
return;
|
||||
}
|
||||
mExtensionList.add(extension);
|
||||
}
|
||||
public void clearPaths(){
|
||||
mPathList.clear();
|
||||
}
|
||||
@Override
|
||||
public JSONArray toJson() {
|
||||
return new JSONArray(mPathList);
|
||||
public void clearExtensions(){
|
||||
mExtensionList.clear();
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONArray json) {
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put(NAME_extensions, new JSONArray(mExtensionList));
|
||||
jsonObject.put(NAME_paths, new JSONArray(mPathList));
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
clearExtensions();
|
||||
clearPaths();
|
||||
if(json==null){
|
||||
return;
|
||||
}
|
||||
int length = json.length();
|
||||
JSONArray extensions = json.optJSONArray(NAME_extensions);
|
||||
if(extensions!=null){
|
||||
int length = extensions.length();
|
||||
for(int i=0;i<length;i++){
|
||||
this.add(json.getString(i));
|
||||
this.addExtension(extensions.getString(i));
|
||||
}
|
||||
}
|
||||
JSONArray paths = json.optJSONArray(NAME_paths);
|
||||
if(paths!=null){
|
||||
int length = paths.length();
|
||||
for(int i=0;i<length;i++){
|
||||
this.addPath(paths.getString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
public void fromJson(File jsonFile) throws IOException {
|
||||
if(!jsonFile.isFile()){
|
||||
return;
|
||||
}
|
||||
JSONArray jsonArray=new JSONArray(new FileInputStream(jsonFile));
|
||||
fromJson(jsonArray);
|
||||
JSONObject jsonObject=new JSONObject(new FileInputStream(jsonFile));
|
||||
fromJson(jsonObject);
|
||||
}
|
||||
public static final String JSON_FILE = "uncompressed-files.json";
|
||||
public static final String NAME_paths = "paths";
|
||||
public static final String NAME_extensions = "extensions";
|
||||
public static String[] COMMON_EXTENSIONS=new String[]{
|
||||
".png",
|
||||
".jpg",
|
||||
".mp3",
|
||||
".mp4",
|
||||
".wav",
|
||||
".webp",
|
||||
};
|
||||
}
|
||||
|
@ -15,15 +15,40 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
public AndroidManifestBlock(){
|
||||
super();
|
||||
}
|
||||
public ResXmlElement getMainActivity(){
|
||||
for(ResXmlElement activity:listActivities()){
|
||||
for(ResXmlElement intentFilter:activity.listElements(TAG_intent_filter)){
|
||||
ResXmlAttribute attribute = intentFilter.searchAttributeByResourceId(ID_name);
|
||||
if(VALUE_android_intent_action_MAIN.equals(attribute.getValueAsString())){
|
||||
return activity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public List<ResXmlElement> listActivities(){
|
||||
return listActivities(true);
|
||||
}
|
||||
public List<ResXmlElement> listActivities(boolean includeActivityAlias){
|
||||
ResXmlElement application=getApplicationElement();
|
||||
if(application==null){
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<ResXmlElement> results = application.listElements(TAG_activity);
|
||||
if(includeActivityAlias){
|
||||
results.addAll(application.listElements(TAG_activity_alias));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
public List<String> getUsesPermissions(){
|
||||
List<String> results=new ArrayList<>();
|
||||
ResXmlElement manifestElement=getManifestElement();
|
||||
if(manifestElement==null){
|
||||
return results;
|
||||
}
|
||||
List<ResXmlElement> permissionList = manifestElement.searchElementsByTagName(TAG_uses_permission);
|
||||
List<ResXmlElement> permissionList = manifestElement.listElements(TAG_uses_permission);
|
||||
for(ResXmlElement permission:permissionList){
|
||||
ResXmlAttribute nameAttr = permission.searchAttributeById(ID_name);
|
||||
ResXmlAttribute nameAttr = permission.searchAttributeByResourceId(ID_name);
|
||||
if(nameAttr==null){
|
||||
continue;
|
||||
}
|
||||
@ -39,9 +64,9 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
if(manifestElement==null){
|
||||
return null;
|
||||
}
|
||||
List<ResXmlElement> permissionList = manifestElement.searchElementsByTagName(TAG_uses_permission);
|
||||
List<ResXmlElement> permissionList = manifestElement.listElements(TAG_uses_permission);
|
||||
for(ResXmlElement permission:permissionList){
|
||||
ResXmlAttribute nameAttr = permission.searchAttributeById(ID_name);
|
||||
ResXmlAttribute nameAttr = permission.searchAttributeByResourceId(ID_name);
|
||||
if(nameAttr==null){
|
||||
continue;
|
||||
}
|
||||
@ -121,7 +146,7 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
if(manifestElement==null){
|
||||
return false;
|
||||
}
|
||||
ResXmlAttribute attribute= manifestElement.searchAttributeById(resId);
|
||||
ResXmlAttribute attribute= manifestElement.searchAttributeByResourceId(resId);
|
||||
if(attribute==null){
|
||||
return false;
|
||||
}
|
||||
@ -147,7 +172,7 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
if(manifestElement==null){
|
||||
return false;
|
||||
}
|
||||
ResXmlAttribute attribute= manifestElement.searchAttributeById(resId);
|
||||
ResXmlAttribute attribute= manifestElement.searchAttributeByResourceId(resId);
|
||||
if(attribute==null){
|
||||
return false;
|
||||
}
|
||||
@ -181,14 +206,14 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
}
|
||||
return attribute.getRawValue();
|
||||
}
|
||||
private ResXmlElement getApplicationElement(){
|
||||
public ResXmlElement getApplicationElement(){
|
||||
ResXmlElement manifestElement=getManifestElement();
|
||||
if(manifestElement==null){
|
||||
return null;
|
||||
}
|
||||
return manifestElement.getElementByTagName(TAG_application);
|
||||
}
|
||||
private ResXmlElement getManifestElement(){
|
||||
public ResXmlElement getManifestElement(){
|
||||
ResXmlElement manifestElement=getResXmlElement();
|
||||
if(manifestElement==null){
|
||||
return null;
|
||||
@ -231,9 +256,24 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
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_action = "action";
|
||||
public static final String TAG_activity = "activity";
|
||||
public static final String TAG_activity_alias = "activity-alias";
|
||||
public static final String TAG_application = "application";
|
||||
public static final String TAG_category = "category";
|
||||
public static final String TAG_data = "data";
|
||||
public static final String TAG_intent_filter = "intent-filter";
|
||||
public static final String TAG_manifest = "manifest";
|
||||
public static final String TAG_meta_data = "meta-data";
|
||||
public static final String TAG_package = "package";
|
||||
public static final String TAG_permission = "permission";
|
||||
public static final String TAG_provider = "provider";
|
||||
public static final String TAG_receiver = "receiver";
|
||||
public static final String TAG_service = "service";
|
||||
public static final String TAG_uses_feature = "uses-feature";
|
||||
public static final String TAG_uses_library = "uses-library";
|
||||
public static final String TAG_uses_permission = "uses-permission";
|
||||
public static final String TAG_uses_sdk = "uses-sdk";
|
||||
|
||||
public static final String NAME_compileSdkVersion = "compileSdkVersion";
|
||||
public static final String NAME_compileSdkVersionCodename = "compileSdkVersionCodename";
|
||||
@ -253,5 +293,7 @@ public class AndroidManifestBlock extends ResXmlBlock{
|
||||
public static final int ID_configChanges = 0x0101001f;
|
||||
public static final int ID_screenOrientation = 0x0101001e;
|
||||
|
||||
public static final String VALUE_android_intent_action_MAIN = "android.intent.action.MAIN";
|
||||
|
||||
public static final String FILE_NAME="AndroidManifest.xml";
|
||||
}
|
||||
|
@ -36,34 +36,37 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
addChild(5, mValueTypeByte);
|
||||
addChild(6, mRawValue);
|
||||
}
|
||||
public int getNamespaceReference(){
|
||||
public String getUri(){
|
||||
return getString(getNamespaceReference());
|
||||
}
|
||||
int getNamespaceReference(){
|
||||
return mNamespaceReference.get();
|
||||
}
|
||||
public void setNamespaceReference(int ref){
|
||||
void setNamespaceReference(int ref){
|
||||
mNamespaceReference.set(ref);
|
||||
}
|
||||
public int getNameReference(){
|
||||
int getNameReference(){
|
||||
return mNameReference.get();
|
||||
}
|
||||
public void setNameReference(int ref){
|
||||
void setNameReference(int ref){
|
||||
mNameReference.set(ref);
|
||||
}
|
||||
public int getValueStringReference(){
|
||||
int getValueStringReference(){
|
||||
return mValueStringReference.get();
|
||||
}
|
||||
public void setValueStringReference(int ref){
|
||||
void setValueStringReference(int ref){
|
||||
mValueStringReference.set(ref);
|
||||
}
|
||||
public short getNameType(){
|
||||
short getNameType(){
|
||||
return mNameType.get();
|
||||
}
|
||||
public void setNameType(short s){
|
||||
void setNameType(short s){
|
||||
mNameType.set(s);
|
||||
}
|
||||
public byte getValueTypeByte(){
|
||||
byte getValueTypeByte(){
|
||||
return mValueTypeByte.get();
|
||||
}
|
||||
public void setValueTypeByte(byte b){
|
||||
void setValueTypeByte(byte b){
|
||||
mValueTypeByte.set(b);
|
||||
}
|
||||
public int getRawValue(){
|
||||
@ -109,18 +112,7 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
}
|
||||
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(){
|
||||
ResXmlStartNamespace getStartNamespace(){
|
||||
ResXmlElement xmlElement=getParentResXmlElement();
|
||||
if(xmlElement==null){
|
||||
return null;
|
||||
@ -364,7 +356,7 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_name, getName());
|
||||
jsonObject.put(NAME_id, getNameResourceID());
|
||||
jsonObject.put(NAME_namespace_uri, getNamespace());
|
||||
jsonObject.put(NAME_namespace_uri, getUri());
|
||||
ValueType valueType=getValueType();
|
||||
jsonObject.put(NAME_value_type, valueType.name());
|
||||
if(valueType==ValueType.STRING){
|
||||
@ -433,8 +425,8 @@ public class ResXmlAttribute extends FixedBlockContainer
|
||||
return builder.toString();
|
||||
}
|
||||
static final String NAME_id = "id";
|
||||
static final String NAME_value_type="value_type";
|
||||
public static final String NAME_value_type = "value_type";
|
||||
static final String NAME_name = "name";
|
||||
static final String NAME_namespace_uri ="namespace_uri";
|
||||
static final String NAME_data="data";
|
||||
public static final String NAME_namespace_uri = "namespace_uri";
|
||||
public static final String NAME_data= "data";
|
||||
}
|
||||
|
@ -90,18 +90,6 @@ public class ResXmlElement extends FixedBlockContainer implements JSONConvert<JS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public List<ResXmlElement> searchElementsByTagName(String name){
|
||||
List<ResXmlElement> results=new ArrayList<>();
|
||||
if(name==null){
|
||||
return results;
|
||||
}
|
||||
for(ResXmlElement child:listElements()){
|
||||
if(name.equals(child.getTag())||name.equals(child.getTagName())){
|
||||
results.add(child);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
public ResXmlAttribute searchAttributeByName(String name){
|
||||
ResXmlStartElement startElement=getStartElement();
|
||||
if(startElement!=null){
|
||||
@ -109,10 +97,10 @@ public class ResXmlElement extends FixedBlockContainer implements JSONConvert<JS
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ResXmlAttribute searchAttributeById(int resourceId){
|
||||
public ResXmlAttribute searchAttributeByResourceId(int resourceId){
|
||||
ResXmlStartElement startElement=getStartElement();
|
||||
if(startElement!=null){
|
||||
return startElement.searchAttributeById(resourceId);
|
||||
return startElement.searchAttributeByResourceId(resourceId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -207,6 +195,18 @@ public class ResXmlElement extends FixedBlockContainer implements JSONConvert<JS
|
||||
public List<ResXmlElement> listElements(){
|
||||
return mBody.getChildes();
|
||||
}
|
||||
public List<ResXmlElement> listElements(String name){
|
||||
List<ResXmlElement> results=new ArrayList<>();
|
||||
if(name==null){
|
||||
return results;
|
||||
}
|
||||
for(ResXmlElement element:listElements()){
|
||||
if(name.equals(element.getTag())||name.equals(element.getTagName())){
|
||||
results.add(element);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
public ResXmlElement getParentResXmlElement(){
|
||||
Block parent=getParent();
|
||||
while (parent!=null){
|
||||
|
@ -31,6 +31,23 @@ public class ResXmlStartElement extends BaseXmlChunk {
|
||||
addChild(mClassAttribute);
|
||||
addChild(mAttributeArray);
|
||||
}
|
||||
public ResXmlAttribute getAttribute(String uri, String name){
|
||||
if(name==null){
|
||||
return null;
|
||||
}
|
||||
for(ResXmlAttribute attribute:listResXmlAttributes()){
|
||||
if(name.equals(attribute.getName())||name.equals(attribute.getFullName())){
|
||||
if(uri!=null){
|
||||
if(uri.equals(attribute.getUri())){
|
||||
return attribute;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ResXmlAttribute searchAttributeByName(String name){
|
||||
if(name==null){
|
||||
return null;
|
||||
@ -42,7 +59,7 @@ public class ResXmlStartElement extends BaseXmlChunk {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ResXmlAttribute searchAttributeById(int resourceId){
|
||||
public ResXmlAttribute searchAttributeByResourceId(int resourceId){
|
||||
if(resourceId==0){
|
||||
return null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user