web-dev-qa-db-ja.com

SecurityException:ユーザー0のプロバイダーnullの検索に失敗しました。 ActiveAndroid on Android 8.0

ActiveAndroidを使用しているアプリがあり、正常に動作しています。しかしながら;モデルをデータベースに保存しようとすると、SecurityExceptionが発生します。

スタックは次のとおりです。

Error saving model Java.lang.SecurityException: Failed to find provider null for user 0; expected to find a valid ContentProvider for this authority 
at Android.os.Parcel.readException(Parcel.Java:1942) 
at Android.os.Parcel.readException(Parcel.Java:1888) 
at Android.content.IContentService$Stub$Proxy.notifyChange(IContentService.Java:801) 
at Android.content.ContentResolver.notifyChange(ContentResolver.Java:2046) 
at Android.content.ContentResolver.notifyChange(ContentResolver.Java:1997) 
at Android.content.ContentResolver.notifyChange(ContentResolver.Java:1967) 
at com.activeandroid.Model.save(Model.Java:162)
[.... local stack removed]

他の誰かがこれを経験しましたか? AndroidManifest.xmlコンテンツプロバイダーを指定する必要がありますか?

申し訳ありませんが、私はまだこれの孤立した例を持っていません。何かをまとめる作業をします。

前もって感謝します

27
rindress

@GeigerGeekが指摘したように、Android 26以降のセキュリティの変更では、マニフェストでコンテンツプロバイダーを指定する必要があります。

ActiveAndroidの場合、以下をマニフェストに追加して、パッケージ名を変更できます。

<provider
  Android:name="com.activeandroid.content.ContentProvider"
  Android:authorities="<your.package.name>"
  Android:enabled="true"
  Android:exported="false">
</provider>

ビルドプロセスでフレーバーを使用する場合は、代わりに以下を使用できます。

Android:authorities="${applicationId}"

${applicationId}を使用すると、フレーバーごとにアプリケーションパッケージが異なるフレーバーベースのプロジェクト構造で役立ちます。

より多くのソリューションまたは情報については、これが採用されました ここから

45
velval

ホットフィックスの場合、

compileSdkVersion 25
targetSDKVersion 25

あなたはAndroid O機能を無視します。それはあなたの一日を節約します!

ホットフィックスにとって重要:

しかし、この解決策は無効になります。

2018年8月:APIレベル26(Android 8.0)以上を対象とする新しいアプリが必要です。 2018年11月:APIレベル26以上を対象とするために必要な既存のアプリの更新。 2019年以降:毎年targetSdkVersion要件が前進します。各Androidデザートリリース後1年以内に、新しいアプリとアプリの更新は、対応するAPIレベル以上をターゲットにする必要があります。

別の方法ActiveAndroid で修正できますが、現在は非推奨です。 試すことができます または ReActiveAndroidを試すことができます

ActiveAndroidで、 https://github.com/pardom/ActiveAndroid/issues/536#issuecomment-344470558 にアクセスします

プロジェクトがJava addModelClasses構成メソッドアプリケーションを介してソースコードが定義されている場合、モデルクラスがその構成を介してロードされないため、アプリケーションコードは引き続きクラッシュします。その場合、モデル定義をAndroidManifestに移動する必要があります.xmlファイル。

AndroidManifest.xml

<provider
    Android:name=".content.DatabaseContentProvider"
    Android:authorities="your package name"
    Android:exported="false" />

DatabaseContentProvider.Java

...
import com.activeandroid.content.ContentProvider;
...

public class DatabaseContentProvider extends ContentProvider {

@Override
protected Configuration getConfiguration() {
    Configuration.Builder builder = new Configuration.Builder(getContext());
    builder.addModelClass(SomeModel.class);
    builder.addModelClass(OtherModel.class);
    return builder.create();
 }}

FileProviderで何かをしている場合、パッケージ名の変更をお見逃しなく

 Uri contentUri = FileProvider.getUriForFile(mContext,
            "your package name", new File(mImageFilePath));
5
Ahmet Cengiz

Android Oでは、データを他のアプリケーションと共有するつもりがない場合でも、データベースの使用にはカスタムContentProviderを使用する必要があるようです。

https://developer.Android.com/about/versions/oreo/Android-8.0-changes.html

カスタムクラスは、AndroidManifest.xmlのアプリケーションタグ内のプロバイダータグで定義する必要があります。必要に応じて、exported = falseを設定して、外部使用からデータを保護します。

<provider Android:name=".MyContentProvider"
    Android:exported="false"
    Android:authorities="com.your_app_path.MyContentProvider"/>

ContentResolverからnotifyChangeを呼び出していたため、私にとって問題が発生しました。私はこれを必要としなくなったので、ContentProviderの実装を避けることができました。

3
GeigerGeek

NotifyChangeを使用する場合、uriがnullであるためか、 https://developer.Android.com/about/versions/oreo/Android-8.0-changes.html#ccn

Android Oはプロバイダーのチェックを追加します:

311 .checkContentProviderAccess(uri.getAuthority(), userHandle);
312 if (msg != null) {
313 if (targetSdkVersion >= Build.VERSION_CODES.O) {
314 throw new **SecurityException**(msg);
315 } else {
0
Willow

同じ問題を探していたときに、この質問にリダイレクトされました。ただし、この特定の質問は、特定のライブラリの実装に関するものです。 Android Oで新たに導入された changes によるこのエラーを克服するには、特定の権限をContentProviderに追加してAndroidManifest.xmlapplicationタグの下のファイル。

<provider
    Android:name=".DatabaseContentProvider"
    Android:authorities="com.yourpackage.name"
    Android:exported="false" /> 

そして、次のようなContentProviderクラスが必要です。

public class DatabaseContentProvider extends ContentProvider {

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri,
                        @Nullable String[] projection,
                        @Nullable String selection,
                        @Nullable String[] selectionArgs,
                        @Nullable String sortOrder) {
        return null;
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values,
                      @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }
}
0
Reaz Murshed

2つの簡単な手順があります。

  1. 次のように、applicationタグの下のAndroidManifest.xmlでプロバイダーを指定する必要があります。

    <uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />
    
    <application
        Android:allowBackup="true"
        Android:icon="@mipmap/ic_launcher"
        Android:label="@string/app_name"
        Android:roundIcon="@mipmap/ic_launcher_round"
        Android:theme="@style/AppTheme">
        <activity
            Android:name=".activity.MainActivity"
            Android:label="@string/app_name"
            Android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action Android:name="Android.intent.action.MAIN" />
    
                <category Android:name="Android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    
        <provider
            Android:name=".util.DatabaseContentProvider"
            Android:authorities="com.your.application.package.name"
            Android:exported="false" />
    </application>
    
  2. また、マニフェストに記載されているプロバイダーを指定するJavaクラスが必要です。私の場合、utilパッケージにプロバイダーファイルがありました。

    package com.your.application.package.name.util;
    
    import Android.content.ContentProvider;
    import Android.content.ContentValues;
    import Android.database.Cursor;
    import Android.net.Uri;
    import Android.support.annotation.NonNull;
    import Android.support.annotation.Nullable;
    
    public class DatabaseContentProvider extends ContentProvider {
    
        @Nullable
        @Override
        public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
            return null;
        }
    
        @Nullable
        @Override
        public Cursor query(@NonNull Uri uri,
                        @Nullable String[] projection,
                        @Nullable String selection,
                        @Nullable String[] selectionArgs,
                        @Nullable String sortOrder) {
            return null;
        }
    
        @Override
        public boolean onCreate() {
            return true;
        }
    
        @Override
        public int update(@NonNull Uri uri, @Nullable ContentValues values,
                      @Nullable String selection, @Nullable String[] selectionArgs) {
            return 0;
        }
    
        @Override
        public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
            return 0;
        }
    
        @Nullable
        @Override
        public String getType(@NonNull Uri uri) {
            return null;
        }
    }
    

それでおしまい。準備できた。

これは完全な作業コードです GithubでのSQLiteの読み取り/書き込み/更新操作の場合。お役に立てば幸いです!

0
Reaz Murshed

パッケージがapplicationIdと異なる場合は、applicationIdを使用する必要があります

<provider
            Android:name="com.activeandroid.content.ContentProvider"
            Android:authorities="${applicationId}"
            Android:exported="false" />
0
Iman Marashi