【发布时间】:2014-05-04 19:48:54
【问题描述】:
我在为 ARM/x86 设备构建 SQLcipher 时遇到了奇怪的问题。
当我使用 2.1.1 版本加密数据库并使用 Gradle for ARM 和 x86(胖客户端)构建它时,它在 ARM 设备上正常运行,但在 x86 上抛出错误
"没有找到原生的实现 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;"
然后我将加密的数据库复制到资产,这是我打开数据库的代码:
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 - Genymotion VM 中的多个设备
ARM - 2 个真实设备,android 模拟器
应用程序构建没有错误:
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 组上发布此消息,但我没有权限。
【问题讨论】:
标签: android android-ndk x86 arm sqlcipher