原文地址:https://www.zybuluo.com/linux1s1s/note/132124
而且有一点我比较好奇的是,为什么有些机型有这个问题(红米,Android5.1.1),而有些机型不会有这个问题呢(红米,Android4.4.2)?
以下是正文:
有些Bug你可能怎么想也想不通,请始终铭记出现Bug首先看看自己的代码哪里出问题了,而不是一直在那郁闷吐槽。废话说到这里,下面直接上干货:
//得到SD卡路径
private final static String DATABASE_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/com/cn21/account/public";
//数据库名
private final static String DATABASE_FILENAME = "account.db3";
public class AccountDBHelper{
private static SQLiteDatabase initDatabase(){
String databaseFilename = DATABASE_PATH + "/" + DATABASE_FILENAME;
File dir = new File(DATABASE_PATH);
if(!dir.exists())
dir.mkdir();
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(databaseFilename, null);
db.execSQL(sql_user);
return db;
}
}
上面代码有啥问题?
如果一旦使用上面代码片段,很可能会抛出以下异常:
01-02 13:29:17.601: E/SQLiteDatabase(2258): Failed to open database '/storage/emulated/0/com/cn21/account/public/account.db3'.
01-02 13:29:17.601: E/SQLiteDatabase(2258): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:339)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:236)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:515)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:207)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:891)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:859)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:696)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:1249)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:1238)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:236)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at com.cn21.account.lib.db.AccountDBHelper.initDatabase(AccountDBHelper.java:114)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at com.cn21.account.lib.db.AccountDBHelper.getCache(AccountDBHelper.java:73)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at com.cn21.account.lib.ui.LoginActivity.onCreate(LoginActivity.java:71)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.Activity.performCreate(Activity.java:5372)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2362)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.ActivityThread.access$700(ActivityThread.java:168)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1329)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.os.Handler.dispatchMessage(Handler.java:99)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.os.Looper.loop(Looper.java:137)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at android.app.ActivityThread.main(ActivityThread.java:5493)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at java.lang.reflect.Method.invokeNative(Native Method)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at java.lang.reflect.Method.invoke(Method.java:525)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
01-02 13:29:17.601: E/SQLiteDatabase(2258): at dalvik.system.NativeStart.main(Native Method)
上面异常大概是说不能打开数据库,所以抛出异常
那么为什么会打不开呢? 按照正常的思维是先检验文件是否存在,如果存在,则直接使用,如果不存在,那么创建相应的目录,所以左思右想,上面的Crash不该有啊。
其实上面的代码有明显的问题,这里先提示一下:
dir.mkdir()
dir.mkdirs()
上面两个方法有啥区别?mkdir()不会创建所有层级,而mkdirs()则可以。对的,就是这个方法的误用导致上面的问题。如果不清楚为啥,可以自行查阅Java JDK,这里不再赘述。