mirror of
https://github.com/revanced/Apktool.git
synced 2025-01-07 18:45:58 +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();
|
private final AndrolibResources mAndRes = new AndrolibResources();
|
||||||
|
|
||||||
public ResTable getResTable(ExtFile apkFile) throws AndrolibException {
|
public ResTable getResTable(ExtFile apkFile) throws AndrolibException {
|
||||||
LOGGER.info("Decoding resource table...");
|
|
||||||
return mAndRes.getResTable(apkFile);
|
return mAndRes.getResTable(apkFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,9 +125,17 @@ public class ApkDecoder {
|
|||||||
mForceDelete = forceDelete;
|
mForceDelete = forceDelete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFrameworkTag(String tag) {
|
||||||
|
mFrameTag = tag;
|
||||||
|
if (mResTable != null) {
|
||||||
|
mResTable.setFrameTag(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ResTable getResTable() throws AndrolibException {
|
public ResTable getResTable() throws AndrolibException {
|
||||||
if (mResTable == null) {
|
if (mResTable == null) {
|
||||||
mResTable = mAndrolib.getResTable(mApkFile);
|
mResTable = mAndrolib.getResTable(mApkFile);
|
||||||
|
mResTable.setFrameTag(mFrameTag);
|
||||||
}
|
}
|
||||||
return mResTable;
|
return mResTable;
|
||||||
}
|
}
|
||||||
@ -157,4 +165,5 @@ public class ApkDecoder {
|
|||||||
private short mDecodeResources = DECODE_RESOURCES_FULL;
|
private short mDecodeResources = DECODE_RESOURCES_FULL;
|
||||||
private boolean mDebug = false;
|
private boolean mDebug = false;
|
||||||
private boolean mForceDelete = 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;
|
package brut.androlib.res;
|
||||||
|
|
||||||
import brut.androlib.AndrolibException;
|
import brut.androlib.AndrolibException;
|
||||||
|
import brut.androlib.err.CantFindFrameworkResException;
|
||||||
import brut.androlib.res.data.*;
|
import brut.androlib.res.data.*;
|
||||||
import brut.androlib.res.data.value.ResXmlSerializable;
|
import brut.androlib.res.data.value.ResXmlSerializable;
|
||||||
import brut.androlib.res.decoder.*;
|
import brut.androlib.res.decoder.*;
|
||||||
@ -27,8 +28,7 @@ import brut.common.BrutException;
|
|||||||
import brut.directory.*;
|
import brut.directory.*;
|
||||||
import brut.util.*;
|
import brut.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
import org.xmlpull.v1.XmlSerializer;
|
||||||
@ -38,17 +38,54 @@ import org.xmlpull.v1.XmlSerializer;
|
|||||||
*/
|
*/
|
||||||
final public class AndrolibResources {
|
final public class AndrolibResources {
|
||||||
public ResTable getResTable(ExtFile apkFile) throws AndrolibException {
|
public ResTable getResTable(ExtFile apkFile) throws AndrolibException {
|
||||||
ResTable resTable = new ResTable();
|
ResTable resTable = new ResTable(this);
|
||||||
decodeArsc(resTable, apkFile, true);
|
loadMainPkg(resTable, apkFile);
|
||||||
if (! resTable.hasPackage(1)) {
|
|
||||||
decodeArsc(resTable, new ExtFile(getAndroidResourcesFile()), false);
|
|
||||||
}
|
|
||||||
if (! resTable.hasPackage(2)) {
|
|
||||||
decodeArsc(resTable, new ExtFile(getHtcResourcesFile()), false);
|
|
||||||
}
|
|
||||||
return resTable;
|
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)
|
public void decode(ResTable resTable, ExtFile apkFile, File outDir)
|
||||||
throws AndrolibException {
|
throws AndrolibException {
|
||||||
Duo<ResFileDecoder, ResAttrDecoder> duo = getResFileDecoder();
|
Duo<ResFileDecoder, ResAttrDecoder> duo = getResFileDecoder();
|
||||||
@ -246,37 +283,69 @@ final public class AndrolibResources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decodeArsc(ResTable resTable, ExtFile apkFile, boolean main)
|
private ResPackage[] getResPackagesFromApk(ExtFile apkFile,
|
||||||
throws AndrolibException {
|
ResTable resTable) throws AndrolibException {
|
||||||
try {
|
try {
|
||||||
loadArsc(resTable, apkFile.getDirectory()
|
return ARSCDecoder.decode(
|
||||||
.getFileInput("resources.arsc"), main);
|
apkFile.getDirectory().getFileInput("resources.arsc"),
|
||||||
|
resTable);
|
||||||
} catch (DirectoryException ex) {
|
} catch (DirectoryException ex) {
|
||||||
throw new AndrolibException(
|
throw new AndrolibException(
|
||||||
"Could not load resources.arsc from file: " + apkFile, ex);
|
"Could not load resources.arsc from file: " + apkFile, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadArsc(ResTable resTable, InputStream arscStream,
|
private File getFrameworkApk(int id, String frameTag)
|
||||||
boolean main) throws AndrolibException {
|
throws AndrolibException {
|
||||||
ResPackage[] groups = ARSCDecoder.decode(arscStream, resTable);
|
File dir = getFrameworkDir();
|
||||||
|
|
||||||
if (groups.length == 0) {
|
File apk = new File(dir, String.valueOf(id) + '-' + frameTag + ".apk");
|
||||||
throw new AndrolibException(
|
if (apk.exists()) {
|
||||||
"Arsc file with zero package groups");
|
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
|
if (id == 1) {
|
||||||
&& "android".equals(groups[i].getName())) {
|
InputStream in = null;
|
||||||
LOGGER.warning("Skipping \"android\" package group");
|
OutputStream out = null;
|
||||||
continue;
|
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 {
|
private File getAndroidResourcesFile() throws AndrolibException {
|
||||||
|
@ -19,16 +19,16 @@ package brut.androlib.res.data;
|
|||||||
|
|
||||||
import brut.androlib.AndrolibException;
|
import brut.androlib.AndrolibException;
|
||||||
import brut.androlib.err.UndefinedResObject;
|
import brut.androlib.err.UndefinedResObject;
|
||||||
|
import brut.androlib.res.AndrolibResources;
|
||||||
import brut.androlib.res.data.value.ResValue;
|
import brut.androlib.res.data.value.ResValue;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||||
*/
|
*/
|
||||||
public class ResTable {
|
public class ResTable {
|
||||||
|
private final AndrolibResources mAndRes;
|
||||||
|
|
||||||
private final Map<Integer, ResPackage> mPackagesById =
|
private final Map<Integer, ResPackage> mPackagesById =
|
||||||
new HashMap<Integer, ResPackage>();
|
new HashMap<Integer, ResPackage>();
|
||||||
private final Map<String, ResPackage> mPackagesByName =
|
private final Map<String, ResPackage> mPackagesByName =
|
||||||
@ -36,7 +36,14 @@ public class ResTable {
|
|||||||
private final Set<ResPackage> mMainPackages =
|
private final Set<ResPackage> mMainPackages =
|
||||||
new LinkedHashSet<ResPackage>();
|
new LinkedHashSet<ResPackage>();
|
||||||
|
|
||||||
|
private String mFrameTag;
|
||||||
|
|
||||||
public ResTable() {
|
public ResTable() {
|
||||||
|
mAndRes = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResTable(AndrolibResources andRes) {
|
||||||
|
mAndRes = andRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResResSpec getResSpec(int resID) throws AndrolibException {
|
public ResResSpec getResSpec(int resID) throws AndrolibException {
|
||||||
@ -53,11 +60,13 @@ public class ResTable {
|
|||||||
|
|
||||||
public ResPackage getPackage(int id) throws AndrolibException {
|
public ResPackage getPackage(int id) throws AndrolibException {
|
||||||
ResPackage pkg = mPackagesById.get(id);
|
ResPackage pkg = mPackagesById.get(id);
|
||||||
if (pkg == null) {
|
if (pkg != null) {
|
||||||
throw new UndefinedResObject(String.format(
|
return pkg;
|
||||||
"package: id=%d", id));
|
|
||||||
}
|
}
|
||||||
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 {
|
public ResPackage getPackage(String name) throws AndrolibException {
|
||||||
@ -100,4 +109,8 @@ public class ResTable {
|
|||||||
mMainPackages.add(pkg);
|
mMainPackages.add(pkg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFrameTag(String tag) {
|
||||||
|
mFrameTag = tag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user