我正試圖將數據庫與APK捆綁在一起。我在我的設備上使用Android Studio 2.2.3和API 24(物理和模擬器)。無法在android studio中打開SQLite數據庫
基本上我想要做的是,使用我已經創建的數據庫(使用python創建)並從該數據庫爲應用程序生成動態HTML。我讀過,我們不能直接使用這個數據庫,我們必須將其複製到app/APK。
我得到的調試日誌以下錯誤:
E/SQLiteLog: (14) cannot open file at line 32456 of [bda77dda96]
E/SQLiteLog: (14) os_unix.c:32456: (2) open(/data/data/com.sunnah.sunnahapp/databases/test.sqlite) -
E/SQLiteDatabase: Failed to open database '/data/data/com.sunnah.sunnahapp/databases/test.sqlite'.
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:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
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:808)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:793)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:696)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:671)
at com.sunnah.sunnahapp.DatabaseHelper1.openDataBase(DatabaseHelper1.java:133)
at com.sunnah.sunnahapp.DatabaseHelper1.<init>(DatabaseHelper1.java:38)
at com.sunnah.sunnahapp.MainActivity.onCreate(MainActivity.java:56)
at android.app.Activity.performCreate(Activity.java:6736)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2636)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2744)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1493)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6195)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:874)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sunnah.sunnahapp, PID: 14478
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sunnah.sunnahapp/com.sunnah.sunnahapp.MainActivity}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2683)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2744)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1493)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6195)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:874)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764)
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:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
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:808)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:793)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:696)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:671)
at com.sunnah.sunnahapp.DatabaseHelper1.openDataBase(DatabaseHelper1.java:133)
at com.sunnah.sunnahapp.DatabaseHelper1.<init>(DatabaseHelper1.java:38)
at com.sunnah.sunnahapp.MainActivity.onCreate(MainActivity.java:56)
at android.app.Activity.performCreate(Activity.java:6736)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2636)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2744)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1493)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6195)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:874)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:764)
E/MQSEventManagerDelegate: failed to get MQSService.
I/Process: Sending signal. PID: 14478 SIG: 9
Disconnected from the target VM, address: 'localhost:8602', transport: 'socket'
我試圖尋找對SO一些解決方案,但他們並沒有爲我工作。有人說數據庫大小可能是問題。我的數據庫是15MB,然後我創建了一個test.sqlite數據庫只有一個表和行。其他人表示,這是因爲SD卡上的權限。我不使用SD卡。它仍然沒有工作。錯誤保持不變。
我嘗試將我的test.sqlite數據庫放在資產和資產/數據庫文件夾中,但它仍然給出相同的錯誤。
下面是我的我的代碼:
DatabaseHelper1.java
package com.sunnah.sunnahapp;
import android.content.Context;
import android.content.ContextWrapper;
import android.database.sqlite.SQLiteException;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.util.Log;
public class DatabaseHelper1 extends SQLiteOpenHelper {
//The Android's default system path of your application database.
private static String DB_PATH; //"/data/data/YOUR_PACKAGE/databases/";
private static String DB_NAME = "test.sqlite";
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* @param context
*/
public DatabaseHelper1(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
//Write a full path to the databases of your application
String packageName = context.getPackageName();
DB_PATH = String.format("/data/data/%s/databases/", packageName);
openDataBase();
}
/**
* Creates a empty database on the system and rewrites it with your own database.
* */
public void createDataBase() throws IOException {
Log.d("Create DB Func", "My Message");
boolean dbExist = checkDataBase();
Log.d("Past DB Create", "My Message 1");
if(dbExist){
Log.e(this.getClass().toString(), "Copying error");
}else{
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
Log.d("getDatabase Func", "My Messag2e");
try {
Log.d("b4 Copy DB Func", "My Messag2e");
copyDataBase();
Log.d("after copy dB Func", "My Messag2e");
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
* @return true if it exists, false if it doesn't
*/
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch(SQLiteException e){
Log.e(this.getClass().toString(), "Error while checking db");
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException{
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
@Override
public synchronized void close() {
if(myDataBase != null)
myDataBase.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
}
MainActivity.java:
package com.sunnah.sunnahapp;
import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
//DB PART
import com.sunnah.sunnahapp.R;
import com.sunnah.sunnahapp.R.layout;
import com.sunnah.sunnahapp.DatabaseHelper1;
import android.app.Activity;
import android.app.ListActivity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
//DB PART END
public class MainActivity extends AppCompatActivity {
private WebView webView;
private SQLiteDatabase database;
//private static final String DB_NAME = "bukhari.sqlite";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView);
webView.setWebViewClient(new MainActivity.myWebClient());
// Database Part START
//Our key helper
DatabaseHelper1 dbOpenHelper; //= new DatabaseHelper1();
dbOpenHelper = new DatabaseHelper1(this);
try {
dbOpenHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
//database = dbOpenHelper.openDataBase();
//That’s it, the database is open!
//Database Part END
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/www/index.html");
}
public class myWebClient extends WebViewClient
{
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
@Override
// This method is used to detect back button
public void onBackPressed() {
if(webView.canGoBack()) {
webView.goBack();
} else {
// Let the system handle the back button
super.onBackPressed();
}
}
}
能否請您指導我在這裏。我嘗試改變實際存在的路徑(即目錄結構)。 我錯過了什麼? 如何在給定路徑中不存在的情況下創建一個空的數據庫。我認爲它會在這種情況下創建,如DatabaseHelper1類的註釋所述。
添加'<使用權限android:name =「android.permission.WRITE_EXTERNAL_STORAGE」/>' –
'/ data/data/sunnahapp/databases /'。然後卸載舊的應用程序並再次運行 –
@IntelliJAmiya,錯誤。 謝謝你的迴應。 –