Hiee,我正在使用sqlcipher来读取数据库但是在读取数据之前它会给出以下错误。下面是我的logcat请看看。
E/AndroidRuntime(21826): FATAL EXCEPTION: main
02-27 11:33:10.608: E/AndroidRuntime(21826): java.lang.UnsatisfiedLinkError: Native method not found: net.sqlcipher.database.SQLiteDatabase.dbopen:(Ljava/lang/String;I)V
02-27 11:33:10.608: E/AndroidRuntime(21826): at net.sqlcipher.database.SQLiteDatabase.dbopen(Native Method)
02-27 11:33:10.608: E/AndroidRuntime(21826): at net.sqlcipher.database.SQLiteDatabase. <init>(SQLiteDatabase.java:1942)
02-27 11:33:10.608: E/AndroidRuntime(21826): at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1920)
02-27 11:33:10.608: E/AndroidRuntime(21826): at example.SQLDemoActivity.onCreate(SQLDemoActivity.java:19)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.Activity.performCreate(Activity.java:5020)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread.access$600(ActivityThread.java:149)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1300)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.os.Handler.dispatchMessage(Handler.java:99)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.os.Looper.loop(Looper.java:153)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread.main(ActivityThread.java:4987)
02-27 11:33:10.608: E/AndroidRuntime(21826): at java.lang.reflect.Method.invokeNative(Native Method)
02-27 11:33:10.608: E/AndroidRuntime(21826): at java.lang.reflect.Method.invoke(Method.java:511)
02-27 11:33:10.608: E/AndroidRuntime(21826): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
02-27 11:33:10.608: E/AndroidRuntime(21826): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
02-27 11:33:10.608: E/AndroidRuntime(21826): at dalvik.system.NativeStart.main(Native Method)
以下是我正在尝试运行此sqlcipher类的链接 sqlcipher link
这是我正在调用SQLiteDatabase.loadLibs(this)的类,请看看
public class SQLDemoActivity extends Activity
{
EventDataSQLHelper eventsData;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//you must set Context on SQLiteDatabase first
SQLiteDatabase.loadLibs(this);
String password = "foo123";
eventsData = new EventDataSQLHelper(this);
//then you can open the database using a password
SQLiteDatabase db = eventsData.getWritableDatabase(password);
for (int i = 1; i < 100; i++)
addEvent("Hello Android Event: " + i, db);
db.close();
db = eventsData.getReadableDatabase(password);
Cursor cursor = getEvents(db);
showEvents(cursor);
db.close();
}
@Override
public void onDestroy() {
eventsData.close();
}
private void addEvent(String title, SQLiteDatabase db) {
ContentValues values = new ContentValues();
values.put(EventDataSQLHelper.TIME, System.currentTimeMillis());
values.put(EventDataSQLHelper.TITLE, title);
db.insert(EventDataSQLHelper.TABLE, null, values);
}
private Cursor getEvents(SQLiteDatabase db) {
Cursor cursor = db.query(EventDataSQLHelper.TABLE, null, null, null, null,
null, null);
startManagingCursor(cursor);
return cursor;
}
private void showEvents(Cursor cursor) {
StringBuilder ret = new StringBuilder("Saved Events:\n\n");
while (cursor.moveToNext()) {
long id = cursor.getLong(0);
long time = cursor.getLong(1);
String title = cursor.getString(2);
ret.append(id + ": " + time + ": " + title + "\n");
}
Log.i("sqldemo",ret.toString());
}
}
以下是方法主体
public class SQLiteDatabase extends SQLiteClosable {
private static final String TAG = "Database";
private static final int EVENT_DB_OPERATION = 52000;
private static final int EVENT_DB_CORRUPT = 75004;
public int status(int operation, boolean reset){
return native_status(operation, reset);
}
private static void loadICUData(Context context, File workingDir)
{
try {
File icuDir = new File(workingDir, "icu");
if(!icuDir.exists()) icuDir.mkdirs();
File icuDataFile = new File(icuDir, "icudt46l.dat");
if(!icuDataFile.exists()) {
ZipInputStream in = new ZipInputStream(context.getAssets().open("icudt46l.zip"));
in.getNextEntry();
OutputStream out = new FileOutputStream(icuDataFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
{
out.write(buf, 0, len);
}
in.close();
out.flush();
out.close();
}
}
catch (Exception e)
{
Log.e(TAG, "Error copying icu data file", e);
}
}
public static void loadLibs (Context context)
{
loadLibs(context, context.getFilesDir());
}
public static void loadLibs (Context context, File workingDir)
{
System.loadLibrary("stlport_shared");
System.loadLibrary("sqlcipher_android");
System.loadLibrary("database_sqlcipher");
boolean systemICUFileExists = new File("/system/usr/icu/icudt46l.dat").exists();
String icuRootPath = systemICUFileExists ? "/system/usr" : workingDir.getAbsolutePath();
setICURoot(icuRootPath);
if(!systemICUFileExists)
{
loadICUData(context, workingDir);
}
}
}
答案 0 :(得分:10)
如果在尝试使用数据库之前未调用SQLiteDatabase.loadLibs()
,则通常会发生该错误。
答案 1 :(得分:3)
UnsatisfiedLinkError
是由于您的应用程序未包含本机库。有关将SQLCipher与现有应用程序集成的示例,请查看this教程。或者,请查看适用于Android的SQLCipher test suite。
答案 2 :(得分:2)
@CommonsWare是正确的,你就投票了。
当你的应用程序从长时间休眠状态恢复时,libs已被循环使用,因此恢复状态正在崩溃,因为libs不存在。
把你的SQLiteDatabase.loadLibs(this);在super.onCreate(savedInstanceState)
之前@Override
public void onCreate(Bundle savedInstanceState) {
//you must set Context on SQLiteDatabase first
SQLiteDatabase.loadLibs(this);
super.onCreate(savedInstanceState);
答案 3 :(得分:0)
如果SQLiteDatabase.loadLibs()
,请确保将这些行添加到ProGuard文件中:
#Keep SQLCypher classes
-keep class net.sqlcipher.** { *; }