android - SQL Cipher android studio中的“没有这样的表”
问题描述
我试图保护我的 SQLDatabase 免受反编译。我在此发布此问题。但没有人回答。我尝试使用SQLCipher。
DBHelper.java:
public class DBHelper extends SQLiteOpenHelper {
private static String DB_NAME = "test.sqlite";
private static String DB_PATH = "";
private SQLiteDatabase myDatabase;
private static final String PASS = "sajjad";
private Context context;
public DBHelper(Context context) {
super(context, DB_NAME, null, 2);
if (Build.VERSION.SDK_INT >= 15)
DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
else
DB_PATH = Environment.getDataDirectory() + "/data/" + context.getPackageName() + "/databases/";
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void checkAndCopyDatabase() {
boolean dbExist = checkDatabases();
if (dbExist) {
Log.d("TAG", "already exist");
} else {
this.getReadableDatabase(PASS);
}
try {
copyDatabases();
} catch (IOException e) {
e.printStackTrace();
Log.d("TAG", "Error copy DataBase");
}
}
public void openDatabase() {
String myPath = DB_PATH + DB_NAME;
myDatabase = SQLiteDatabase.openDatabase(myPath, PASS, null, SQLiteDatabase.OPEN_READWRITE);
}
private void copyDatabases() throws IOException {
InputStream myInput = context.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int lenght;
while ((lenght = myInput.read(buffer)) > 0)
myOutput.write(buffer, 0, lenght);
}
private boolean checkDatabases() {
SQLiteDatabase checkdb = null;
try {
String myPath = DB_PATH + DB_NAME;
checkdb = SQLiteDatabase.openDatabase(myPath, PASS, null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
}
if (checkdb != null)
checkdb.close();
return checkdb != null ? true : false;
}
public synchronized void close() {
if (myDatabase != null) {
myDatabase.close();
}
super.close();
}
public Cursor QueryData(String query) {
return myDatabase.rawQuery(query, null);
}}
并将数据库加载到 MainActivity 中的 recyclerView:
public class MainActivity extends AppCompatActivity {
DBHelper dataBaseHelper;
Cursor cursor;
ArrayList<Info> arrayList = new ArrayList<Info>();
Info item;
private Adapter adapterMain;
@Override
protected void onCreate(Bundle savedInstanceState) {
SQLiteDatabase.loadLibs(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recy);
dataBaseHelper = new DBHelper(this);
try {
dataBaseHelper.checkAndCopyDatabase();
dataBaseHelper.openDatabase();
} catch (SQLException e) {
e.printStackTrace();
}
try {
cursor = dataBaseHelper.QueryData("SELECT name FROM dictionary");
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
item = new Info();
item.setName(cursor.getString(0));
arrayList.add(item);
} while (cursor.moveToNext());
}
}
} catch (SQLException e) {
e.printStackTrace();
}
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
adapterMain = new Adapter(this, arrayList);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(adapterMain);
}}
安装应用程序时,应用程序崩溃。可以帮我?
错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{ir.seljad.sqlitechipher/ir.seljad.sqlitechipher.MainActivity}: **net.sqlcipher.database.SQLiteException: no such table: dictionary: , while compiling: SELECT name FROM dictionary**
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2974)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3059)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1724)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:7000)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
Caused by: net.sqlcipher.database.SQLiteException: no such table: dictionary: , while compiling: SELECT name FROM dictionary
at net.sqlcipher.database.SQLiteCompiledSql.native_compile(Native Method)
at net.sqlcipher.database.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:91)
at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:64)
at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:89)
at net.sqlcipher.database.SQLiteQuery.<init>(SQLiteQuery.java:48)
at net.sqlcipher.database.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:60)
at net.sqlcipher.database.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1954)
at net.sqlcipher.database.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1840)
at ir.seljad.sqlitechipher.DBHelper.QueryData(DBHelper.java:102)
at ir.seljad.sqlitechipher.MainActivity.onCreate(MainActivity.java:39)
at android.app.Activity.performCreate(Activity.java:7258)
at android.app.Activity.performCreate(Activity.java:7249)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1222)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)
解决方案
我认为根本问题是数据库目录不存在,因此在检查数据库是否存在时尝试打开数据库会导致异常。由于它位于 try/catch 构造中,因此该异常被隐藏。结果是一个空数据库,因此没有表。
我建议如下:-
使用 Context 的getDatabasePath来确定路径。这消除了对数据库名称以外的任何内容(包括构建版本变体)进行硬编码的需要。
不要打开数据库检查数据库是否存在,而是检查文件是否存在。
如果文件存在,则返回 true。
如果File不存在,则使用File的getParentFile方法检查File的父File(数据库目录)是否存在。如果父File不存在,则使用File的mkdirs方法创建目录。
返回假。
有关示例代码,请参见此答案。
推荐阅读
- prometheus - Prometheus:计算仪表值发生变化的次数
- java - Microsoft 图:使用 Put 请求 Java 更新文档
- php - 使用相同的 id Laravel 再次存储数据
- pandas - 将日期操作代码转换为函数,然后将其应用于多列
- reactjs - 在“加载”时反应可加载(延迟加载)?
- c# - 使用 OLEDB 提供程序连接到 Access 数据库崩溃(自 Office 365 Build 12430.20184 起)
- python - keep_prob: 0.8 是什么意思?
- curl - 通过 curl 向 API 发送音频数据
- python - 如果答案是随机的,我如何追踪对原始答案的响应?
- google-cloud-platform - 在 GKE 中使用 N2 机器类型 - (Google Kubernetes Engine)