web-dev-qa-db-de.com

SecurityException: Anbieter-Null für Benutzer 0 konnte nicht gefunden werden; auf ActiveAndroid auf Android 8.0

Ich habe eine App, die ActiveAndroid verwendet und sie funktioniert einwandfrei. Jedoch; Wenn ich jetzt versuche, ein Modell in der Datenbank zu speichern, erhalte ich eine SecurityException. 

Der Stapel ist:

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]

Hat das noch jemand erlebt? Müssen wir den Content Provider in der AndroidManifest.xml angeben? 

Sorry, aber ich habe noch kein isoliertes Beispiel dafür. Ich werde daran arbeiten, etwas zusammenzustellen.

Danke im Voraus

21
rindress

Wie durch @GeigerGeek Sicherheitsänderungen auf Android 26 und höher hervorgehoben, müssen Sie den Inhaltsanbieter in Ihrem Manifest angeben. 

Für ActiveAndroid können Sie die folgenden Angaben zu Ihrem Manifest hinzufügen und den Paketnamen ändern.

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

Wenn Sie für Ihren Buildprozess Flavors verwenden, können Sie stattdessen Folgendes verwenden:

Android:authorities="${applicationId}"

Die Verwendung von ${applicationId} hilft in einer auf Aromen basierenden Projektstruktur, in der sich das Anwendungspaket für jede Sorte unterscheiden kann.

Für weitere Lösungen oder Informationen wurde hier genommen.

39
velval

Legen Sie für Hotfix Ihr fest

compileSdkVersion 25
targetSDKVersion 25

und Sie werden Android O-Funktionen ignorieren. Es wird deinen Tag retten! 

wichtig für Hotfix:

Diese Lösung ist jedoch ungültig.

August 2018: Neue Apps für API-Level 26 (Android 8.0) oder höher erforderlich. November 2018: Aktualisierungen vorhandener Apps für API-Level 26 oder höher erforderlich . Innerhalb eines Jahres nach jeder Android-Dessertversion müssen neue Apps und App-Updates auf die entsprechende API-Stufe oder höher ausgerichtet sein.

Eine andere Möglichkeit, die Sie mit ActiveAndroid beheben können, ist aber jetzt veraltet. Du kannst versuchen oder Du kannst ReActiveAndroid versuchen

mit ActiveAndroid, Besuch https://github.com/pardom/ActiveAndroid/issues/536#issuecomment-344470558

Wenn das Projekt Modellklassen im Java-Quellcode über die Konfigurationsmethode addModelClasses definiert hat, stürzt die Anwendung weiterhin ab, da Modellklassen nicht durch diese Konfiguration geladen werden. In dieser Situation müssen Sie die Modelldefinition in die Datei AndroidManifest.xml verschieben.

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();
 }}

Wenn Sie mit FileProvider etwas unternehmen, sollten Sie den Paketnamen nicht verpassen

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

Android O erfordert anscheinend die Verwendung eines benutzerdefinierten ContentProviders für die Datenbanknutzung, auch wenn Sie Ihre Daten nicht mit anderen Anwendungen teilen möchten.

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

Ihre benutzerdefinierte Klasse muss in einem Provider-Tag innerhalb Ihres Anwendungstags in AndroidManifest.xml definiert sein. Setzen Sie ggf. exported = false, um Ihre Daten vor externer Verwendung zu schützen.

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

Für mich ergab sich das Problem, weil ich notifyChange vom contentResolver aus aufgerufen habe. Am Ende brauchte ich das nicht, also konnte ich die Implementierung eines ContentProviders vermeiden.

3
GeigerGeek

Möglicherweise ist Ihr Uri null, wenn Sie notifyChange verwenden, https://developer.Android.com/about/versions/oreo/Android-8.0-changes.html#ccn

Android O fügt einen Check für Provider hinzu:

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

Ich wurde zu dieser Frage weitergeleitet, als ich nach demselben Problem suchte. Diese spezielle Frage bezieht sich jedoch auf eine spezifische Bibliotheksimplementierung. Um diesen Fehler aufgrund der Änderungen zu beseitigen, die in Android O neu eingeführt wurden, müssen Sie der ContentProvider die spezifische Berechtigung zuweisen, indem Sie Folgendes in die AndroidManifest.xml-Datei unter application hinzufügen.

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

Und Sie müssen eine ContentProvider-Klasse wie die folgende haben. 

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

Es gibt zwei einfache Schritte.

  1. Sie müssen den Provider in Ihrem AndroidManifest.xml Unter Ihrem application -Tag wie folgt angeben.

    <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. Und Sie benötigen die Java Klasse, die den im Manifest angegebenen Provider angibt. In meinem Fall hatte ich die Provider-Datei im Paket 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;
        }
    }
    

Das ist es. Du bist startklar.

Hier ist ein vollständiger Arbeitscode für SQLite-Lese-/Schreib-/Aktualisierungsvorgänge in Github. Ich hoffe, das hilft!

0
Reaz Murshed

wenn sich Ihr Paket von Ihrer applicationId unterscheidet, sollten Sie die applicationId verwenden

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