所以,
我想要的是什么:
能够告诉Couchbase Lite(CB Lite)存储数据的位置并在其上实现SQLCipher加密。
我的问题是什么:
即使我对默认目录进行了加密,但只要我告诉Manager使用自定义目录,它就会在尝试创建数据库时抛出异常: 消息:
"错误8,1032(尝试编写只读数据库)执行sql' CREATE INDEX docs_docid ON docs(docid)'"
来源:
" Couchbase.Lite.Storage.SQLCipher"
堆栈跟踪:
"在/ Users / jenkins / jenkins / workspace /中的Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.ExecSQL(System.String sql,SQLitePCL.sqlite3 db,System.Object [] paramArgs)[0x00079] couchbase-lite-net-build@2/1.4/Android/couchbase-lite-net/src/StorageEngines/SQLiteCommon/storage.sqlite.common/src/DatabaseUpgraderFactory_Upgraders.cs:249 \ n在Couchbase.Lite.Storage.SQLCipher。 SqlitePCLRawStorageEngine.ExecSQL(System.String sql,System.Object [] paramArgs)< 0xd70821f8 + 0x0005f> in< 223c4357c0d44faaaa01c387793a30cc>:0 \ n在Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.Open(System.String path,System.Boolean readOnly,System.String schema,Couchbase.Lite.Store.SymmetricKey encryptionKey)[0x00065] in /Users/jenkins/jenkins/workspace/couchbase-lite-net-build@2/1.4/Android/couchbase-lite-net/src/StorageEngines/SQLiteCommon/storage.sqlite.common/src/DatabaseUpgraderFactory.cs:87 34;
现在,奇怪的是,在模拟器上运行我的代码时,它不会抛出任何异常。只有在真实设备(Lenovo TAB 2A Series,Android 5.0.1)上运行我的代码时才会出现此问题。
注意:即使抛出了异常,也会创建自定义文件夹,也会创建couchbase lite文件夹,但在其中只能找到名为db.sqlite3的文件。通常会创建三个文件和一个文件夹:
注2:我已将 WRITE_EXTERNAL_STORAGE 权限添加到Android Manifest。
运行的代码没有问题:
public async Task<Database> OpenDatabaseOnEncryptedWayAsync(string encryptionPassword)
{
Database encryptedDatabase = null;
try
{
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
// Database stored in default directory
encryptedDatabase = Manager.SharedInstance.OpenDatabase(database, options);
}
catch (CouchbaseLiteException e)
{
LogWriterMethod.TryWriteLog(String.Format("Error while creating encrypted database: {0}", e));
Console.WriteLine("Encryption Message: {0}", e);
}
catch (Exception e)
{
LogWriterMethod.TryWriteLog(String.Format("Unhandled Exception on OpenDatabaseOnEncryptedWayAsync method: {0}", e));
Console.WriteLine("Unhandled Exception Message: {0}", e);
}
App.SettingsViewModel.isDatabaseOpen = encryptedDatabase != null;
return encryptedDatabase;
}
抛出(CouchbaseLite)异常的代码:
public async Task<Database> OpenDatabaseOnEncryptedWayAsync(string encryptionPassword)
{
Database encryptedDatabase = null;
try
{
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
// Custom directory
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
var dir = Directory.CreateDirectory(path);
Manager manager = new Manager(dir, Manager.DefaultOptions);
encryptedDatabase = manager.GetDatabase(database);
}
catch (CouchbaseLiteException e)
{
LogWriterMethod.TryWriteLog(String.Format("Error while creating encrypted database: {0}", e));
Console.WriteLine("Encryption Message: {0}", e);
}
catch (Exception e)
{
LogWriterMethod.TryWriteLog(String.Format("Unhandled Exception on OpenDatabaseOnEncryptedWayAsync method: {0}", e));
Console.WriteLine("Unhandled Exception Message: {0}", e);
}
App.SettingsViewModel.isDatabaseOpen = encryptedDatabase != null;
return encryptedDatabase;
}
那么,那里有人知道如何处理这个问题吗?在此先感谢:)
答案 0 :(得分:0)
回到主题,我发现抛出(CouchbaseLite)异常的代码中有一个非常简单的错误。我分享它,以防任何人阅读这个错误:
我正在创建目录,然后使用新路径创建管理器,但我从未将DatabaseOptions分配给新创建的Manager
SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
Key = new SymmetricKey(encryptionPassword);
options.EncryptionKey = Key;
options.Create = true;
options.StorageType = StorageEngineTypes.SQLite;
});
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
var dir = Directory.CreateDirectory(path);
Manager manager = new Manager(dir, Manager.DefaultOptions);
encryptedDatabase = manager.GetDatabase(database);
因此,我们所要做的就是将代码更改为
encryptedDatabase = manager.OpenDatabase(database, options);
就是这样!