如何修复“在DownloadManager中调用新的静态方法时出现NoSuchMethodError”

时间:2019-08-06 01:44:05

标签: java powermock robolectric nosuchmethoderror

我在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

最后,

  1. 仅在RobolectricTestRunner中,可以编译由我创建的静态方法“ isDownloadAlertEnabled”,但无法在运行时调用。 但是在运行时可以调用SDK中的其他本来静态的方法。

  2. 使用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'

}

0 个答案:

没有答案