我在Android应用程序中遇到了一个奇怪的行为。当我开始应用程序并创建表并将信息输入数据库时,数据库正在工作。
但是当我从应用程序退出并再次登录时,我收到错误。
07-04 02:54:03.427 5171-5877/? E/Database: CREATE TABLE android_metadata failed
07-04 02:54:03.427 5171-5877/? E/Database: Failed to setLocale() when constructing, closing the database
net.sqlcipher.database.SQLiteException: file is encrypted or is not a database
at net.sqlcipher.database.SQLiteDatabase.native_setLocale(Native Method)
at net.sqlcipher.database.SQLiteDatabase.setLocale(SQLiteDatabase.java:2474)
at net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal(SQLiteDatabase.java:2338)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1087)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1150)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:162)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:129)
at com.package.helper.MyOpenHelper.getWritableDatabase(MyOpenHelper.java:58)
at com.package.provider.MyContentProvider.query(MyContentProvider.java:31)
at android.content.ContentProvider.query(ContentProvider.java:857)
at android.content.ContentProvider$Transport.query(ContentProvider.java:200)
at android.content.ContentResolver.query(ContentResolver.java:461)
at android.support.v4.content.ContentResolverCompatJellybean.query(ContentResolverCompatJellybean.java:29)
at android.support.v4.content.ContentResolverCompat$ContentResolverCompatImplJB.query(ContentResolverCompat.java:57)
at android.support.v4.content.ContentResolverCompat.query(ContentResolverCompat.java:125)
at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:59)
at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:37)
at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:296)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:54)
at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:42)
at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:128)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
MyOpenHelper.java
@ContextSingleton
public class MyOpenHelper extends SQLiteOpenHelper {
Context context;
private static final String PWD = "databse password";
@Inject
public MyOpenHelper(Context context) {
super(context, Constants.DB_NAME, null, 25);
this.context = context;
SQLiteDatabase.loadLibs(context);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public SQLiteDatabase getWritableDatabase() {
return getWritableDatabase(PWD);
}
public SQLiteDatabase getReadableDatabase() {
return getReadableDatabase(PWD);
}
MyContentProvider.java
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
import com.google.inject.Inject;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteQueryBuilder;
import roboguice.content.RoboContentProvider;
public class MyContentProvider extends RoboContentProvider {
@Inject
MyOpenHelper openHelper;
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
try {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(parsePath(uri));
SQLiteDatabase db = openHelper.getWritableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
// Tell the cursor what uri to watch, so it knows when its source data changes
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}catch(Exception ex){
ex.printStackTrace();
}
return null;
}
@Override
public String getType(Uri uri) {
return "";
}
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
SQLiteDatabase db = openHelper.getWritableDatabase();
long rowId = db.insert(parsePath(uri), null, initialValues);
if (rowId > 0) {
Uri noteUri = ContentUris.withAppendedId(uri, rowId);
getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
@Override
public int delete(Uri uri, String where, String[] whereArgs) {
SQLiteDatabase db = openHelper.getWritableDatabase();
int i = db.delete(parsePath(uri), where, whereArgs);
getContext().getContentResolver().notifyChange(uri, null);
return i;
}
@Override
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
SQLiteDatabase db = openHelper.getWritableDatabase();
int count = db.update(parsePath(uri), values, where, whereArgs);
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
public String parsePath(Uri uri) {
String path = uri.getPath();
return parsePath(path);
}
public String parsePath(String path) {
//TODO implement method correctly using RegExp
//When update gnerates must return following string /table_name/id
int index = path.indexOf("/");
if (index < 0) {
return path;
} else {
index = path.lastIndexOf("/");
if (index > 0) {
String str = path.substring(index + 1, path.length());
try {
Integer.valueOf(str);
return parsePath(path.substring(0, index));
} catch (NumberFormatException e) {
return str;
}
} else {
return path.replace("/", "");
}
}
}
}
由于我不知道为什么发生此错误仍无法解决问题。有人可以提出建议。
仅供参考:它是使用Salesforce Android Mobile SDK的Salesforce应用程序。并为salesforce SmartStore SyncAdapter使用2个ContentProviders。但我认为它对这个问题没有影响