SecurityException: no se pudo encontrar el proveedor nulo para el usuario 0; en ActiveAndroid en Android 8.0
android-8.0-oreo (9)
Tengo una aplicación que utiliza ActiveAndroid y ha funcionado bien. Sin embargo; ahora, cuando intento guardar un modelo en la base de datos, obtengo una excepción SecurityException.
La pila es:
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]
Alguien más ha experimentado esto? ¿Necesitamos especificar el proveedor de contenido en el AndroidManifest.xml ?
Lo siento pero todavía no tengo un ejemplo aislado de esto. Voy a trabajar para poner algo juntos.
Gracias por adelantado
Aparentemente, Android O requiere el uso de un ContentProvider personalizado para el uso de la base de datos, incluso si no tiene intención de compartir sus datos con otras aplicaciones.
https://developer.android.com/about/versions/oreo/android-8.0-changes.html
Su clase personalizada debe definirse en una etiqueta de proveedor dentro de su etiqueta de aplicación en AndroidManifest.xml. Si corresponde, configure export = false para proteger sus datos del uso externo.
<provider android:name=".MyContentProvider"
android:exported="false"
android:authorities="com.your_app_path.MyContentProvider"/>
Para mí, el problema surgió porque estaba llamando a NotifyChange desde contentResolver. Terminé no necesitando esto, así que pude evitar la implementación de un ContentProvider.
Como lo indican los cambios de seguridad de @GeigerGeek en Android 26 y superiores, es necesario que especifique el proveedor de contenido en su manifiesto.
Para ActiveAndroid puede agregar lo siguiente a su Manifiesto y cambiar el nombre de su paquete.
<provider
android:name="com.activeandroid.content.ContentProvider"
android:authorities="<your.package.name>"
android:enabled="true"
android:exported="false">
</provider>
Si usa sabores en su proceso de construcción, puede usar a continuación:
android:authorities="${applicationId}"
El uso de ${applicationId}
ayudará en la estructura del proyecto basada en el sabor, donde el paquete de aplicación puede ser diferente para cada sabor.
Para más soluciones o información, esto fue tomado de aquí.
Edite Manifest y agregue este nodo de etiqueta de proveedor en el nodo de aplicación lateral.
<application ....>
<provider android:name="com.activeandroid.content.ContentProvider"
android:exported="false"
android:enabled="true"
android:authorities="here will be package name of your app"/>
.....
</application>
Yo uso esto y solucioné mi error. Haga clic aquí para la demostración .
Fui redirigido a esta pregunta cuando estaba buscando el mismo problema. Sin embargo, esta pregunta específica se refiere a una implementación de biblioteca específica. Para superar este error debido a los https://developer.android.com/about/versions/oreo/android-8.0-changes.html#ccn que se introdujeron recientemente en Android O, debemos proporcionar la autorización específica a ContentProvider
agregando lo siguiente en el archivo AndroidManifest.xml
bajo la etiqueta de la application
.
<provider
android:name=".DatabaseContentProvider"
android:authorities="com.yourpackage.name"
android:exported="false" />
Y necesita tener una clase ContentProvider
como la siguiente.
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;
}
}
Hay dos pasos simples.
Debe tener el proveedor especificado en su
AndroidManifest.xml
bajo su etiqueta deapplication
como la siguiente.<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>
Y necesita tener la clase java que especifica el proveedor indicado en el manifiesto. En mi caso, tenía el archivo del proveedor en el paquete
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; } }
Eso es. Tú eres bueno para irte.
Aquí hay un código de trabajo completo para la operación de lectura / escritura / actualización de SQLite en Github. ¡Espero que ayude!
Sé que ya existe una buena respuesta, pero no entiendo la mejor manera de corregir este error y leer esta publicación. Solución Excepto SecurityException que requiere un ContentProvider válido en Android 8 , es muy útil para solucionar mi error, espero que sea útil para otros, Saludos !!!
Tal vez debido a que tu uri es nulo cuando utilizas notifyChange, https://developer.android.com/about/versions/oreo/android-8.0-changes.html#ccn
Android O agregará cheque para el proveedor:
311 .checkContentProviderAccess(uri.getAuthority(), userHandle);
312 if (msg != null) {
313 if (targetSdkVersion >= Build.VERSION_CODES.O) {
314 throw new **SecurityException**(msg);
315 } else {
Tuve exactamente el mismo problema con Android activo en Android O. Resulta que uno de los métodos en mi ContentProvider personalizado devolvió un Uri
, algunas veces devolvería el valor nulo y esto causaba el problema. Así que agregué la anotación @Nullable
al método como se muestra a continuación, que solucionó el problema.
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {..}
Para hotfix , configura tu
compileSdkVersion 25
targetSDKVersion 25
e ignorarás las características de Android O. ¡Te salvará el día!
importante para hot fix:
Pero esta solución será inválida.
Agosto de 2018: se requieren nuevas aplicaciones para alcanzar el nivel de API 26 (Android 8.0) o superior. Noviembre de 2018: se requieren actualizaciones de las aplicaciones existentes para alcanzar el nivel de API 26 o superior. A partir de 2019: cada año avanzará el requisito de targetSdkVersion. Dentro de un año después de cada lanzamiento de Android, las aplicaciones nuevas y las actualizaciones de las aplicaciones deberán apuntar al nivel de API correspondiente o superior.
Otra forma , puedes arreglarlo con ActiveAndroid pero ahora está obsoleto. Puedes probar o puedes probar ReActiveAndroid
con ActiveAndroid , visite https://github.com/pardom/ActiveAndroid/issues/536#issuecomment-344470558
Cuando el proyecto haya definido clases de modelo en el código fuente de Java a través de la aplicación del método de configuración addModelClasses, aún se bloqueará porque las clases de modelo no se cargarán a través de esa configuración. En esa situación, necesita mover la definición del modelo al archivo 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();
}}
Si está haciendo algo con FileProvider, no deje de cambiar el nombre del paquete
Uri contentUri = FileProvider.getUriForFile(mContext,
"your package name", new File(mImageFilePath));