SecurityException: Не удалось найти нулевой провайдер для пользователя 0; на ActiveAndroid на 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]
Кто-нибудь еще испытал это? Нужно ли указывать Content Provider в AndroidManifest.xml?
Извините, но у меня пока нет отдельного примера. Я буду работать над тем, чтобы что-то собрать.
Заранее спасибо
Ответы
Ответ 1
Как указано в @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}
поможет в структуре проекта, основанной на ароматах, где пакет приложения может быть различным для каждого варианта.
Для большего количества решений или информации это было взято отсюда.
Ответ 2
Для исправления установите ваш
compileSdkVersion 25
targetSDKVersion 25
и вы будете игнорировать особенности Android. Это спасет ваш день!
важно для оперативного исправления:
Но это решение будет недействительным.
Август 2018 года. Требуются новые приложения для определения уровня API 26 (Android 8.0) или выше. Ноябрь 2018 г.: обновление существующих приложений требуется для целевого уровня API 26 или выше. 2019 года: каждый год будет увеличиваться требование targetSdkVersion. В течение одного года после каждого выпуска Android-десерта новые приложения и обновления приложений должны будут ориентироваться на соответствующий уровень 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));
Ответ 3
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"/>
Для меня проблема возникла из-за того, что я вызывал notifyChange из contentResolver. Я не нуждался в этом, поэтому мне удалось избежать реализации ContentProvider.
Ответ 4
Возможно, из-за вашего uri null, когда вы используете notifyChange,
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 {
Ответ 5
Я был перенаправлен на этот вопрос, когда искал ту же проблему. Однако этот конкретный вопрос относится к конкретной реализации библиотеки. Чтобы преодолеть эту ошибку из-за изменений, недавно представленных в Android O, мы должны предоставить определенные полномочия ContentProvider
, добавив следующее в файл AndroidManifest.xml
под тегом application
.
<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;
}
}
Ответ 6
Есть два простых шага.
-
Вам необходимо указать провайдера в вашем AndroidManifest.xml
под тегом 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>
-
И вам нужно иметь класс 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;
}
}
Это. Тебе хорошо идти.
Вот полный рабочий код для операции чтения/записи/обновления SQLite в Github. Надеюсь, это поможет!
Ответ 7
если ваш пакет отличается от applicationId, вам следует использовать applicationId
<provider
android:name="com.activeandroid.content.ContentProvider"
android:authorities="${applicationId}"
android:exported="false" />
Ответ 8
У меня была такая же проблема с активным Android на Android O. Оказывается, что один из методов в моем пользовательском ContentProvider возвратил Uri
, иногда он возвращает null, и это вызывало проблему. Поэтому я добавил аннотацию @Nullable
к методу, как показано ниже, в котором исправлена проблема.
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {..}
Ответ 9
Измените манифест и добавьте тег провайдера node в боковое приложение node.
<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>
Я использую это, и он исправил мою ошибку.
Нажмите здесь для демонстрации.
Ответ 10
я знаю, что уже есть хороший ответ, но я не понимаю, как лучше всего исправить эту ошибку, и прочитал эту статью. Исправление SecurityException, требующего действительный ContentProvider на Android 8, очень полезно исправить мою ошибку, надеюсь, это полезно для других, ура !!!