ContentProviderとWebView

ContentProviderは、ファイルとか何やらのやりとりが直接的にできない要素同士がやりとりできるようにするためのものです。プロセスを超えるのも可能。あと、delete, insert, query といったSQLみたいなのも可能。実装サンプルコードは http://d.hatena.ne.jp/isher/20090613/ とかが有名。

が、今回はWebViewの話。

ねらいは、ZIPファイルから画像エントリを抜き出してWebViewに渡すというもの。

WebViewは img src="content://..." といったかんじにできます。コンテントプロバイダは、delete, insert, query でなく、openFileで受けます。delete, instaer, queryはnullを返すだけのメソッドにしてしまう。openFileは ParcelFileDescriptor型のものを返します。

で ParcelFileDescriptor ってどんなもんかと http://developer.android.com/reference/android/os/ParcelFileDescriptor.html を見て愕然とする。

1.6対応にするには、 ParcelFileDescriptor.open()ぐらいしかない。これはZIPファイルから抽出したエントリをどこかに置かないといけない。

dup()とかシステムコールじゃねえかよと思うようなメソッドは1.6では対応していない。ああでも、/data/data/(app)/(キャッシュフォルダ)/(ファイル) のパスに置くキャッシュ機構もどきを作るつもりだったので、そこをopenして渡せばいいか。

アプリケーション専用のディレクトリは Context#getDir(String name, int mode) で得られます。ここで int mode となっているのは Context.MODE_PRIVATE (外部から秘匿), Context.MODE_WORLD_READABLE (外部から読み込み可) とかを指定する。今回は Context.MODE_PRIVATE にする。

実は当初は Context.MODE_WORLD_READABLE にしてました。でないと他のアプリからの content://... のアクセスを寄せ付けない、と思ったから。
で、今日試したところ、Context.MODE_PRIVATEでもOK。外部アプリからのアクセス許可は AndroidManifest.xml で制御するようです。

ContentProvider使うと、複数アプリでひとつのContentProviderが出す地図画像を見ることができると思いますが、多分需要が無い、ていうかcontent://...を受け付けるアプリあるんだろうか…?
あと、たとえばWMSもどきのパラメータを受け取りタイル画像を切り貼りしたり拡大縮小したりして返す、というのができそうなので、任意縮尺を指定できる地図アプリと連携させると面白いと思ったけれども、アプリがそもそもタイル画像対応を考えるので、多分需要無い。