android.database.sqlite.SQLiteCantOpenDatabaseException:未知错误(代码 14):无法打开数据库仍然无法解决问题

android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database still unable to fix issue

这个问题已经有人问过了,但是按照很多人的步骤我仍然无法解决这个问题,请帮忙。 我还在清单文件中添加了权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

这里是 logcat 错误。

07-17 15:23:58.253 14526-14526/com.techmobile2.yogahome E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.techmobile2.yogahome, PID: 14526
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.techmobile2.yogahome/com.techmobile2.yogahome.SettingPage}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2480)
    at android.app.ActivityThread.access0(ActivityThread.java:151)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1377)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:155)
    at android.app.ActivityThread.main(ActivityThread.java:5725)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1030)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:825)
 Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
    at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:235)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:219)
    at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:468)
    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:190)
    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:182)
    at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:874)
    at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:854)
    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:752)
    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:727)
    at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getReadableDatabase(SQLiteAssetHelper.java:264)
    at com.techmobile2.yogahome.Database.YogaDB.getSettingMode**(YogaDB.java:21)**
    at com.techmobile2.yogahome.SettingPage.onCreate**(SettingPage.java:41)**
    at android.app.Activity.performCreate(Activity.java:6018)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2370)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2480) 
    at android.app.ActivityThread.access0(ActivityThread.java:151) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1377) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:155) 
    at android.app.ActivityThread.main(ActivityThread.java:5725) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1030) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:825) 

这是 yogaDB.java 文件,我也会提到行号

public class YogaDB extends SQLiteAssetHelper {

private static final String DB_NAME = "yoga.db";
private static final int DB_VER=1;

public YogaDB(Context context) {
    super(context, DB_NAME, null, DB_VER);
}

public int getSettingMode()
{
    **SQLiteDatabase db = getReadableDatabase();** //THIS is line 21
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

    String[] sqlSelect = {"Mode"};
    String sqlTable = "Setting";

    qb.setTables(sqlTable);
    Cursor c = qb.query(db,sqlSelect,null,null,null,null,null);
    c.moveToFirst();
    return c.getInt(c.getColumnIndex("Mode"));
}

public void saveSettingMode(int value)
{
    SQLiteDatabase db = getReadableDatabase();
    String query = "UPDATE Setting SET Mode = "+value;
    db.execSQL(query);
}

这里是SettingPage.java,我还会提到行号

public class SettingPage extends AppCompatActivity {

Button btnSave;
RadioButton rdiEasy,rdiMedium,rdiHard;
RadioGroup rdiGroup;
YogaDB yogaDB;
ToggleButton switchAlarm;
TimePicker timePicker;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_setting_page);

    //Init view
    btnSave = (Button)findViewById(R.id.btnSave);
    rdiGroup = (RadioGroup)findViewById(R.id.rdiGroup);
    rdiEasy = (RadioButton)findViewById(R.id.rdiEasy);
    rdiMedium = (RadioButton)findViewById(R.id.rdiMedium);
    rdiHard = (RadioButton)findViewById(R.id.rdiHard);

    switchAlarm = (ToggleButton)findViewById(R.id.switchAlarm);

    timePicker = (TimePicker)findViewById(R.id.timePicker);

    yogaDB = new YogaDB(this);

    int mode = yogaDB.getSettingMode(); this is line 41
    setRadioButton(mode);

    //Event
    btnSave.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            saveWorkoutMode();
        }
    });

}

private void saveWorkoutMode() {
    int selectedID = rdiGroup.getCheckedRadioButtonId();
    if(selectedID == rdiEasy.getId())
        yogaDB.saveSettingMode(0);
    else if(selectedID == rdiMedium.getId())
        yogaDB.saveSettingMode(1);
    else if(selectedID == rdiHard.getId())
        yogaDB.saveSettingMode(2);
}

private void setRadioButton(int mode) {
    if(mode == 0)
        rdiGroup.check(R.id.rdiEasy);
    else if(mode == 1)
        rdiGroup.check(R.id.rdiMedium);
    else if(mode == 2)
        rdiGroup.check(R.id.rdiHard);
}

我的 sql 数据库文件名是 yoga.db 请帮我解决我的问题

问题: 大多数时候 SQLiteCantOpenDatabaseException 发生在您从多线程访问 sqlite 数据库时。假设您在一个线程中打开了数据库,并试图在另一个线程中访问数据库将导致 SQLiteCantOpenDatabaseException 异常。

解决方案:为你的 SQLiteOpenHelper 创建一个单例对象class,并始终对多个线程使用相同的实例。

示例:

DBHelper class:

public class DBHelper extends SQLiteOpenHelper {
  private DBHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
  }

  public synchronized static DBHelper getInstance(Context context) {
    if (dbHelper == null) {
        dbHelper = new DBHelper(context);
    }

    return dbHelper;
  }

  @Override
  public void onCreate(SQLiteDatabase sqLiteDatabase) {
    //...
  }

  @Override
  public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    //...
    onCreate(sqLiteDatabase);
  }
}

用法:

private static SQLiteDatabase database;


DBHelper dbHelper = DBHelper.getInstance(context);
if (database == null) {
  database = dbHelper.getWritableDatabase();
}

注意:切勿自行关闭 SqliteDatabase 实例android系统会自动关闭。