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
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.
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));
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.
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 {
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;
}
}
Es gibt zwei einfache Schritte.
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>
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!
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" />