How to load .so when using Robolectric?

感情迁移 提交于 2019-12-07 04:41:12

问题


W/Environment: EXTERNAL_STORAGE undefined; falling back to default

java.lang.UnsatisfiedLinkError: com.autonavi.amap.mapcore.MapCore.nativeNewInstance(Ljava/lang/String;)J
    at com.autonavi.amap.mapcore.MapCore.nativeNewInstance(Native Method)
    at com.autonavi.amap.mapcore.MapCore.<init>(MapCore.java:62)
    at com.amap.api.mapcore.AMapDelegateImpGLSurfaceView.<init>(AMapDelegateImpGLSurfaceView.java:356)
    at com.amap.api.mapcore.AMapDelegateImpGLSurfaceView.<init>(AMapDelegateImpGLSurfaceView.java:318)
    at com.amap.api.mapcore.ak.a(MapFragmentDelegateImp.java:123)
    at com.amap.api.maps.MapView.onCreate(MapView.java:131)
    at com.e.activity.DriverReleaseActivity.initData(DriverReleaseActivity.java:179)
    at com.e.base.BaseActivity.onCreate(BaseActivity.java:29)
    at android.app.Activity.performCreate(Activity.java:5933)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:195)
    at org.robolectric.util.ActivityController$1.run(ActivityController.java:122)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:304)
    at org.robolectric.shadows.CoreShadowsAdapter$2.runPaused(CoreShadowsAdapter.java:45)
    at org.robolectric.util.ActivityController.create(ActivityController.java:118)
    at org.robolectric.util.ActivityController.create(ActivityController.java:129)
    at com.enjoytech.ecar.carpooling.activity.DriverReleaseAcitivityTest.init(DriverReleaseAcitivityTest.java:87)
    at com.enjoytech.ecar.carpooling.activity.DriverReleaseAcitivityTest.test(DriverReleaseAcitivityTest.java:79)
    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.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
    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.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Process finished with exit code -1

It couldn't load the .so file.

When I use

try {      
    System.loadLibrary("libamapv304");
    System.loadLibrary("libamapv304ex");
} catch (UnsatisfiedLinkError e) {
    e.printStackTrace();
}

it cause java.lang.UnsatisfiedLinkError: no libamapv304 in java.library.path

How can I using .so to complete unit test with Roboletric?


回答1:


I would load native libraries in some controlled way. For simplicity let assume it is in Application:

public class NativeLibApplication extends Application {
    ...
    protected void loadNativeLibraries() {
        try {      
            System.loadLibrary("libamapv304");
            System.loadLibrary("libamapv304ex");
        } catch (UnsatisfiedLinkError e) {
            ...
        }
    }
    ...
}

Robolectric gives you a possibility to tweak your application under the test. You should create TestNativeLibApplication in the same package under test folder and suppress loading native libraries:

public class TestNativeLibApplication extends NativeLibApplication {
    ...
    @Override
    protected void loadNativeLibraries() {
        //do nothing
    }
    ...
}



回答2:


Support libraries that package native libraries

Summary

1. Disable load so in your app code.

2. Porting Dynamic Link Library.

  • If you use the Linux operating system that is the most simple, just get the x86-64(Depending on your cpu architecture) 's so file, and add the dependency so library(Found in the ndk-bundle, platforms folder).

  • If you use the masOS operating system, you need to do a little more work. And you should have the native so library source code, and compile it under macOS system:

``` Bash

.o

cc -c -I/System/Library/Frameworks/JavaVM.framework/Headers *.cpp

get xxx.dylib

g++ -dynamiclib -undefined suppress -flat_namespace *.o -o something.dylib

```

  • Windows is similar.

3. Load so library in your RobolectricApplication.

End, run your test case, well done:

load so test case http://rocko-blog.qiniudn.com/2016-11-27_09-32-15_test_case_success.png

Detail

Sample code: RobolectricSupportNativeLibs



来源:https://stackoverflow.com/questions/34554998/how-to-load-so-when-using-robolectric

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!