0

我正在尝试在我的应用程序中使用 DB SQLite,但遇到了麻烦。当我尝试运行应用程序时,Android 正在返回一个应用程序崩溃说“强制关闭”,我检查了代码以查看值和返回是否正常,并且似乎是,进行了一些调试,问题显然出在 createDataBase方法。他需要找到数据库的位置,我已经传入了一个变量 PATH,即使它仍然崩溃,不知道直接在平板电脑上运行是否是正确的原因我需要创建一个不同的路径,如数据/数据。 ...(发现正在研究,不确定)和 AVD(这就是问题所在)我需要指定数据库在我的桌面上的位置?

看一下代码:

连接数据库

   package com.victor.profile;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.app.Dialog;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import com.victor.profile.MainActivity;

public class ConnectDB extends SQLiteOpenHelper{

    //The Android's default system path of your application database.
    private static String DB_PATH = "C:/Users/Victor/Dropbox/workspace/Profile/database";

    private static String DB_NAME = "profile_db";

    private SQLiteDatabase myDataBase; 

    private final Context myContext;

    Dialog dialog;

    boolean  dbalert;

    /**
     * Constructor
     * Takes and keeps a reference of the passed context in order to access to the application assets and resources.
     * @param context
     */
    public ConnectDB(Context context) {

        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }   

  /**
     * Creates a empty database on the system and rewrites it with your own database.
     * */
    public void createDataBase() throws IOException{

        boolean dbExist = checkDataBase();

        if(dbExist){
            //do nothing - database already exist
        }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();

            try {

                copyDataBase();

            } 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){

            dbalert = new MainActivity().dbFail();

        }

        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_READWRITE);

    }

    @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.

主要活动

    package com.victor.profile;

import java.io.IOException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    public void onDestroy(){
        System.exit(0);
    }

    public void RegisterActivity(View view) throws IOException{

        Intent intent = new Intent (this, RegisterActivity.class);
        ConnectDB dbcreator = new ConnectDB(this);
        dbcreator.createDataBase();
        startActivity(intent);  
    }



    public boolean dbFail(){
        AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
        alertDialog.setTitle("Closing App");
        alertDialog.setMessage("Unable to find Database...");
        alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int which) {
              onDestroy();
           }
        });
        alertDialog.show();
        return true;
    }

}

这是 logcat 错误

08-06 17:44:09.915: I/Database(283): sqlite returned: error code = 14, msg = cannot open file at source line 25467
*08-06 17:44:09.915: E/Database(283): sqlite3_open_v2("profile_db", &handle, 1, NULL) failed*
08-06 17:44:09.925: D/AndroidRuntime(283): Shutting down VM
08-06 17:44:09.925: W/dalvikvm(283): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
*08-06 17:44:09.946: E/AndroidRuntime(283): FATAL EXCEPTION: main
08-06 17:44:09.946: E/AndroidRuntime(283): java.lang.IllegalStateException: Could not execute method of the activity
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.view.View$1.onClick(View.java:2072)
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.view.View.performClick(View.java:2408)
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.view.View$PerformClick.run(View.java:8816)
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.os.Handler.handleCallback(Handler.java:587)
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.os.Handler.dispatchMessage(Handler.java:92)
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.os.Looper.loop(Looper.java:123)
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.app.ActivityThread.main(ActivityThread.java:4627)
08-06 17:44:09.946: E/AndroidRuntime(283):  at java.lang.reflect.Method.invokeNative(Native Method)
08-06 17:44:09.946: E/AndroidRuntime(283):  at java.lang.reflect.Method.invoke(Method.java:521)
08-06 17:44:09.946: E/AndroidRuntime(283):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
08-06 17:44:09.946: E/AndroidRuntime(283):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
08-06 17:44:09.946: E/AndroidRuntime(283):  at dalvik.system.NativeStart.main(Native Method)
08-06 17:44:09.946: E/AndroidRuntime(283): Caused by: java.lang.reflect.InvocationTargetException
08-06 17:44:09.946: E/AndroidRuntime(283):  at com.victor.profile.MainActivity.RegisterActivity(MainActivity.java:36)
08-06 17:44:09.946: E/AndroidRuntime(283):  at java.lang.reflect.Method.invokeNative(Native Method)
08-06 17:44:09.946: E/AndroidRuntime(283):  at java.lang.reflect.Method.invoke(Method.java:521)
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.view.View$1.onClick(View.java:2067)
08-06 17:44:09.946: E/AndroidRuntime(283):  ... 11 more
08-06 17:44:09.946: E/AndroidRuntime(283): Caused by: java.lang.IllegalStateException: System services not available to Activities before onCreate()
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.app.Activity.getSystemService(Activity.java:3526)
08-06 17:44:09.946: E/AndroidRuntime(283):  at com.android.internal.app.AlertController$AlertParams.<init>(AlertController.java:743)
08-06 17:44:09.946: E/AndroidRuntime(283):  at android.app.AlertDialog$Builder.<init>(AlertDialog.java:273)
08-06 17:44:09.946: E/AndroidRuntime(283):  at com.victor.profile.MainActivity.dbFail(MainActivity.java:43)
08-06 17:44:09.946: E/AndroidRuntime(283):  at com.victor.profile.ConnectDB.checkDataBase(ConnectDB.java:83)
08-06 17:44:09.946: E/AndroidRuntime(283):  at com.victor.profile.ConnectDB.createDataBase(ConnectDB.java:47)
08-06 17:44:09.946: E/AndroidRuntime(283):  ... 15 more
08-06 17:44:09.965: W/ActivityManager(58):   Force finishing activity com.victor.profile/.MainActivity
08-06 17:44:10.315: I/ARMAssembler(58): generated scanline__00000077:03515104_00000000_00000000 [ 33 ipp] (47 ins) at [0x342d00:0x342dbc] in 385721 ns
08-06 17:44:10.525: W/ActivityManager(58): Activity pause timeout for HistoryRecord{44fee218 com.victor.profile/.MainActivity}
08-06 17:44:20.796: W/ActivityManager(58): Activity destroy timeout for HistoryRecord{44fee218 com.victor.profile/.MainActivity}*
4

1 回答 1

2

您不能像这样在模拟器中定义硬盘驱动器的路径:

private static String DB_PATH = "C:/Users/Victor/Dropbox/workspace/Profile/database";

模拟器创建了一个尽可能模仿真实设备的环境。它有自己的文件结构,您的方法不正确。而是使用它来创建数据库:

checkDB = SQLiteDatabase.openDatabase(DB_NAME, null, SQLiteDatabase.OPEN_READONLY);

如果您想在模拟器中访问您的数据库,请阅读以下内容:Android 模拟器在哪里存储 SQLite 数据库?

新的 LogCat

当您调用new ConnectDB(this)SQLiteOpenHelper 类时,会为您创建数据库。您不需要您的方法 createDataBase()。

当你像这样使用 getReadableDatabase() 时:

try {
    SQLiteDatabase database = mDbHelper.getReadableDatabase();
}
catch(SQLiteException exception) {
    // Database didn't open, exit app gracefully
}

那么你也不需要你的 checkDataBase() 方法,这两个过程都已经由 SQLite 完成了。

最后,您不需要在 onDestory() 中退出您的应用程序。试图关闭正在关闭的应用程序是多余的。此外,如果您想关闭应用程序,请使用 Android 方法finish()。始终使用 Android 命令而不是标准 Java 命令。

于 2012-08-06T17:11:28.980 回答