我正在使用SQLCIPHER读取或写入数据库获取错误

时间:2014-02-27 06:46:29

标签: android database sqlite sqlcipher

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);
    }
}


    }

4 个答案:

答案 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.** { *; }