2011-01-17 11 views
9

最近、私はHTC Desireシリーズについて多くの苦情を受けており、SQL文を呼び出す際には失敗しています。私は、以下を含むログスナップショットを持つユーザーからのレポートを受け取りました。呼び出しが開いたままにされているカーソルとして現れ、重大なランタイムエラーでデータベースの結果を開くためにので私のアプリは基本的に炎で燃焼させ、その後SqliteがHTC Desire HDで問題を解決するHD

I/Database(2348): sqlite returned: error code = 8, msg = statement aborts at 1: [pragma journal_mode = WAL;] 
E/Database(2348): sqlite3_exec to set journal_mode of /data/data/my.app.package/files/localized_db_en_uk-1.sqlite to WAL failed 

。この時点でカーソルを開こうとしているときはカーソルを置いてはいけません。

これはHTC Desire HDとZでのみ発生します。私のコードは基本的に次のことを行います(問題の領域を分けるために少し変更しました)。

SQLiteDatabase db; 
String dbName; 

public SQLiteDatabase loadDb(Context context) throws IOException{ 
    //Close any old db handle 
    if (db != null && db.isOpen()) { 
     db.close(); 
    } 
    // The name of the database to use from the bundled assets. 
    String dbAsset = "/asset_dir/"+dbName+".sqlite"; 
    InputStream myInput = context.getAssets().open(dbAsset, Context.MODE_PRIVATE); 

    // Create a file in the app's file directory since sqlite requires a path 
    // Not ideal but we will copy the file out of our bundled assets and open it 
    // it in another location. 
    FileOutputStream myOutput = context.openFileOutput(dbName, Context.MODE_PRIVATE); 

    byte[] buffer = new byte[1024]; 
    int length; 
    while ((length = myInput.read(buffer)) > 0) { 
     myOutput.write(buffer, 0, length); 
    } 

    // Close the streams 
    myOutput.flush(); 
    // Guarantee Write! 
    myOutput.getFD().sync(); 
    myOutput.close(); 
    myInput.close(); 
    // Not grab the newly written file 
    File fileObj = context.getFileStreamPath(dbName); 
    // and open the database 
    return db = SQLiteDatabase.openDatabase(fileObj.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
} 

悲しいことに、この電話は英国でのみ利用可能で、私は自分の在庫に1つもありません。私はHTC Desireシリーズからこのタイプのレポートを取得しています。私は、このコードが何の問題もなく働いていたので、何が変わったのか分かりません。私が紛失しているものはありますか?

答えて

20

短い回答:SQLiteDatabase.OPEN_READONLYを削除してみてください。

長い答え:

「WALは」先行書き込みログ、SQLiteのでは比較的新しい機能、私はそれを理解するようです。 WALのSQLiteドキュメントでは、「読み取り専用のWALデータベースを開くことはできません」と述べています。今、それは読み取り専用メディアの文脈の中にあるようですが、それはOPEN_READONLYの場合に当てはまるかもしれません。

このことができます場合は、それがあることを前提として、私は、多少驚かれることと思います:HTCは、これら二つのデバイス

  • にご使用の環境についての特別な何かをWALを有効にWALが
  • 標準のAndroidで使用されていない

    • (例えば、バイナリデータベースが資産から抜け出している)、通常の読み取り専用データベースが正常に動作する場所で、このような問題が発生しています。これらのデバイスは、読み取り専用データベースの壊れた互換性テストに合格していません。

    しかし、私はそれが少なくともショットの価値があると思います。

    また、バイナリデータベースのパッケージ化からSQL文のパッケージ化に切り替えて、データベースをビルド/ポピュレートして実行することも考えられます。これは遅くなりますが(トランザクションを使用しない場合は非常に遅くなります)、データベースのファイル固有の問題が発生しにくくなります。

  • +0

    これはショットの価値があるように聞こえる、私は明日これを間違いなく試みるでしょう。それが動作する場合は、チェックボックスとビールを取得します。 –

    +0

    モルモットを発見し、それは働いた。ありがとう!それは同時に素晴らしいと悲しかった。 –

    +1

    @Greg: "それは働いた" ... 'SQLiteDatabase.OPEN_READONLY'を削除することを意味しますか?今後、この問題を防ぐために、私たちが終了しようとしているCompatibility Test Suiteのギャップを示していることをお知らせください。ありがとう! – CommonsWare

    0

    ここでの基本的な根本的な問題は、sqlite3データベースファイルがAndroidデバイス間で移植可能であると仮定していることです。本当じゃない。ファイル形式 - 実際にはSQLiteをデータベースエンジンとして使用する - は、ではなく、APIの一部であるです。 HTCは、sqlite3の代わりにpostgresを使用するAndroid携帯を作ることができました。それは正式に互換性があります。

    はい、アプリケーションのアセットにsqlite3 .dbファイルをバンドルし、インストール後にそのまま使用すると、データベースコンテンツをあらかじめ入力するのが一般的です。 Androidプラットフォームの同じバージョンを実行するデバイス間でさえ、動作することは保証されていません。あなたが保証できる唯一のことは、それです。同じバージョンのAndroidを同じシステムベンダーから実行している同じ物理デバイスのデバイスで、特定のバージョンのAndroidを実行しているデバイスで作成されたdbファイルは引き続き使用できます。

    (同じベンダーの同じ機種のデバイスでもない)いいえ、2つのデバイスが実際に同じシステムビルドを実際に実行しているという保証はありません。 )

    この移植可能性を実現する唯一の方法は、未加工のデータベースファイル自体を埋め込むことではなく、パブリックAPIで再生してデバイスに適したデータベースファイルを確立する汎用化された解析可能な表現です。

    +2

    ファイルフォーマットが変わる可能性があるので、あなたが言っているのは、あるコンピュータから別のコンピュータにファイルを転送しないということですか?私はそれが良い答えか真実だとは思わない。この前提をバックアップする証拠がありますか?この問題は、SDKがsqlite、sqlite 3.4.0を正確に呼び出すように見えます。http://developer.android.com/reference/android/database/sqlite/package-summary.htmlこのベンダーは実際には従いませんでしたこの。また、WALはReadOnlyデータベースで必要とされるべきではありません。なぜなら、ロックやジャーナルが発生する必要がないからです。 –

    +0

    あなたはクラスとメソッドの名前を読み、そのクラスとメソッドの_implementation_に関する契約を構成していると仮定します。残念ながら、実際にはそうではありません。私はこれがうんざりしていることに同意します。私たちは根本的な問題を穏やかで移植可能な方法で解決したいと思います。しかし、それは、この種の問題に取り組んでいる人々を助けるものではありません。 – ctate

    +0

    独自のViewクラスも実装する必要がありますか?ベンダーはライフサイクルを任意に上書きしますか?申し訳ありませんが、APIのどの部分を信頼できるはずなのか、混乱していますか?私はそれ以来問題を修正していますが、ドキュメントを読んで文書化されているように行動することを期待しているので、あなたのコメントは私に衝撃的ではありません。 –

    関連する問題