按照这里的编译apktool的方法:
https://ibotpeaches.github.io/Apktool/build/
编译v2.2.2及后续版本都没有问题,但是对于v2.2.1的时候,就出现了错误。起初在我的macOs上是这样的:
brut.androlib.BuildAndDecodeTest > classMethod FAILED
brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [/var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/brut_util_Jar_5701664016852435316.tmp, p, --version-code, 1, --version-name, 1.0, -F, /var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/BRUT728632478128516271.tmp/testapp.apk, -0, arsc, -A, /var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/BRUT728632478128516271.tmp/testapp-orig/assets, /var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/BRUT728632478128516271.tmp/testapp-orig/build/apk]
at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.java:439)
at brut.androlib.Androlib.buildApk(Androlib.java:675)
at brut.androlib.Androlib.build(Androlib.java:315)
at brut.androlib.BuildAndDecodeTest.beforeClass(BuildAndDecodeTest.java:56)
Caused by:
brut.common.BrutException: could not exec (exit code = 1): [/var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/brut_util_Jar_5701664016852435316.tmp, p, --version-code, 1, --version-name, 1.0, -F, /var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/BRUT728632478128516271.tmp/testapp.apk, -0, arsc, -A, /var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/BRUT728632478128516271.tmp/testapp-orig/assets, /var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/BRUT728632478128516271.tmp/testapp-orig/build/apk]
at brut.util.OS.exec(OS.java:95)
at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.java:433)
... 3 more
brut.androlib.DefaultBaksmaliVariableTest > classMethod FAILED
java.lang.NoSuchMethodError: brut.androlib.Androlib.build(Lbrut/directory/ExtFile;Ljava/io/File;)V
at brut.androlib.DefaultBaksmaliVariableTest.beforeClass(DefaultBaksmaliVariableTest.java:30)
brut.androlib.ExternalEntityTest > classMethod FAILED
java.lang.NoSuchMethodError: brut.androlib.Androlib.build(Lbrut/directory/ExtFile;Ljava/io/File;)V
at brut.androlib.ExternalEntityTest.beforeClass(ExternalEntityTest.java:46)
brut.androlib.ParentDirectoryTraversalTest > checkIfDrawableFileDecodesProperly FAILED
brut.androlib.AndrolibException: brut.directory.DirectoryException: Error copying file: ../assets/0/logo.png
at brut.androlib.Androlib.decodeUnknownFiles(Androlib.java:218)
at brut.androlib.ApkDecoder.decode(ApkDecoder.java:158)
at brut.androlib.ParentDirectoryTraversalTest.checkIfDrawableFileDecodesProperly(ParentDirectoryTraversalTest.java:54)
Caused by:
brut.directory.DirectoryException: Error copying file: ../assets/0/logo.png
at brut.directory.DirUtil.copyToDir(DirUtil.java:88)
at brut.directory.AbstractDirectory.copyToDir(AbstractDirectory.java:207)
at brut.androlib.Androlib.decodeUnknownFiles(Androlib.java:211)
... 2 more
Caused by:
java.io.FileNotFoundException: /var/folders/cv/dg1rf__x7ygbp_dmd6r2snnw0000gn/T/BRUT5609822345258535982.tmp/issue1498.apk.out/unknown/../assets/0/logo.png (No such file or directory)
at java.io.FileOutputStream.open0(Native Method)
at java.io.FileOutputStream.open(FileOutputStream.java:270)
at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
at java.io.FileOutputStream.<init>(FileOutputStream.java:162)
at brut.directory.DirUtil.copyToDir(DirUtil.java:84)
... 4 more
brut.androlib.PositionalEnumerationTest > threeArgumentsTest FAILED
org.junit.ComparisonFailure: expected:<%1$s, %2$s, and %[3$]d other.> but was:<%1$s, %2$s, and %[]d other.>
at org.junit.Assert.assertEquals(Assert.java:115)
at org.junit.Assert.assertEquals(Assert.java:144)
at brut.androlib.PositionalEnumerationTest.threeArgumentsTest(PositionalEnumerationTest.java:45)
brut.androlib.VectorDrawableTest > checkIfDrawableFileDecodesProperly FAILED
java.lang.IllegalStateException: duplicated prefix 'android'
at org.xmlpull.mxp1_serializer.MXSerializer.setPrefix(MXSerializer.java:444)
at org.xmlpull.v1.wrapper.classic.StaticXmlSerializerWrapper.setPrefix(StaticXmlSerializerWrapper.java:132)
at org.xmlpull.v1.wrapper.classic.StaticXmlSerializerWrapper.writeStartTag(StaticXmlSerializerWrapper.java:261)
at org.xmlpull.v1.wrapper.classic.StaticXmlSerializerWrapper.event(StaticXmlSerializerWrapper.java:211)
at brut.androlib.res.decoder.XmlPullStreamDecoder$1.event(XmlPullStreamDecoder.java:83)
at brut.androlib.res.decoder.XmlPullStreamDecoder.decode(XmlPullStreamDecoder.java:141)
at brut.androlib.res.decoder.ResStreamDecoderContainer.decode(ResStreamDecoderContainer.java:33)
at brut.androlib.res.decoder.ResFileDecoder.decode(ResFileDecoder.java:120)
at brut.androlib.res.decoder.ResFileDecoder.decode(ResFileDecoder.java:105)
at brut.androlib.res.AndrolibResources.decode(AndrolibResources.java:262)
at brut.androlib.Androlib.decodeResourcesFull(Androlib.java:132)
at brut.androlib.ApkDecoder.decode(ApkDecoder.java:108)
at brut.androlib.VectorDrawableTest.checkIfDrawableFileDecodesProperly(VectorDrawableTest.java:54)
24 tests completed, 6 failed
:brut.apktool:apktool-lib:test FAILED
FAILURE: Build failed with an exception.
都是编译的时候进行了Test,然后Test没有通过的导致的编译出错。然后我试试在我的ubuntu16.04上看看。开始由于是OpenJDK,我怕这个可能有影响,然后卸载了OpenJDK, 再重新下载oracle JDK,然而还是有问题:
brut.androlib.BuildAndDecodeTest > classMethod FAILED
brut.androlib.AndrolibException: java.io.FileNotFoundException: /tmp/BRUT189745146216816624.tmp/testapp-orig/unknown/nonprintable.file (No such file or directory)
at brut.androlib.Androlib.buildUnknownFiles(Androlib.java:603)
at brut.androlib.Androlib.build(Androlib.java:319)
at brut.androlib.BuildAndDecodeTest.beforeClass(BuildAndDecodeTest.java:56)
Caused by:
java.io.FileNotFoundException: /tmp/BRUT189745146216816624.tmp/testapp-orig/unknown/nonprintable.file (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at brut.util.BrutIO.copy(BrutIO.java:78)
at brut.androlib.Androlib.copyUnknownFiles(Androlib.java:656)
at brut.androlib.Androlib.buildUnknownFiles(Androlib.java:601)
... 2 more
15 tests completed, 1 failed
:brut.apktool:apktool-lib:test FAILED
FAILURE: Build failed with an exception.
这下就只有一个错误了,但是还是编译出错。然后这里的
https://network.informatica.com/thread/17212
回答给了我启示,即将java.io.tmpdir=<your specific location>
。然后我就找一下可能是哪里用到了java.io.tmpdir
。
搜到了这个。
cqq@ubuntu:~/repos/apktool-dev/Apktool-2.2.1/Apktool-2.2.1$ grep -rn "java.io.tmpdir" *
brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java:726: parentPath.getAbsolutePath(), System.getProperty("java.io.tmpdir")));
brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java:730: parentPath = new File(System.getProperty("java.io.tmpdir"));
然后傻不啦叽的把System.getProperty("java.io.tmpdir")
改成了自己指定了目录,以为万事大吉了,结果重新编译还是一样的问题。
后来又再仔细看看出错的地方:brut.androlib.Androlib.buildUnknownFiles(Androlib.java:601)
,编译的时候应该是Test中的代码没有通过才对啊,为啥要去改源码。。。。
然后找到这里:brut.apktool/apktool-lib/src/test/java/brut/androlib/BuildAndDecodeTest.java
的beforeClass
方法:
sTmpDir = new ExtFile(OS.createTempDirectory());
使用brut.util.OS
类的createTempDirectory()
方法创建了一个tmp目录。
其中createTempDirectory()
方法为:
public static File createTempDirectory() throws BrutException {
try {
File tmp = File.createTempFile("BRUT", null);
if (!tmp.delete()) {
throw new BrutException("Could not delete tmp file: " + tmp.getAbsolutePath());
}
if (!tmp.mkdir()) {
throw new BrutException("Could not create tmp dir: " + tmp.getAbsolutePath());
}
return tmp;
} catch (IOException ex) {
throw new BrutException("Could not create tmp dir", ex);
}
}
即使用File.createTempFile("BRUT", null);
创建了/tmp/BRUTxxxxxx
目录。
测试了一下这个方法的功能。
$ cat Test.java
import java.io.File;
public class Test{
public static void main(String[] args){
try{
File.createTempFile("test_cqq", null);
}catch(Exception e){
e.printStackTrace();
}
}
}
$ javac Test.java
$ java Test
$ ll /tmp|grep test_cqq
-rw-rw-r-- 1 cqq cqq 0 Dec 28 22:48 test_cqq5553827309620261131.tmp
可能在apktool的Test代码中生成的tmp目录在之后寻找的时候已经不存在了。于是这里试试换成自己自定义的目录”/home/cqq/tmp”吧。
….醉了,结果还是不行:
brut.androlib.BuildAndDecodeTest > classMethod FAILED
brut.androlib.AndrolibException: java.io.FileNotFoundException: /home/cqq/tmp/testapp-orig/unknown/nonprintable.file (No such file or directory)
后来又用brut.androlib.BuildAndDecodeTest > classMethod FAILED
关键词搜到了官方仓库的bug issue。
https://github.com/iBotPeaches/Apktool/issues/1394
官方给的答案是:可能是因为有空格导致的。
然后我根据错误信息brut.androlib.AndrolibException: java.io.FileNotFoundException: /home/cqq/tmp/testapp-orig/unknown/non printable.file (No such file or directory)
中的”printable.file”搜了一下,
cqq@ubuntu:~/repos/apktool-dev/Apktool-2.2.1/Apktool-2.2.1$ grep -rn "printable.file" *
brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/apktool.yml:15: non\u007Fprintable.file: '8'
brut.apktool/apktool-lib/build/reports/tests/classes/brut.androlib.BuildAndDecodeTest.html:79:<pre>brut.androlib.AndrolibException: java.io.FileNotFoundException: /home/cqq/tmp/testapp-orig/unknown/nonpriversion: 2.0.0
ntable.file (No such file or directory)
brut.apktool/apktool-lib/build/reports/tests/classes/brut.androlib.BuildAndDecodeTest.html:118:Caused by: java.io.FileNotFoundException: /home/cqq/tmp/testapp-orig/unknown/nonprintable.file (No such file or directory)
Binary file brut.apktool/apktool-lib/build/test-results/binary/test/results.bin matches
brut.apktool/apktool-lib/build/test-results/TEST-brut.androlib.BuildAndDecodeTest.xml:5: <failure message="brut.androlib.AndrolibException: java.io.FileNotFoundException: /home/cqq/tmp/testapp-orig/unknown/nonprintable.file (No such file or directory)" type="brut.androlib.AndrolibException">brut.androlib.AndrolibException: java.io.FileNotFoundException: /home/cqq/tmp/testapp-orig/unknown/nonprintable.file (No such file or directory)
brut.apktool/apktool-lib/build/test-results/TEST-brut.androlib.BuildAndDecodeTest.xml:44:Caused by: java.io.FileNotFoundException: /home/cqq/tmp/testapp-orig/unknown/nonprintable.file (No such file or directory)
brut.apktool/apktool-lib/build/resources/test/brut/apktool/testapp/apktool.yml:15: non\u007Fprintable.file: '8'
然后看这个brut.apktool/apktool-lib/build/resources/test/brut/apktool/testapp/apktool.yml
文件是很久之前建的,所以应该不是我手动改的,是官方自带的。
cqq@ubuntu:~/repos/apktool-dev/Apktool-2.2.1/Apktool-2.2.1$ ll brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/apktool.yml
-rw-rw-r-- 1 cqq cqq 344 Oct 18 2016 brut.apktool/apktool-lib/src/test/resources/brut/apktool/testapp/apktool.yml
查看这个文件,原来这里面有\u007F
这种操作!
然后把non\u007Fprintable.file
改成nonprintable.file
就编译成功了!
而作者是通过四个commits修改的。
https://github.com/iBotPeaches/Apktool/pull/1395/commits