我在frameworks / base / core / java / android / app / DownloadManager.java中创建一个新的静态方法“ isDownloadAlertEnabled”。
public static boolean isDownloadAlertEnabled() {
boolean isEnabled = true;
String downloadAlert = SystemProperties.get("persist.downloadalert.enabled");
if (downloadAlert == null || downloadAlert.isEmpty()) {
String gms = SystemProperties.get("ro.com.google.gmsversion");
if (gms == null || gms.isEmpty()) {
isEnabled = true;
} else {
isEnabled = false;
}
} else {
isEnabled = downloadAlert.equals("true");
}
if (DEBUG) Log.d(TAG, "isDownloadAlertEnabled : " + isEnabled);
return isEnabled;
}
我将maked framework.jar放入app / libs中并添加为库。
test1:
@RunWith(RobolectricTestRunner.class)
public class test3 {
@Test
public void test333() {
System.out.println("test333 isDownloadAlertEnabled:" + DownloadManager.isDownloadAlertEnabled());
}
}
结果1:
[Robolectric] com.android.providers.downloads.test3.test333: sdk=28; resources=BINARY
Called loadFromPath(/system/framework/framework-res.apk, true); mode=binary sdk=28
java.lang.NoSuchMethodError: android.app.DownloadManager.isDownloadAlertEnabled()Z
at com.android.providers.downloads.test3.test333(test3.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:546)
at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:252)
at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
test2:
// getRecommendedMaxBytesOverMobile是SDK中的原始静态方法。
@RunWith(RobolectricTestRunner.class)
public class test3 {
@Test
public void test333() {
Context mContext = ApplicationProvider.getApplicationContext();
System.out.println("test333 getRecommendedMaxBytesOverMobile: " + DownloadManager.getRecommendedMaxBytesOverMobile(mContext));
}
}
result2:
[Robolectric] com.android.providers.downloads.test3.test333: sdk=28; resources=BINARY
Called loadFromPath(/system/framework/framework-res.apk, true); mode=binary sdk=28
test333 getRecommendedMaxBytesOverMobile: null
Process finished with exit code 0
test3:
//添加PowerMockRule,然后可以调用isDownloadAlertEnabled。
@RunWith(RobolectricTestRunner.class)
@PowerMockIgnore({ "org.powermock.*", "org.mockito.*", "org.robolectric.*", "android.*", "androidx.*" })
@PrepareForTest(DownloadManager.class)
public class test3 {
@Rule
public PowerMockRule rule = new PowerMockRule();
@Test
public void test333() {
System.out.println("test333 isDownloadAlertEnabled:" + DownloadManager.isDownloadAlertEnabled());
}
}
result3:
[Robolectric] com.android.providers.downloads.test3.test333: sdk=28; resources=BINARY
Called loadFromPath(/system/framework/framework-res.apk, true); mode=binary sdk=28
test333 isDownloadAlertEnabled:true
Process finished with exit code 0
test4:
//通过RobolectricTestRunner和PowerMockRule,我不能使用getSystemService。
@RunWith(RobolectricTestRunner.class)
@PowerMockIgnore({ "org.powermock.*", "org.mockito.*", "org.robolectric.*", "android.*", "androidx.*" })
@PrepareForTest(DownloadManager.class)
public class test3 {
@Rule
public PowerMockRule rule = new PowerMockRule();
@Test
public void test333() {
Context mContext = ApplicationProvider.getApplicationContext();
DownloadManager mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
mDownloadManager.setAccessAllDownloads(true);
System.out.println("test333 finish");
}
}
result4:
[Robolectric] com.android.providers.downloads.test3.test333: sdk=28; resources=BINARY
Called loadFromPath(/system/framework/framework-res.apk, true); mode=binary sdk=28
java.lang.ClassCastException: android.app.DownloadManager cannot be cast to android.app.DownloadManager
at com.android.providers.downloads.test3.test333(test3.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1854)
at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:816)
at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:681)
at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
at org.powermock.classloading.AbstractClassloaderExecutor.getResult(AbstractClassloaderExecutor.java:76)
at org.powermock.classloading.AbstractClassloaderExecutor.invokeWithClassLoader(AbstractClassloaderExecutor.java:64)
at org.powermock.classloading.AbstractClassloaderExecutor.executeWithClassLoader(AbstractClassloaderExecutor.java:56)
at org.powermock.classloading.SingleClassloaderExecutor.execute(SingleClassloaderExecutor.java:33)
at org.powermock.classloading.AbstractClassloaderExecutor.execute(AbstractClassloaderExecutor.java:40)
at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:75)
at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:546)
at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:252)
at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Process finished with exit code -1
最后,
仅在RobolectricTestRunner中,可以编译由我创建的静态方法“ isDownloadAlertEnabled”,但无法在运行时调用。 但是在运行时可以调用SDK中的其他本来静态的方法。
使用RobolectricTestRunner和PowerMock PowerMockRule,可以正常调用新方法,但不能使用getSystemService。
我必须同时使用静态方法和getSystemService。如何解决所有问题?
有人可以帮助我吗? 非常感谢!
android studio 3.4.2
gradle 5.1.1
SDK 28
JAVA 8
JUnit 4.12
app build.gradle :
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "com.android.providers.downloads"
minSdkVersion 27
targetSdkVersion 28
versionCode 1
versionName "1.0"
//testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
testCoverageEnabled = true
}
}
compileOptions {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
testOptions {
unitTests {
includeAndroidResources = true
//returnDefaultValues = true
}
}
sourceSets {
main { java.srcDirs = ['src/main/java'] }
}
}
dependencies {
implementation files('libs/framework.jar')
implementation files('libs/libcore.jar')
//implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
//implementation 'androidx.appcompat:appcompat:1.0.2'
testImplementation 'junit:junit:4.12'
testImplementation 'androidx.test:core:1.0.0'
//androidTestImplementation 'androidx.test:core:1.1.0'
//androidTestImplementation 'androidx.test.ext:junit:1.1.0'
//androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
testImplementation 'com.android.support.test:runner:1.0.2'
testImplementation 'com.android.support.test:rules:1.0.2'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation 'com.google.guava:guava:28.0-jre'
testImplementation 'org.mockito:mockito-core:2.9.0'
testImplementation 'org.robolectric:robolectric:4.3'
testImplementation 'org.robolectric:robolectric-gradle-plugin:1.1.0'
testImplementation 'org.powermock:powermock-module-junit4-rule:2.0.2'
testImplementation 'org.powermock:powermock-classloading-xstream:2.0.2'
testImplementation 'org.powermock:powermock-module-junit4:2.0.2'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.2'
testImplementation 'org.robolectric:shadows-multidex:4.3'
testImplementation 'org.robolectric:shadows-support-v4:3.4-rc2'
//testImplementation 'org.powermock:powermock-module-junit4-rule-agent:2.0.2'
}