mirror of
https://github.com/revanced/Apktool.git
synced 2025-01-06 10:05:54 +01:00
Reading framework files from hard disk.
This commit is contained in:
parent
43797e0c0d
commit
d2fdeb5a73
@ -42,7 +42,6 @@ public class Androlib {
|
||||
private final AndrolibResources mAndRes = new AndrolibResources();
|
||||
|
||||
public ResTable getResTable(ExtFile apkFile) throws AndrolibException {
|
||||
LOGGER.info("Decoding resource table...");
|
||||
return mAndRes.getResTable(apkFile);
|
||||
}
|
||||
|
||||
|
@ -125,9 +125,17 @@ public class ApkDecoder {
|
||||
mForceDelete = forceDelete;
|
||||
}
|
||||
|
||||
public void setFrameworkTag(String tag) {
|
||||
mFrameTag = tag;
|
||||
if (mResTable != null) {
|
||||
mResTable.setFrameTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
public ResTable getResTable() throws AndrolibException {
|
||||
if (mResTable == null) {
|
||||
mResTable = mAndrolib.getResTable(mApkFile);
|
||||
mResTable.setFrameTag(mFrameTag);
|
||||
}
|
||||
return mResTable;
|
||||
}
|
||||
@ -157,4 +165,5 @@ public class ApkDecoder {
|
||||
private short mDecodeResources = DECODE_RESOURCES_FULL;
|
||||
private boolean mDebug = false;
|
||||
private boolean mForceDelete = false;
|
||||
private String mFrameTag;
|
||||
}
|
||||
|
40
src/brut/androlib/err/CantFindFrameworkResException.java
Normal file
40
src/brut/androlib/err/CantFindFrameworkResException.java
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010 Ryszard Wiśniewski <brut.alll@gmail.com>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* under the License.
|
||||
*/
|
||||
package brut.androlib.err;
|
||||
|
||||
import brut.androlib.AndrolibException;
|
||||
|
||||
/**
|
||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
*/
|
||||
public class CantFindFrameworkResException extends AndrolibException {
|
||||
|
||||
public CantFindFrameworkResException(Throwable cause, int id) {
|
||||
super(cause);
|
||||
mPkgId = id;
|
||||
}
|
||||
|
||||
public CantFindFrameworkResException(int id) {
|
||||
mPkgId = id;
|
||||
}
|
||||
|
||||
public int getPkgId() {
|
||||
return mPkgId;
|
||||
}
|
||||
|
||||
private final int mPkgId;
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
package brut.androlib.res;
|
||||
|
||||
import brut.androlib.AndrolibException;
|
||||
import brut.androlib.err.CantFindFrameworkResException;
|
||||
import brut.androlib.res.data.*;
|
||||
import brut.androlib.res.data.value.ResXmlSerializable;
|
||||
import brut.androlib.res.decoder.*;
|
||||
@ -27,8 +28,7 @@ import brut.common.BrutException;
|
||||
import brut.directory.*;
|
||||
import brut.util.*;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
@ -38,17 +38,54 @@ import org.xmlpull.v1.XmlSerializer;
|
||||
*/
|
||||
final public class AndrolibResources {
|
||||
public ResTable getResTable(ExtFile apkFile) throws AndrolibException {
|
||||
ResTable resTable = new ResTable();
|
||||
decodeArsc(resTable, apkFile, true);
|
||||
if (! resTable.hasPackage(1)) {
|
||||
decodeArsc(resTable, new ExtFile(getAndroidResourcesFile()), false);
|
||||
}
|
||||
if (! resTable.hasPackage(2)) {
|
||||
decodeArsc(resTable, new ExtFile(getHtcResourcesFile()), false);
|
||||
}
|
||||
ResTable resTable = new ResTable(this);
|
||||
loadMainPkg(resTable, apkFile);
|
||||
return resTable;
|
||||
}
|
||||
|
||||
public ResPackage loadMainPkg(ResTable resTable, ExtFile apkFile)
|
||||
throws AndrolibException {
|
||||
LOGGER.info("Loading resource table...");
|
||||
ResPackage[] pkgs = getResPackagesFromApk(apkFile, resTable);
|
||||
ResPackage pkg = null;
|
||||
|
||||
switch (pkgs.length) {
|
||||
case 1:
|
||||
pkg = pkgs[0];
|
||||
break;
|
||||
case 2:
|
||||
if (pkgs[0].getName().equals("android")) {
|
||||
LOGGER.warning("Skipping \"android\" package group");
|
||||
pkg = pkgs[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (pkg == null) {
|
||||
throw new AndrolibException(
|
||||
"Arsc files with zero or multiple packages");
|
||||
}
|
||||
|
||||
resTable.addPackage(pkg, true);
|
||||
return pkg;
|
||||
}
|
||||
|
||||
public ResPackage loadFrameworkPkg(ResTable resTable, int id,
|
||||
String frameTag) throws AndrolibException {
|
||||
File apk = getFrameworkApk(id, frameTag);
|
||||
|
||||
LOGGER.info("Loading resource table from file: " + apk);
|
||||
ResPackage[] pkgs = getResPackagesFromApk(new ExtFile(apk), resTable);
|
||||
|
||||
if (pkgs.length != 1) {
|
||||
throw new AndrolibException(
|
||||
"Arsc files with zero or multiple packages");
|
||||
}
|
||||
|
||||
resTable.addPackage(pkgs[0], false);
|
||||
return pkgs[0];
|
||||
}
|
||||
|
||||
public void decode(ResTable resTable, ExtFile apkFile, File outDir)
|
||||
throws AndrolibException {
|
||||
Duo<ResFileDecoder, ResAttrDecoder> duo = getResFileDecoder();
|
||||
@ -246,37 +283,69 @@ final public class AndrolibResources {
|
||||
}
|
||||
}
|
||||
|
||||
private void decodeArsc(ResTable resTable, ExtFile apkFile, boolean main)
|
||||
throws AndrolibException {
|
||||
private ResPackage[] getResPackagesFromApk(ExtFile apkFile,
|
||||
ResTable resTable) throws AndrolibException {
|
||||
try {
|
||||
loadArsc(resTable, apkFile.getDirectory()
|
||||
.getFileInput("resources.arsc"), main);
|
||||
return ARSCDecoder.decode(
|
||||
apkFile.getDirectory().getFileInput("resources.arsc"),
|
||||
resTable);
|
||||
} catch (DirectoryException ex) {
|
||||
throw new AndrolibException(
|
||||
"Could not load resources.arsc from file: " + apkFile, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void loadArsc(ResTable resTable, InputStream arscStream,
|
||||
boolean main) throws AndrolibException {
|
||||
ResPackage[] groups = ARSCDecoder.decode(arscStream, resTable);
|
||||
|
||||
if (groups.length == 0) {
|
||||
throw new AndrolibException(
|
||||
"Arsc file with zero package groups");
|
||||
private File getFrameworkApk(int id, String frameTag)
|
||||
throws AndrolibException {
|
||||
File dir = getFrameworkDir();
|
||||
|
||||
File apk = new File(dir, String.valueOf(id) + '-' + frameTag + ".apk");
|
||||
if (apk.exists()) {
|
||||
return apk;
|
||||
}
|
||||
if (groups.length > 1) {
|
||||
LOGGER.warning("Arsc file with multiple package groups");
|
||||
|
||||
apk = new File(dir, String.valueOf(id) + ".apk");
|
||||
if (apk.exists()) {
|
||||
return apk;
|
||||
}
|
||||
for (int i = 0; i < groups.length; i++) {
|
||||
if (groups.length != 1 && i == 0
|
||||
&& "android".equals(groups[i].getName())) {
|
||||
LOGGER.warning("Skipping \"android\" package group");
|
||||
continue;
|
||||
|
||||
if (id == 1) {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
in = AndrolibResources.class.getResourceAsStream(
|
||||
"/brut/androlib/android-framework.jar");
|
||||
out = new FileOutputStream(apk);
|
||||
IOUtils.copy(in, out);
|
||||
return apk;
|
||||
} catch (IOException ex) {
|
||||
throw new AndrolibException(ex);
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException ex) {}
|
||||
}
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ex) {}
|
||||
}
|
||||
}
|
||||
resTable.addPackage(groups[i], main);
|
||||
}
|
||||
|
||||
throw new CantFindFrameworkResException(id);
|
||||
}
|
||||
|
||||
private File getFrameworkDir() throws AndrolibException {
|
||||
File dir = new File(System.getProperty("user.home") +
|
||||
File.separatorChar + "apktool" + File.separatorChar + "framework");
|
||||
if (! dir.exists()) {
|
||||
if (! dir.mkdirs()) {
|
||||
throw new AndrolibException("Can't create directory: " + dir);
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
private File getAndroidResourcesFile() throws AndrolibException {
|
||||
|
@ -19,16 +19,16 @@ package brut.androlib.res.data;
|
||||
|
||||
import brut.androlib.AndrolibException;
|
||||
import brut.androlib.err.UndefinedResObject;
|
||||
import brut.androlib.res.AndrolibResources;
|
||||
import brut.androlib.res.data.value.ResValue;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
*/
|
||||
public class ResTable {
|
||||
private final AndrolibResources mAndRes;
|
||||
|
||||
private final Map<Integer, ResPackage> mPackagesById =
|
||||
new HashMap<Integer, ResPackage>();
|
||||
private final Map<String, ResPackage> mPackagesByName =
|
||||
@ -36,7 +36,14 @@ public class ResTable {
|
||||
private final Set<ResPackage> mMainPackages =
|
||||
new LinkedHashSet<ResPackage>();
|
||||
|
||||
private String mFrameTag;
|
||||
|
||||
public ResTable() {
|
||||
mAndRes = null;
|
||||
}
|
||||
|
||||
public ResTable(AndrolibResources andRes) {
|
||||
mAndRes = andRes;
|
||||
}
|
||||
|
||||
public ResResSpec getResSpec(int resID) throws AndrolibException {
|
||||
@ -53,11 +60,13 @@ public class ResTable {
|
||||
|
||||
public ResPackage getPackage(int id) throws AndrolibException {
|
||||
ResPackage pkg = mPackagesById.get(id);
|
||||
if (pkg == null) {
|
||||
throw new UndefinedResObject(String.format(
|
||||
"package: id=%d", id));
|
||||
if (pkg != null) {
|
||||
return pkg;
|
||||
}
|
||||
return pkg;
|
||||
if (mAndRes != null) {
|
||||
return mAndRes.loadFrameworkPkg(this, id, mFrameTag);
|
||||
}
|
||||
throw new UndefinedResObject(String.format("package: id=%d", id));
|
||||
}
|
||||
|
||||
public ResPackage getPackage(String name) throws AndrolibException {
|
||||
@ -100,4 +109,8 @@ public class ResTable {
|
||||
mMainPackages.add(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFrameTag(String tag) {
|
||||
mFrameTag = tag;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user