0

アプリで DB SQLite を使用しようとしていますが、問題が発生しています。アプリを実行しようとすると、Android が「強制終了」というアプリのクラッシュを返します。コードをチェックして、値と戻り値が問題ないかどうかを確認しました。問題はないようです。いくつかのデバッグを行い、問題は明らかに createDataBase にあります。方法。彼は DB の場所を見つける必要があります。私は変数 PATH を渡しましたが、それでもクラッシュします。タブレットで直接実行するのが正しい原因かどうかわかりません。データ/データのような別のパスを作成する必要があります。 ...(調査中に発見しましたが、わかりません)およびAVD(それが問題です)デスクトップ上のDBの場所を指定する必要がありますか?

コードを見てください:

ConnectDB

   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()。標準の Java コマンドよりも常に Android コマンドを使用してください。

于 2012-08-06T17:11:28.980 に答える