0

圧縮された sqlite データベース ダンプ ファイルをフェッチし、そのデータベースを使用するアプリケーションがあります。データベースを取得する方法のガイドとして、このチュートリアルを使用しました。ただし、私の目的のために、代わりにローカルホスト (192.168.1.4) でホストされているデータベースをプルしました。

上記のリンクには、参照用にダウンロードした完全なプロジェクトも含まれていますが、AsyncTask を使用してデータベースをフェッチするようにコードを微調整する必要がありました。そうしないと、NetworkOnMainThreadException が発生します。AsyncTask を適切に機能させることができました。私の AsyncTask は次のようになります。

private class Connection extends AsyncTask {
    @Override
    protected Object doInBackground(Object... arg0) {
        //connect();
        myDroidSQLDatabase = new MyDroidSQLDatabase(MyDBAppActivity.this);
        myDroidSQLDatabase.open();

        return null;
    }

}

そして、それは私の主な活動で次のように呼び出されます:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    new Connection().execute();

}

そして、問題は onResume() にあるようです。これは、logcat がアクティビティを再開できないというエラーを示しているためです。

@Override
protected void onResume() {
    myDroidSQLDatabase.open();
    super.onResume();
}

デバイスに最初にアプリケーションをインストールしたときに onResume() がトリガーされた理由はよくわかりません。問題は、onCreate()、onResume() が呼び出された後、データベースがまだ開いているため、既に開いているデータベースを開こうとしていると思います。

ただし、Web サイトの元の例では、パッケージ化されたダンプ ファイルがアプリケーションにデプロイされ、適切に実行されます。このメソッドは db fetch を必要とせず、AsyncTask で実行したため、onResume は機能しませんでした。したがって、今の私の推測では、 onResume() で問題が発生しないように、 AsyncTask が終了するのを待つ必要があります。

申し訳ありませんが、スレッドと非同期タスクはまったく初めてなので、ジョブが完了したときにスレッドを処理する方法がわかりません。問題は、onResume が (アクティビティ ライフ サイクルの一部として) 実行を試み、Async タスクがまだ完了していないため、open() 呼び出しが動作することだと思います。

何か案は?

また、ここにさらに 3 つのクラスがあります。MyDroidSQLデータベース

public class MyDroidSQLDatabase {
    private SQLiteOpenHelper sqlLiteOpenHelper;
    private SQLiteDatabase sqlLiteDatabase;

    public MyDroidSQLDatabase(Context context) {
        sqlLiteOpenHelper = new MyDroidSQLiteOpenHelper(context);       
    }

    public void open() {
        sqlLiteDatabase = sqlLiteOpenHelper.getWritableDatabase();
    }

    public void close() {
        sqlLiteDatabase.close();
    }

    public SQLiteDatabase getSqlLiteDatabase() {
        return sqlLiteDatabase;
    }
}

MyDroidSQLiteOpenHelper

public class MyDroidSQLiteOpenHelper extends SQLiteOpenHelper {
    private Context context;
    private static final String __DB_NAME = "mydbapp.db";
    private static final int __DB_VERSION = 1;

    public MyDroidSQLiteOpenHelper(Context context) {
        super(context, __DB_NAME, null, __DB_VERSION);
        this.context=context;
    }

    @Override
    public void onCreate(SQLiteDatabase sqlLiteDb) {
        try {
            //SQLiteDBDeploy.deploy(sqlLiteDb, this.context, "northwind.zip");

            // if you like to download file from remote site comment above line and uncomment below line.
            SQLiteDBDeploy.deploy(sqlLiteDb,
                    //"http://ingenious-camel.googlecode.com/svn/trunk/SQLiteDBDeployer/assets/northwind.zip");         
                    "http://192.168.1.4/dbtest/android.zip");
        } catch (IOException e) {
            Log.e(MyDBAppActivity.TAG,e.getMessage(),e);
            throw new Error(e.getMessage());
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqlLiteDb, int oldVersion, int newVersion) {

    }
}

SQLiteDBDeploy

public class SQLiteDBDeploy {
    private static final String TAG = "SQLiteDBDeploy";
    private static List<String> ignoreSQLs;

    static {
        ignoreSQLs = new LinkedList<String>();
        ignoreSQLs.add("--");
        ignoreSQLs.add("begin transaction;");
        ignoreSQLs.add("commit;");
        ignoreSQLs.add("create table android_metadata (locale text);");
        ignoreSQLs.add("create table \"android_metadata\" (locale text);");
        ignoreSQLs.add("insert into android_metadata values('en_us');");
        ignoreSQLs.add("insert into \"android_metadata\" values('en_us');");
    }

    /**
     * Deploys given zip file in SQLiteDatabase
     * 
     * @param sqlLiteDb
     *            the database
     * @param context
     *            to use to open or create the database
     * @param dbName
     *            dump zip file
     * @throws IOException
     */
    public static void deploy(SQLiteDatabase sqlLiteDb, Context context, String dbName) throws IOException {
        Log.i(TAG, "reading zip file: " + dbName);
        InputStream dbStream = context.getAssets().open(dbName);

        deploy(sqlLiteDb, dbStream);

        dbStream.close();
    }

    /**
     * Deploys given zip file url in SQLiteDatabase
     * 
     * @param sqlLiteDb
     *            the database
     * @param dbUrl
     *            dump zip file url
     * @throws IOException
     */
    public static void deploy(SQLiteDatabase sqlLiteDb, String dbUrl) throws IOException {
        Log.i(TAG, "reading url: " + dbUrl);

        HttpURLConnection c = (HttpURLConnection) new URL(dbUrl).openConnection();
        c.setRequestMethod("GET");
        c.setDoOutput(true);
        c.connect();
        InputStream dbStream = c.getInputStream();

        deploy(sqlLiteDb, dbStream);

        dbStream.close();
        c.disconnect();
    }

    /**
     * Deploys given dump  file stream in SQLiteDatabase
     * 
     * @param sqlLiteDb the database
     * @param dbStream stream to read dump data 
     * @throws IOException
     */
    private static void deploy(SQLiteDatabase sqlLiteDb, InputStream dbStream) throws IOException {
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(dbStream));
        ZipEntry entry = null;
        while ((entry = zis.getNextEntry()) != null) {
            Log.i(TAG, "deploying zip entry: " + entry);
            InputStreamReader dbReader = new InputStreamReader(zis);
            deploy(sqlLiteDb, dbReader);
        }
    }

    /**
     * Deploys given stream in SQLiteDatabase
     * 
     * @param sqlLiteDb
     *            the database
     * @param dbReader
     *            stream to read dump SQL statements
     * @throws IOException
     * @throws SQLException
     */
    private static void deploy(SQLiteDatabase sqlLiteDb, InputStreamReader dbReader) throws IOException {
        String sqlLine = null;
        StringBuffer sqlBuffer = new StringBuffer();
        BufferedReader bufferedReader = new BufferedReader(dbReader);

        sqlLiteDb.beginTransaction();
        try {
            while ((sqlLine = bufferedReader.readLine()) != null) {
                String sql = sqlLine.trim();
                if (!isIgnoreSQL(sql)) {
                    if (sql.endsWith(";")) {
                        sqlBuffer.append(sql);
                        String execSQL = sqlBuffer.toString();
                        Log.d(TAG, "running sql=>" + execSQL);
                        sqlLiteDb.execSQL(execSQL);
                        sqlBuffer.delete(0, sqlBuffer.length());
                    } else {
                        if (sqlBuffer.length() > 0) {
                            sqlBuffer.append(' ');
                        }
                        sqlBuffer.append(sql);
                    }
                }
            }
            sqlLiteDb.setTransactionSuccessful();
        } finally {
            sqlLiteDb.endTransaction();
        }
    }

    /**
     * Returns true if the given SQL statement is to be ignored
     * @param sql SQL statement
     * @return
     */
    private static boolean isIgnoreSQL(String sql) {
        if (sql.length() == 0) {
            return true;
        }

        String lowerSQL = sql.toLowerCase();
        for (String ignoreSQL : ignoreSQLs) {
            if (lowerSQL.startsWith(ignoreSQL)) {
                return true;
            }
        }
        return false;
    }
}
4

1 に答える 1

1

デバイスに最初にアプリケーションをインストールしたときに onResume() がトリガーされた理由はよくわかりません。

このメソッドは、 が一時停止されたときだけでなく、 が最初に作成されonResume()たときに常に呼び出されます。アクティビティのライフサイクルを見るActivityActivity

問題は、onCreate()、onResume() が呼び出された後、データベースがまだ開いているため、既に開いているデータベースを開こうとしていると思います。

いいえ、それは問題ではありません。への複数の呼び出しgetWriteableDatabase()が許可されます。

エラーが発生する最も可能性の高い理由は、AsyncTask doInBackground(...)メソッドが完了していないことです。これがポイントです。AsyncTaskこれは非同期であり、メソッド内の への呼び出しはexecute()すぐonCreate(...)に返されます。onPostExecute(...)のメソッドを利用する必要がありますAsyncTask

于 2013-08-18T01:04:19.773 に答える