首页 > 解决方案 > Sqlite 数据库在 Samsung Android Oreo 8.0 设备中无法正常运行

问题描述

我创建了一个应用程序,它只执行一些数据库读取操作,(从数据库中获取记录并执行一些公式并显示结果)

该应用程序在Lenovo (5.1.1)、Moto (5.1、6.0、7.1.1)、OnePlus (8.1)、Mi A1 (8.0.0)、Micromax (5.0)、Samsung (7.1)上测试的所有设备上运行良好

但它不起作用是三星设备包含(8.0)设备是三星galaxy J8(SM-J810G),三星galaxy S7(SM-G930W8),三星galaxy 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;
  }
}

测试应用.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)     

标签: androidsqlitesamsung-mobileandroid-8.0-oreo

解决方案


尝试在需要时关闭和打开数据库,到目前为止,只需在 checkDataBase() 的代码下方评论它就会像魅力一样工作......

mDB.close();


推荐阅读