假设您的应用程序有一个名为
以下是一种情况说明:
您的项目具有以下构建文件:
一个将被混淆的简单类:
UI测试:
现在如果你运行测试,
Foo
的类,并且您在应用程序和测试代码中都使用这个类。但是,该类在应用APK中被混淆后,您的测试代码将无法引用它。是否有可能在使用测试代码的同时继续对该类进行混淆?以下是一种情况说明:
您的项目具有以下构建文件:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "ademar.testproguard"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
resConfigs "en"
}
buildTypes {
all {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt')
testProguardFile "proguard-test-rules.pro"
}
}
}
dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.1'
}
Proguard测试规则:
-dontobfuscate
-dontwarn
-dontshrink
-dontoptimize
-dontusemixedcaseclassnames
-ignorewarnings
-keepattributes *Annotation*
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="ademar.testproguard"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".App"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
App类:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
new Foo().foo();
}
}
一个将被混淆的简单类:
public class Foo {
public void foo() {
Log.d("TestProguard", "Success called");
}
}
UI测试:
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void testA() throws Exception {
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("ademar.testproguard", appContext.getPackageName());
}
@Test
public void testB() throws Exception {
new Foo().foo();
}
}
现在如果你运行测试,
testA
将会通过,注意到App
已经被创建了,混淆后的Foo
类已经被调用,并且你已经成功记录了Success called
的调用。另一方面,testB
会收到以下异常:java.lang.NoClassDefFoundError: Failed resolution of: Lademar/testproguard/Foo;
at ademar.testproguard.ExampleInstrumentedTest.testB(ExampleInstrumentedTest.java:23)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:58)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:375)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2075)
Caused by: java.lang.ClassNotFoundException: Didn't find class "ademar.testproguard.Foo" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/system/framework/android.test.mock.jar", zip file "/data/app/ademar.testproguard.test-yIIGwW8RoqUKvzfKeMd__Q==/base.apk", zip file "/data/app/ademar.testproguard-L6M8bDawepTV9VltDF2TqA==/base.apk"],nativeLibraryDirectories=[/data/app/ademar.testproguard.test-yIIGwW8RoqUKvzfKeMd__Q==/lib/x86, /data/app/ademar.testproguard-L6M8bDawepTV9VltDF2TqA==/lib/x86, /system/lib, /vendor/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
从上面的图片中可以看出,应用程序APK已经对Foo类进行了混淆。
Instrumentation类也有Foo,但没有进行混淆: