AssetsからSQLiteをdatabaseとしてimportする

その中でも、Arrows端末だと落ちてしまう件に関する考察。

とりあえず、databaseをAssetsからコピーしてくるというのに関しては以下の通り。
http://y-anz-m.blogspot.jp/2011/01/android-sqline-database.html

普通に行うのであれば、yanzmさんのコードをそのまま活用すれば、Nexusシリーズや、
海外制端末や、XperiaだとかKyoceraだとかの端末だと大丈夫。
(ここで挙げてるのは手持ちで確認した端末)

ただ特定の端末(Arrows端末)だと落ちる。
大抵SQLite no such tableだとか、あと何だったかIOExpectionだとかで落ちる。

上記記事のコメント欄でも、同じようなコメントが散見されるが、
Assetsからアプリ内のDatabase領域に保存するのはまだ分かるが、
Databaseでエラーを吐くからFiles領域にしてしまおうというのは少しどうなんだろ……と思う。
下手にContentProviderとかを関連させると、予期せぬ挙動をしそうで怖い。

ちなみに、私の扱うデータは12MBとかになるので、zipで圧縮しているが、それも以下を参考。
http://d.hatena.ne.jp/itog/20091228/1262016898

最終的にあれこれした後、下記の通りに解決した。
ただ、これを行ってから後ErrorがGoogleDeveloperセンターに届けられなくなったってだけなので、
実際もしかすると、自分のアプリケーションがあまりに落ちるからArrowsシリーズ持ちの方がアンインストールした可能性もあるが……。

public class DBHelperHoge extends SQLiteOpenHelper {
	private static String DB_ZIP_NAME = "TEST.zip";
        private static int DB_VERSION;
        static String SQLstring = null;
        private static Context mContext = null;
    
    private final File mDatabasePath;
    
        
        //データベースを作成またはオープン
        public DBHelperHoge(Context context, String name, CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
        mDatabasePath = mContext.getDatabasePath(name);
        DB_VERSION = version;
    }


    /** 
     * asset に格納したデータベースをコピーするための空のデータベースを作成する 
     */  
    public void createEmptyDataBase() throws IOException {
            
        boolean dbExist = checkDataBaseExists();  
  
        if (dbExist) {  
            // 既にDBが存在

        } else {  

            // 空のデータベースをデフォルトシステムパスに作成
            SQLiteDatabase db_Read = this.getReadableDatabase();
            db_Read.close();

            try {
                    unzipCopyDataBaseFromAsset();
                String dbPath = mDatabasePath.getAbsolutePath();  
                SQLiteDatabase checkDb = null;  
                try {  
                    checkDb = SQLiteDatabase.openDatabase(dbPath, null,SQLiteDatabase.OPEN_READWRITE);  
                } catch (SQLiteException e) {  
                }  
  
                if (checkDb != null) {  
                    checkDb.setVersion(DB_VERSION);  
                    checkDb.close();  
                }  
  
            } catch (IOException e) {  
                throw new Error("Error copying database");  
            }  
        }  
    }   
    

    /** 
     * 再コピーを防止するために、すでにデータベースがあるかどうか判定する 
     *  
     * @return 存在している場合 {@code true} 
     */  
        private boolean checkDataBaseExists() {
                
                
                String dbPath = mDatabasePath.getAbsolutePath();  
                  
        SQLiteDatabase checkDb = null;  
        try {  
            checkDb = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY);  
        } catch (SQLiteException e) {
                
            // データベースはまだ存在していない  
        }  
  
        if (checkDb == null) {  
            // データベースはまだ存在していない  
            return false;  
        }  
  
        int oldVersion = checkDb.getVersion();  
        int newVersion = DB_VERSION;  
        if (oldVersion == newVersion) {  
            // データベースは存在していて最新
            checkDb.close();  
            return true;  
        }  
        // データベースが存在していて最新ではないので削除  
        File f = new File(dbPath);  
        f.delete();  
        return false;  
    }  
  
   
    private void unzipCopyDataBaseFromAsset() throws IOException{
            try {
                    //ZIPから解答して結合;
                    AssetManager am = mContext.getResources().getAssets();
                    InputStream	is = am.open("DB_ZIP_NAME",AssetManager.ACCESS_STREAMING);
                    ZipInputStream zis        = new ZipInputStream(is);
                    ZipEntry ze        = zis.getNextEntry();
                    if (ze != null) { 
                    OutputStream mOutput = new FileOutputStream(mDatabasePath); 
                            byte[] buffer = new byte[1024];
                            int size;
                            while ((size = zis.read(buffer,0,buffer.length)) > -1) {
                                    mOutput.write(buffer, 0, size);
                            }
                            mOutput.flush();
                            mOutput.close();
                            zis.closeEntry();
                    }
                    zis.close();
            } catch (Exception e) {
            }
    }
    @Override  
    public void onCreate(SQLiteDatabase db) {  
    }  
  
    @Override  
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            
    }  
}

これを行うことで、F-10Dだったり、F-05DからF-08Eだったかな?
からのエラー報告が出なくなったので、恐らくこれが答えではないかと。たぶん。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です