我正在使用 SQLiteOpenHelper 编写所有查询等。当我在内部写入和读取数据库时,一切工作正常,但如果我想将数据库保存到手机上的文件夹中,我会得到以下信息:
01-03 07:12:24.786 16097-16097/com.myApp.app E/SQLiteLog: (14) cannot open file at line 31278 of [2ef4f3a5b1]
01-03 07:12:24.786 16097-16097/com.myApp.app E/SQLiteLog: (14) os_unix.c:31278: (2) open(/storage/emulated/0/myApp/db/app) -
01-03 07:12:24.787 16097-16097/com.myApp.app E/SQLiteDatabase: Failed to open database '/storage/emulated/0/myApp/db/app'.
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.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:571)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:269)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at com.myApp.db.DbMain.getCountValueForMainMenu(DbMain.java:576)
at com.myApp.app.Beginner.openApp(Beginner.java:672)
at com.myApp.app.Beginner.checkfilepermission(Beginner.java:341)
at com.myApp.app.Beginner.onCreate(Beginner.java:332)
at android.app.Activity.performCreate(Activity.java:6251)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
DBhelper类文件:
public DbMain(Context context)
{
// code to create database in internal storage
//super(context, DATABASE_NAME, null, DATABASE_VERSION);
//code to create database in External SD card
super(context, Environment.getExternalStorageDirectory()
+ File.separator + "/myApp/db/"
+ File.separator
+ DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db)
{
//1
String CREATE_TABLE_MENU = "CREATE TABLE IF NOT EXISTS " + TABLE_MENU_LOCAL +"("
+KEY_MENUID_LOCAL + " TEXT,"
+KEY_MENUNAME_LOCAL + " TEXT,"
+KEY_ISCHILD_LOCAL + " TEXT,"
+KEY_CATEGORYURL_LOCAL + " TEXT,"
+KEY_IMAGEID_LOCAL + " TEXT,"
+KEY_MENUNAME_DESCRIPTION_LOCAL + " TEXT"
+ ")";
db.execSQL(CREATE_TABLE_MENU);
}
//to get totalcount
public int getCountValueForMainMenu()
{
SQLiteDatabase db = this.getWritableDatabase();
int count = 0;
Cursor cursor = db.rawQuery("SELECT COUNT (*) FROM " + TABLE_MENU_LOCAL, null);
if(null != cursor)
{
if(cursor.moveToFirst() && 0 < cursor.getCount())
{
count = cursor.getInt(0);
}
cursor.close();
}
return count;
}
在内部创建数据库时调用相同的方法等,一切都很好。
可能出了什么问题?
谢谢!
检查这几点
1.READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE在androidmanifest.xml中定义
2.创建外部存储目录。如果没有,则在调用db Helper的构造函数之前创建存储目录
试试 dbHelper 的这段代码
public class DbHelper extends SQLiteOpenHelper {
private static final String TABLE_MENU_LOCAL = "menu";
private static final String KEY_MENUID_LOCAL ="menuid" ;
private static final String KEY_MENUNAME_LOCAL ="menuname" ;
private static final String KEY_ISCHILD_LOCAL ="ischild" ;
private static final String KEY_CATEGORYURL_LOCAL ="categoryurl" ;
private static final String KEY_IMAGEID_LOCAL ="imageid" ;
private static final String KEY_MENUNAME_DESCRIPTION_LOCAL ="description" ;
private static String DATABASE_NAME="dbtest.db";
private static int DATABASE_VERSION=1;
public DbHelper(Context context)
{
// code to create database in internal storage
//super(context, DATABASE_NAME, null, DATABASE_VERSION);
//code to create database in External SD card
super(context, Environment.getExternalStorageDirectory()
+ File.separator + "/myapp/db/"
+ File.separator
+ DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//1
String CREATE_TABLE_MENU = "CREATE TABLE IF NOT EXISTS " + TABLE_MENU_LOCAL +"("
+KEY_MENUID_LOCAL + " TEXT,"
+KEY_MENUNAME_LOCAL + " TEXT,"
+KEY_ISCHILD_LOCAL + " TEXT,"
+KEY_CATEGORYURL_LOCAL + " TEXT,"
+KEY_IMAGEID_LOCAL + " TEXT,"
+KEY_MENUNAME_DESCRIPTION_LOCAL + " TEXT"
+ ")";
db.execSQL(CREATE_TABLE_MENU);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public void insertValues(){
SQLiteDatabase db=this.getWritableDatabase();
for(int count=0;count<5;count++) {
ContentValues insertValues = new ContentValues();
insertValues.put(KEY_MENUID_LOCAL, "1");
insertValues.put(KEY_MENUNAME_LOCAL, "Food1");
insertValues.put(KEY_ISCHILD_LOCAL, "No");
insertValues.put(KEY_CATEGORYURL_LOCAL, "Demo");
insertValues.put(KEY_IMAGEID_LOCAL, "imageid");
insertValues.put(KEY_MENUNAME_DESCRIPTION_LOCAL, "Description");
db.insert(TABLE_MENU_LOCAL, null, insertValues);
}
}
//to get totalcount
public int getCountValueForMainMenu()
{
SQLiteDatabase db = this.getWritableDatabase();
int count = 0;
Cursor cursor = db.rawQuery("SELECT COUNT (*) FROM " + TABLE_MENU_LOCAL, null);
if(null != cursor)
{
if(cursor.moveToFirst() && 0 < cursor.getCount())
{
count = cursor.getInt(0);
}
cursor.close();
}
return count;
}
}
并从您的活动或类似的任何地方调用它
String storage_folder = "/myapp/db";
File f = new File(Environment.getExternalStorageDirectory(), storage_folder);
if (!f.exists()) {
f.mkdirs();
}
DbHelper lDbHeper=new DbHelper(MainActivity.this);
lDbHeper.insertValues();
int count=lDbHeper.getCountValueForMainMenu();
Log.i("Count is:",""+count);
让我知道这对你有没有帮助
确保您拥有清单中声明的写入权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
如果您的目标是 API 23 或更高版本,您还需要 在运行时请求权限。
<uses-permission
android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
并添加应用程序标签
android:requestLegacyExternalStorage="true"
此外,这是要添加到您的主要活动中的代码片段:
if (Build.VERSION.SDK_INT >= 30) {
if (!Environment.isExternalStorageManager()) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Please Allow File Access")
.setPositiveButton("Go To Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finishAffinity();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
} else {
// Proceed with your app logic
}
} else {
// Proceed with your app logic for lower SDK versions
}