android - SQLcipher(不同版本)在一个平台上工作,但在另一个平台上崩溃

标签 android android-ndk x86 arm sqlcipher

我在为 ARM/x86 设备构建 SQLcipher 时遇到奇怪的问题。

当我用 2.1.1 版本加密数据库并使用 Gradle for ARM 和 x86(胖客户端)构建它时,它在 ARM 设备上运行正确,但在 x86 上抛出错误

"No implementation found for native Lnet/sqlcipher/database/SQLiteDatabase;.native_key ([C)V"

当我对版本 2.2.2 重复之前的步骤时,它在 x86 上运行,但在 ARM 上它会抛出之前的错误。

3.1.0 版本的结果与 2.2.2 版本相同

你能帮我解决吗?

这是构建的 apk 文件(过滤后的 res 文件)的内容:

unzip -l SKG-fat-debug-unaligned.apk | grep -v res/
Archive:  SKG-fat-debug-unaligned.apk
  Length     Date   Time    Name
 --------    ----   ----    ----
   113664  05-03-14 22:32   assets/enc.db
  2305475  05-03-14 22:32   assets/icudt46l.zip
    11937  05-04-14 21:17   assets/postupy.json
     7988  05-04-14 21:17   AndroidManifest.xml
   228184  05-04-14 21:10   resources.arsc
  4348908  05-03-14 22:32   classes.dex
    11358  05-04-14 21:17   META-INF/LICENSE.txt
      301  05-04-14 21:17   META-INF/NOTICE.txt
    38544  05-04-14 21:17   lib/armeabi/libdatabase_sqlcipher.so
    21624  05-04-14 21:17   lib/armeabi/libgenerate.so
  1176064  05-04-14 21:17   lib/armeabi/libsqlcipher_android.so
   402604  05-04-14 21:17   lib/armeabi/libstlport_shared.so
  1757156  05-04-14 21:17   lib/x86/libdatabase_sqlcipher.so
    17536  05-04-14 21:17   lib/x86/libgenerate.so
  3520252  05-04-14 21:17   lib/x86/libsqlcipher_android.so
   455740  05-04-14 21:17   lib/x86/libstlport_shared.so
    53292  05-04-14 21:17   META-INF/MANIFEST.MF
    53321  05-04-14 21:17   META-INF/CERT.SF
      776  05-04-14 21:17   META-INF/CERT.RSA
 --------                   -------
 17178672                   530 files

这是 ARM 设备上的错误:

05-04 21:21:13.377  28356-29048/com.my.app W/dalvikvm﹕ No implementation found for native Lnet/sqlcipher/database/SQLiteDatabase;.native_key ([C)V
05-04 21:21:13.377  28356-29048/com.my.app W/dalvikvm﹕ threadid=12: thread exiting with uncaught exception (group=0x40a98228)
05-04 21:21:13.447  28356-28420/com.my.app I/global﹕ In close() at SocketHttpClientConnection
05-04 21:21:13.587  28356-28420/com.my.app I/global﹕ call createSocket() return a new socket.
05-04 21:21:13.767  28356-29048/com.my.app E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:278)
            at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:864)
     Caused by: java.lang.UnsatisfiedLinkError: native_key
            at net.sqlcipher.database.SQLiteDatabase.native_key(Native Method)
            at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1948)
            at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:875)
            at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:868)
            at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:903)
            at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:914)
            at com.my.appskg.OtvorDB(skg.java:535)
            at com.my.appfsListActivity$asyncOtvorDB.doInBackground(fsListActivity.java:289)
            at com.my.appfsListActivity$asyncOtvorDB.doInBackground(fsListActivity.java:80)
            at android.os.AsyncTask$2.call(AsyncTask.java:264)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:864)

并且在 x86 设备上它可以正确打开数据库。

05-04 21:22:38.494    1849-1884/com.my.app D/DeviceID.db﹕ LastError
05-04 21:22:38.874    1849-1849/com.my.app D/com.my.appfsListActivity$asyncOtvorDB﹕ onPostExecute
05-04 21:22:38.890    1849-1849/com.my.app D/fsListActivity﹕ DID.LastError:
05-04 21:22:38.890    1849-1849/com.my.app D/com.my.app.skg﹕ ZoznamCS
05-04 21:22:38.902    1849-1849/com.my.app D/cursor is﹕ net.sqlcipher.CrossProcessCursorWrapper@52aa7f30

这是我创建加密数据库的代码:

~/Soft/sqlcipher-2.1.1/sqlite3 db.sqlite "ATTACH DATABASE 'enc_v211.db' AS encrypted KEY '$dbkey';SELECT sqlcipher_export('encrypted');DETACH DATABASE encrypted;"
~/Soft/sqlcipher-2.2.1/sqlcipher db.sqlite "ATTACH DATABASE 'enc_v221.db' AS encrypted KEY '$dbkey';SELECT sqlcipher_export('encrypted');DETACH DATABASE encrypted;"
~/Soft/sqlcipher-3.1.0/sqlcipher db.sqlite "ATTACH DATABASE 'enc_v310.db' AS encrypted KEY '$dbkey';SELECT sqlcipher_export('encrypted');DETACH DATABASE encrypted;"

然后我将加密的数据库复制到 Assets 中,这是我打开数据库的代码:

 public void OpenDB() {     
        skg.logD(Thread.currentThread().getStackTrace()[2].getClassName() , Thread.currentThread().getStackTrace()[2].getMethodName()); 

        String dbname = "enc.db";
        String dbpath = "/data/data/com.my.app/databases/";
        try {
            InputStream myInput = context.getAssets().open(dbname);
            String outFileName = dbpath + dbname;
            OutputStream myOutput = new FileOutputStream(outFileName);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = myInput.read(buffer)) > 0) {
                myOutput.write(buffer, 0, length);
            }
            myOutput.flush();
            myOutput.close();
            myInput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            SQLiteDatabase.loadLibs(context);
            File databaseFile = context.getDatabasePath(dbpath + dbname);
            skg.logD("OtvorDB","getDBpath=" + databaseFile.toString());
            DID.context = context;
            database = SQLiteDatabase.openOrCreateDatabase(databaseFile, DID.db(), null);
            //database = SQLiteDatabase.openDatabase(databaseFile.getAbsolutePath(), DID.db(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
        } catch (Exception e) {
            e.printStackTrace();
            skg.logD("OtvorDB", e.getMessage() + e.toString() + e.getCause());
        }

正如您在代码中看到的,我尝试过使用 openDatabase,也尝试过使用 openOrCreateDatabase。

我用于测试的设备:

x86 - several devices in Genymotion VM

ARM - 2 real devices, android emulator

应用构建无误:

Executing tasks: [:SKG:assembleFatDebug]

Parallel execution with configuration on demand is an incubating feature.
Relying on packaging to define the extension of the main artifact has been deprecated and is scheduled to be removed in Gradle 2.0
:SKG:compileFatDebugNdk UP-TO-DATE
:SKG:preBuild
:SKG:preFatDebugBuild
:SKG:checkFatDebugManifest
:SKG:preArmDebugBuild
:SKG:preArmReleaseBuild
:SKG:preArmv7DebugBuild
:SKG:preArmv7ReleaseBuild
:SKG:preFatReleaseBuild
:SKG:preMipsDebugBuild
:SKG:preMipsReleaseBuild
:SKG:preX86DebugBuild
:SKG:preX86ReleaseBuild
:SKG:prepareComAndroidSupportAppcompatV71910Library UP-TO-DATE
:SKG:prepareComGoogleAndroidGmsPlayServices3159Library UP-TO-DATE
:SKG:prepareFatDebugDependencies
:SKG:compileFatDebugAidl UP-TO-DATE
:SKG:compileFatDebugRenderscript UP-TO-DATE
:SKG:generateFatDebugBuildConfig UP-TO-DATE
:SKG:mergeFatDebugAssets UP-TO-DATE
:SKG:generateFatDebugResValues UP-TO-DATE
:SKG:generateFatDebugResources UP-TO-DATE
:SKG:mergeFatDebugResources UP-TO-DATE
:SKG:processFatDebugManifest UP-TO-DATE
:SKG:processFatDebugResources UP-TO-DATE
:SKG:generateFatDebugSources UP-TO-DATE
:SKG:ndkBuild
make: Entering directory `/Users/coudy/git/myapp/SKG/src/main/jni'
[armeabi] Install        : libdatabase_sqlcipher.so => libs/armeabi/libdatabase_sqlcipher.so
[armeabi] Install        : libgenerate.so => libs/armeabi/libgenerate.so
[armeabi] Install        : libsqlcipher_android.so => libs/armeabi/libsqlcipher_android.so
[armeabi] Install        : libstlport_shared.so => libs/armeabi/libstlport_shared.so
[x86] Install        : libdatabase_sqlcipher.so => libs/x86/libdatabase_sqlcipher.so
[x86] Install        : libgenerate.so => libs/x86/libgenerate.so
[x86] Install        : libsqlcipher_android.so => libs/x86/libsqlcipher_android.so
[x86] Install        : libstlport_shared.so => libs/x86/libstlport_shared.so
make: Leaving directory `/Users/coudy/git/myapp/SKG/src/main/jni'
:SKG:compileFatDebugJava UP-TO-DATE
:SKG:preDexFatDebug UP-TO-DATE
:SKG:dexFatDebug UP-TO-DATE
:SKG:processFatDebugJavaRes UP-TO-DATE
:SKG:validateDebugSigning
:SKG:packageFatDebug
:SKG:assembleFatDebug

BUILD SUCCESSFUL

Total time: 15.848 secs

p.s: 我试图在 SQLCipher 用户 google 组上发布此消息,但我没有权限。

最佳答案

我已经在邮件列表线程 here 上回复了你的问题.

关于android - SQLcipher(不同版本)在一个平台上工作,但在另一个平台上崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23460841/

相关文章:

android - finishActivity() 的可能用例是什么

java - writeUTF 后的额外字符

android - 在 Android 中使用 openGL 绘制动态图形

android - 如何在安卓上构建openssl

linux - 如何在主函数中创建局部变量?

android - Android 上的 EGL 与 GLES 2.0(例如 Java)

java - 是否可以将事件从线程发送到 Activity ?

android - 我的应用程序已成功安装到 Android 上,但加载后立即崩溃

assembly - "rep; nop;"在 x86 汇编中意味着什么?和 "pause"指令一样吗?

c - 快速逐字节替换 if