14

リストビュー内にアプリのローカルデータベースからの情報を表示するために使用しようとしているウィジェットがあります。

RemoteViewsService.RemoteViewsFactoryインターフェイスを使用して、リストのコンテンツをロードしています。onDataSetChangedメソッドでリストを再ロードするコードのブロックを実行した場合。アプリがクラッシュし、次のメッセージが表示されます。

11-01 16:40:39.540: E/ACRA(27175): DataDisplay fatal error : Permission Denial: reading com.datadisplay.content.ContentProviderAdapter uri content://com.datadisplay.provider.internalDB/events from pid=573, uid=10029 requires the provider be exported, or grantUriPermission()

ただし、クラスのコンストラクターで実行されるこの同じコードは問題なく機能します。もちろん、これをonDataSetChangedメソッドでも機能させて更新などを行う必要があります。

マニフェストのプロバイダーのエントリは次のとおりです。

    <provider android:name="com.datadisplay.content.ContentProviderAdapter"
        android:authorities="com.datadisplay.provider.internalDB"
        android:exported="true"
        android:enabled="true"
        android:grantUriPermissions="true">
            <grant-uri-permission android:pathPattern="/events/"/>
    </provider>

私はそれをエクスポートし、エラーメッセージリクエストのようなUri権限を付与していますが、それでも失敗します。私はこの質問を見つけました。その男は問題を抱えていましたが、最終的に彼のカスタム権限を削除し、それは機能しました。私にはそのようなカスタム権限はありませんが、それでも運がありません。

コンテンツプロバイダーを備えたウィジェット。ReadPermissionを使用することは不可能ですか?

誰かが私が本当に感謝する洞察を持っているなら、これは信じられないほどイライラしている、ハハ。

4

3 に答える 3

31

これは、RemoteViewsFactoryがリモートプロセスから呼び出されており、そのコンテキストが権限の適用に使用されているために発生しています。(リモートの呼び出し元にはプロバイダーを使用する権限がないため、SecurityExceptionがスローされます。)

これを解決するには、リモートプロセスのIDをクリアして、リモートの呼び出し元ではなくアプリに対して権限の適用がチェックされるようにします。プラットフォーム全体で見られる一般的なパターンは次のとおりです。

final long token = Binder.clearCallingIdentity();
try {
    [perform your query, etc]
} finally {
    Binder.restoreCallingIdentity(token);
}
于 2013-12-17T22:19:55.637 に答える
9

これをあなたのonDataSetChanged()方法に入れてください:

    Thread thread = new Thread() {
        public void run() {
            query();
        }
    };
    thread.start();
    try {
        thread.join();
    } catch (InterruptedException e) {
    }

query()メソッド内のデータベースからデータをフェッチします。別のスレッドでデータをフェッチすることがこの問題を回避するのに役立つ理由はわかりませんが、機能します。これはAndroidの例の1つから取得しました。

于 2012-11-02T14:47:43.837 に答える
9

これが4.2でのみ発生し、残りでは発生しない場合は、デフォルトが変更されているため、android:exported = "true"を設定する必要があります:http: //developer.android.com/about/versions/android-4.2.html

コンテンツプロバイダーはデフォルトでエクスポートされなくなりました。つまり、android:exported属性のデフォルト値は「false」になりました。他のアプリがコンテンツプロバイダーにアクセスできることが重要な場合は、android:exported="true"を明示的に設定する必要があります。

于 2013-01-09T14:16:57.417 に答える