やまものブログ

メモ書きブログです (^_^;A

Failed to find provider info for jp.co.se.android.chapter05

今週は、

 CHAPTER05 データベースを操作しよう
を無事に実行することができました。

CHAPTER05 は以下3つの LESSON から構成されています。
  1. LESSON 18 SQLiteデータベースを利用しよう
  2. LESSON 19 データベースを外部に公開しよう
  3. LESSON 20 公開したデータベースを利用しよう

各LESSON ごとに題材になるプロジェクトを import しますが、その手順は先週のブログの中でまとめた 【LESSON 用プロジェクトの import 前処理】 とほぼ同じです。違いは以下の2点だったので、手順の一部が不要になるだけでした。
● proguard.cfg ファイルが存在しない
● AndroidManifest.xmlandroid:minSdkVersion の定義が省略されている

CHAPTER05 の成果物は、下記2つのアプリが連携して動作することです。
● LESSON19 のアプリ chapter05
● LESSON20 のアプリ chapter0503

まず、LESSON19 (chapter05) のスクリーンショットはこちらです。
イメージ 1
各日付をクリックすると、その日付に関連付けされたテキストを入力できます。つまり、「カレンダー・メモ」と言えば説明になるようなアプリです。


次に、LESSON20 (chapter0503) がこちらです。
イメージ 2
ここでは "LESSON" という文字列を「検索」した結果を示しています。検索の対象は、chapter05 アプリで作成したカレンダー・メモ(=データベース)になります。つまり、chapter0503 は他のアプリが作成して公開したデータベースを参照します。


で、今回、ほぼまる一日ハマってしまったのが、下記のエラーです。
Failed to find provider info for jp.co.se.android.chapter05

このエラーにある "jp.co.se.android.chapter05" は、
  URI(Uniform Resource Identifier)
と呼ばれるものです。

URI は公開側と参照側の両方のアプリにおいて、予め java ソースコードの中で定義してあります。さらに、公開側については、AndroidManifest.xml の中でも定義します。

エラーはデータベースを参照する側 chapter0503 の実行時に出てきました。つまり、参照側は jp.co.se.android.chapter05 を見に行くものの、それが公開されていないという状況でした。

このエラーの対策方法は、公開側の AndroidManifest.xml にて、
10 <provider
11 android:name=".DiaryProvider"
12 android:authorities="jp.co.se.android.chapter05"
となっていた定義を、以下のように書き換えることで、公開・参照ができるようになりました。
10 <provider
11 android:name="jp.co.se.android.chapter05.DiaryProvider"
12 android:authorities="jp.co.se.android.chapter05"

name の前に追加した "jp.co.se.android.chapter05” はパッケージ名です。Google 先生のどこかで見かけた情報では、コンテンツが同じパッケージに存在する場合は name の前でパッケージ名は省略できるとあったように記憶しています。それが正しければ、修正前の記述でも動くはずなのですが、何故か修正後のフルパス定義が必要でした

なお、下記の属性もあわせて追加しました。
android:enabled="true"
android:multiprocess="true"
android:exported="true"
この属性のみでは公開できませんでしたが、これが無し公開されるかどうかは未確認です。


上記と同じくらい悩まされたのは、deprecate(推奨しない,廃止) されたメソッドの対策で、3種類ありました。それぞれのエラーメッセージは以下のとおりです。
The method stopManagingCursor(Cursor) from the type Activity is deprecated

The method managedQuery(Uri, String, String, String, String) from the type Activity is deprecated

The constructor CursorAdapter(Context, Cursor) is deprecated

まず、最初の stopManagingCursor(Cursor) は、単純にコメントアウトしました。このメソッドと対になるはずの startManagingCursor() が何故か使われていなかったので、コメントアウトでOKと判断しました。

2番目の managedQuery() はメソッドを getContentResolver().query に置き換えただけでOKでした。

最後の super(context, c)CursorAdapter のコンストラクタですが、3種類あったうちの1つが deprecate されました。残った2つのうち、3番目の引数に int があるコンストラクタに置き換えて super(context, c, 0) として逃れました。3つ目の引数が 0 でいいのかどうかは分かりませんが、とりあえず動きました。


あと、下記の警告があったのですが、無視していたら、いつの間にか消滅しました。
Avoid passing null as the view root (needed to resolve layout parameters on the inflated layout's root element)
Eclipse は相変わらず SIGSEGV で落ちるので、何かのはずみで Lint がオフになったのかもしれません。


蛇足になってしまったのですが、deprecate されたメソッドの対策として、Support Library (android-support-v7-appcompat) の導入を試みました。これは見当ハズレで、そもそも、Support Library は、Android のバージョンが古いデバイスで、新しいAndroid の機能を使うために用意されたものらしく、deprecate を回避したいというような、新しいデバイス古いAndroid コードを使うためのものではなさそうです。
# Support Library に対するこの認識が誤っていたらご指摘いただけると幸甚です

なお、Support Library の追加では、下記のような類のエラーで悩みました。
error: Error: No resource found that matches the given name: attr 'android:actionModeShareDrawable'.

これの対策は、とにかく targetSdkVersion のバージョン指定を最新にすることでした。今日の時点での最新は Android 5.0 (API 21) で、具体的には、以下2つを変更してエラーを回避できました。

AndroidManifext.xml の application タグの前に下記 uses-sdk タグを追加
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="21" />

project.properties の修正、target=android-16 を 21 に書き換え
target=android-21


データベースを公開できない問題、deprecate 対策はともに自分には大物でした。 JavaAndroid も知識が皆無な状態での暗中模索は疲れましたが、サンプルを動作させるという明確な目標をもって取組めたおかげで、いい訓練になったと思います