我已经创建了一个仅执行一些数据库读取操作的应用程序(从db中获取记录并执行一些公式并显示结果)
该应用程序在通过 Lenovo(5.1.1),Moto(5.1、6.0、7.1.1),OnePlus(8.1),Mi A1(8.0.0),Micromax(5.0)测试的所有设备上均能正常运行),三星(7.1)
但三星设备包含(8.0),但无法正常工作 设备是三星银河J8(SM-J810G),三星银河S7(SM-G930W8),三星银河S9(SM-G960U)。
下面是我使用的代码。
DBQuery.java
package com.test.dbhelper;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import com.test.common.DBConstants;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class DBAdapter extends SQLiteOpenHelper implements DBConstants {
private static String DB_PATH = "";
private SQLiteDatabase mDB;
private static int DB_VERSION = 1;
private Context appContext;
public DBAdapter(Context context) {
super(context.getApplicationContext(), DB_NAME, null, DB_VERSION);
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
appContext = context;
createDataBase();
}
@Override
public void onCreate(SQLiteDatabase db) {
System.out.println("DB Helper On Create....");
this.mDB = db;
createDataBase();
}
public void createDataBase() {
SQLiteDatabase db_Read = null;
try {
boolean dbExist = checkDataBase();
if (dbExist) {
} else {
db_Read = this.getReadableDatabase();
db_Read.close();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean checkDataBase() {
try {
String myPath = DB_PATH + DB_NAME;
mDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
}
if (mDB != null) {
mDB.close();
}
return mDB != null ? true : false;
}
private void copyDataBase() throws IOException {
InputStream myInput = appContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() {
try {
String myPath = DB_PATH + DB_NAME;
mDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READONLY);
} catch (Exception e) {
System.out.println("Open Database failed...");
e.printStackTrace();
}
}
public DBAdapter open() throws SQLException {
mDB = getWritableDatabase();
return this;
}
@Override
public synchronized void close() {
if (mDB != null)
mDB.close();
super.close();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public int insertData(String table_name, ContentValues initialValues) {
int record = (int) mDB.insert(table_name, null, initialValues);
return record;
}
public int deleteData(String table_name, String whereClause) {
return (int) mDB.delete(table_name, whereClause, null);
}
public int updateData(String table_name, ContentValues initialValues,
String whereClause) {
return mDB.update(table_name, initialValues, whereClause, null);
}
public Cursor executeRawQuery(String query) {
Cursor c = null;
c = mDB.rawQuery(query, null);
return c;
}
}
DBConstants.java
package com.test.common
interface DBConstants {
companion object {
const val DB_NAME = "test.db3"
const val TAB_WELL_RITE = "well_rite"
const val TAB_WELL_RITE_TANK_VOLUME_IN_GALLON = "tank_volume_in_gallon"
const val TAB_WELL_RITE_MODEL_WELL_RITE = "model_well_rite"
const val TAB_WELL_RITE_MODEL_CHALLANGER = "model_challanger"
const val TAB_WELL_RITE_MODEL_FLEX_LITE = "model_flex_lite"
const val TAB_WELL_RITE_TANK_VOLUME_IN_LITRE = "tank_volume_in_litre"
}
}
DBQuery.java
package com.test.dbhelper;
import android.database.Cursor;
import com.test.activity.TestApp;
import com.test.common.Constants;
import com.test.common.DBConstants;
import com.test.common.LogUtils;
import java.util.HashMap;
public class DBQuery implements DBConstants, Constants {
public static String TAG = "DBQuery";
public static HashMap<String, String> getWellRiteModels(String tableName, String field, double value) {
HashMap<String, String> dataMap = new HashMap<>();
String query = "SELECT * " + " FROM " + tableName
+ " WHERE " + field + " >= '" + value + "' order by " + field + " LIMIT 1";
Cursor cursor = TestApp.dbAdapter.executeRawQuery(query);
if (cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
dataMap.put(WELL_RITE, cursor.getString(1));
dataMap.put(CHALLANGER, cursor.getString(2));
dataMap.put(FLEX_LITE, cursor.getString(3));
}
}
return dataMap;
}
}
TestApp.kt
package com.test.activity
import android.app.Application
import com.crashlytics.android.Crashlytics
import com.test.dbhelper.DBAdapter
import io.fabric.sdk.android.Fabric
class TestApp : Application() {
companion object {
lateinit var dbAdapter: DBAdapter
}
override fun onCreate() {
super.onCreate()
Fabric.with(this, Crashlytics())
dbAdapter = DBAdapter(applicationContext)
dbAdapter.openDataBase()
}
}
从MainActivity.java中,我正在调用下面的函数以使用DBQuery方法获取数据。
var dataMap: HashMap<kotlin.String, kotlin.String> = HashMap()
dataMap = DBQuery.getWellRiteModels(TAB_WELL_RITE, DBConstants.TAB_WELL_RITE_TANK_VOLUME_IN_GALLON, 32.50)
我的test.db3数据库的资产文件夹中有记录。 它将从资产复制到/ data / data / ...,如您在DBAdapter.java类中看到的代码。
Android 8.0的三星设备是否存在任何特定问题?
下面是错误日志
Fatal Exception: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/user/0/com.test/databases/test.db3
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1742)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1685)
at com.test.dbhelper.DBAdapter.executeRawQuery(DBAdapter.java:147)
at com.test.dbhelper.DBQuery.getWellRiteModels(DBQuery.java:26)
答案 0 :(得分:1)
尝试在需要时关闭和打开数据库,到目前为止,只需在checkDataBase()的下面的代码中注释一下,它将像魅力一样工作...
mDB.close();
答案 1 :(得分:0)
所以我解决了Oreo中的类似问题,该问题来自特定版本中Sqlite的优化,该版本在其他设备上运行良好,但不适用于Oreo。如果您有复杂的查询,请尝试使用交叉联接为优化器强制某些表的顺序,并在实际查询之前执行“编译优化”。
使用EXPLAIN QUERY PLAN可以发现,在Oreo中,优化器在某个时刻扫描的表与其他设备不同。该表很大,因此查询花费了很多时间。我无法真正解释为什么这样做,但是根据SQLite documentation的说法,可能会有关于复杂子查询的回归。
我不知道它是否对您有帮助,但对我有用。