nilkash
nilkash

Reputation: 7536

UnsatisfiedLinkError for sqlcipher with robolectric

Hi I am using active android with sqlcipher intigrated for database encryption. It is working fine. I am able to create application with encrypted database. Now I am using robolectic for testcases. And it is giving me error on linking error. I have updated my gradle version. So I am not including any .so files. Instead of that I am using

 ndk {
        abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
    }

I am getting following error :

    java.lang.UnsatisfiedLinkError: no sqlcipher in java.library.path

    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1864)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:196)
    at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:189)
    at com.example.android.testing.unittesting.BasicSample.SampleApplication.onCreate(SampleApplication.java:20)
    at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:141)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:234)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:171)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:47)
    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:137)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)


java.util.ServiceConfigurationError: org.robolectric.internal.ShadowProvider: Provider org.robolectric.shadows.multidex.Shadows not a subtype

    at java.util.ServiceLoader.fail(ServiceLoader.java:239)
    at java.util.ServiceLoader.access$300(ServiceLoader.java:185)
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
    at org.robolectric.internal.bytecode.InstrumentationConfiguration$Builder.build(InstrumentationConfiguration.java:151)
    at org.robolectric.RobolectricTestRunner.createClassLoaderConfig(RobolectricTestRunner.java:115)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:169)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:47)
    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:137)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Accounding to https://groups.google.com/forum/#!topic/sqlcipher/i_Gw-7d8DpU robolectic uses JVM for simulating cases. and it will not support .so files. To un those cases need to do either on device or emulator. How to resolve this issue? Need some help.

Upvotes: 1

Views: 1792

Answers (2)

MichaB
MichaB

Reputation: 555

You have to import sqlcipher correctly to your android project.

1) Create a folder jniLibs under Project\app\src\main... It has to look like Project\app\src\main\jniLibs\

2) Now put the sqlcipher.so file under the correct folder (one of these):

Project\app\src\main\jniLibs\armeabi\sqlcipher.so
Project\app\src\main\jniLibs\armeabi-v7a\sqlcipher.so
Project\app\src\main\jniLibs\mips\sqlcipher.so
Project\app\src\main\jniLibs\x86\sqlcipher.so

3) Now add an static import to this library anywhere in the class where you want to use it.

static {
        try {
            //Libraryname without .so!!
            System.loadLibrary("sqlcipher");
        }
        catch(UnsatisfiedLinkError ex)
        {
           //Not found
        }
    }

Compile your project. Maybe a project clean too. I hope this helps! Please tell me if you need more help!

EDIT: Maybe try to add the .so file under libs\armeabi\ sqlcipher.so

Upvotes: 0

Dmitry Zaytsev
Dmitry Zaytsev

Reputation: 23972

Few things:

  1. If you want to test class which relies on .so library (let's call it NativeClass) - that won't work.
  2. If you want to test class which relies NativeClass - use an interface instead of using NativeClass directly and then mock that interface.

Upvotes: 2

Related Questions