正在运行最新版本的Android Studio。专为API级别23及更高版本(棉花糖)构建项目,并使用Pixel XL仿真器。我已经在清单中授予了权限,并在运行时也获得了写访问权限(API 23及更高版本要求)
有一个与此相关的按钮
public void createDatabase(View view) {
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, 1);
}
我在AndroidManifest.xml中也有这个
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这是我的权限授予代码
@Override
public void onRequestPermissionsResult(int requestCode, String
permissions[], int[] grantResults) {
switch (requestCode) {
case 1:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
DbUtil.CreateDb(getApplicationContext().getApplicationInfo().dataDir + "/databases/game360.db");
}
else{
//Permission denied.
}
break;
}
}
这是DBUtil.CreateDb
public static void CreateDb(String dbPath){
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbPath, null);
db.execSQL("CREATE TABLE if not exists user (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"username VARCHAR NOT NULL unique, firstName VARCHAR NOT NULL, lastName VARCHAR NOT NULL)");
ContentValues values = new ContentValues();
values.put("username", "jj678");
values.put("firstName", "brad");
values.put("lastName", "pitt");
db.insert("user",null, values);
db.close();
}
当我在模拟器上运行应用程序并单击按钮时,我将按预期方式弹出权限弹出窗口。在我授予o权限后,create Database被调用,并且失败并显示以下堆栈跟踪(错误代码14)。知道为什么吗?
02-23 17:44:39.347 19358-19358/com.jtech.game360 E/SQLiteLog: (14) cannot open file at line 31278 of [2ef4f3a5b1]
02-23 17:44:39.347 19358-19358/com.jtech.game360 E/SQLiteLog: (14) os_unix.c:31278: (2) open(/data/user/0/com.jtech.game360/databases/game360.db) -
02-23 17:44:39.348 19358-19358/com.jtech.game360 E/SQLiteDatabase: Failed to open database '/data/user/0/com.jtech.game360/databases/game360.db'.
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:207)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:191)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:806)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:709)
at com.jtech.game360.DbUtil.CreateDb(DbUtil.java:13)
at com.jtech.game360.Main2Activity.onRequestPermissionsResult(Main2Activity.java:52)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6553)
at android.app.Activity.dispatchActivityResult(Activity.java:6432)
答案 0 :(得分:1)
似乎您缺少databases
文件夹。试试:
public static void CreateDb(String dbPath){
File f = new File(dbPath);
f.getParentFile().mkdirs();
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbPath, null);
// ...
}
答案 1 :(得分:1)
由于您使用数据库的标准位置,因此不需要权限,因为它们已经存在。
此外,无需对完整路径进行硬编码,而是可以使用上下文的 getDatabasePath(),这是推荐的方法。
您遇到的问题是 dataabses 文件夹不存在,因此无法打开该文件。因此,您需要检查数据库目录/文件夹是否存在,以及是否不创建该文件夹。
此外,如果数据库存在,在获取文件时可以很容易地进行检查,以检查数据库文件夹是否存在,因此无需尝试检查目录是否存在存在,也不能 openOrCreate 数据库,也不要尝试在后续运行中添加已经存在的行。
因此 CreateDB 方法可能更有效:-
// Only context required to be passed (assuming just the one database)
public static void CreateDB(Context context) {
File f = new File(context.getDatabasePath(DBNAME).toString()); //<<<<<<<<<< uses the recommended GetDatabasePath method
// If DB exists no need to waste time doing anything
if (f.exists()) {
return;
}
// Creates the databases directory (or others if directories change in the future)
if (!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f,null); //<<<<<<<<< uses the File to create the database
//Same code as original from now
db.execSQL("CREATE TABLE if not exists user (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"username VARCHAR NOT NULL unique, firstName VARCHAR NOT NULL, lastName VARCHAR NOT NULL)");
ContentValues values = new ContentValues();
values.put("username", "jj678");
values.put("firstName", "brad");
values.put("lastName", "pitt");
db.insert("user",null, values);
db.close();
}
作为利用以上内容(在棒棒糖(5.0)和Pie(10.1)中进行测试)的示例(在活动中):-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//DBUtil.CreateDb(getApplicationContext().getApplicationInfo().dataDir + "/databases/game360.db");
DBUtil.CreateDB(this);
SQLiteDatabase db = SQLiteDatabase.openDatabase(this.getDatabasePath(DBUtil.DBNAME).toString(),null,SQLiteDatabase.OPEN_READWRITE);
Cursor csr = db.query("user",null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
csr.close();
db.close();
}
运行良好,对于第一次和随后的运行,将以下输出记录到日志中:-
02-24 17:58:07.175 9579-9579/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@12c4306e
02-24 17:58:07.176 9579-9579/? I/System.out: 0 {
02-24 17:58:07.176 9579-9579/? I/System.out: id=1
02-24 17:58:07.176 9579-9579/? I/System.out: username=jj678
02-24 17:58:07.176 9579-9579/? I/System.out: firstName=brad
02-24 17:58:07.176 9579-9579/? I/System.out: lastName=pitt
02-24 17:58:07.176 9579-9579/? I/System.out: }
02-24 17:58:07.176 9579-9579/? I/System.out: <<<<<