我有一个使用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 中指定 Content Provider ?
很抱歉,但我还没有一个孤立的例子。我会努力把事情放在一起。
提前致谢
答案 0 :(得分:42)
正如@GeigerGeek所指出的,Android 26及更高版本的安全性更改要求您在清单中指定内容提供程序。
对于ActiveAndroid,您可以将以下内容添加到您的清单中并更改您的包名称。
<provider
android:name="com.activeandroid.content.ContentProvider"
android:authorities="<your.package.name>"
android:enabled="true"
android:exported="false">
</provider>
如果在构建过程中使用flavor,则可以使用以下代码:
android:authorities="${applicationId}"
使用${applicationId}
将有助于基于风格的项目结构,其中应用程序包可能因每种风格而异。
有关更多解决方案或信息,请执行from here.
答案 1 :(得分:5)
要进行热修复,请设置
compileSdkVersion 25
targetSDKVersion 25
你将忽略android O功能。它会节省你的一天!
对于热修复很重要:
但是这个解决方案无效。
2018年8月:针对API级别26(Android 8.0)或更高级别所需的新应用程序。 2018年11月:针对API级别26或更高级别所需的现有应用程序的更新。 2019年起:每年targetSdkVersion要求将提前。在每个Android甜点发布后的一年内,新的应用和应用更新需要针对相应的API级别或更高级别。
另一种方式,您可以使用ActiveAndroid进行修复,但现在已弃用。 You can try或you can try ReActiveAndroid
使用ActiveAndroid,请访问https://github.com/pardom/ActiveAndroid/issues/536#issuecomment-344470558
当项目通过addModelClasses配置方法在java源代码中定义了模型类时,应用程序仍将崩溃,因为模型类不会通过该配置加载。在这种情况下,您需要将模型定义移动到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));
答案 2 :(得分: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"/>
对我来说问题出现了,因为我从contentResolver调用notifyChange。我最终不需要这个,所以我能够避免实现ContentProvider。
答案 3 :(得分:0)
也许是因为当你使用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 {
答案 4 :(得分:0)
当我在寻找同样的问题时,我被重定向到这个问题。但是,此特定问题涉及特定库实现。为了克服由于Android O中新引入的changes导致的此错误,我们必须通过在{{1}下的ContentProvider
文件中添加以下内容来为AndroidManifest.xml
提供特定权限标签。
application
你需要有一个<provider
android:name=".DatabaseContentProvider"
android:authorities="com.yourpackage.name"
android:exported="false" />
类,如下所示。
ContentProvider
答案 5 :(得分:0)
有两个简单的步骤。
您需要在AndroidManifest.xml
标签下的application
中指定提供者,如下所示。
<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;
}
}
就是这样。你已准备好出发。
Here is a complete working code用于Github中的SQLite读/写/更新操作。希望有帮助!
答案 6 :(得分:0)
如果您的软件包与applicationId不同,则应使用applicationId
<provider
android:name="com.activeandroid.content.ContentProvider"
android:authorities="${applicationId}"
android:exported="false" />
答案 7 :(得分:-1)
我在Android O上遇到与活动android完全相同的问题。原来我的自定义ContentProvider中的一个方法返回了Uri
,有时会返回null,这导致了问题。所以我将@Nullable
注释添加到方法中,如下所示修复了问题。
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {..}
答案 8 :(得分:-1)
编辑清单并在侧应用程序节点中添加此提供程序标记节点。
<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>
我使用它并修复了我的错误。 Click here for demo
答案 9 :(得分:-1)
我知道已经有很好的答案了,但是我不知道如何以最佳方式修复此错误并阅读this post Fixing SecurityException requiring a valid ContentProvider on Android 8,这对修复我的错误非常有帮助,我希望它对其他人有帮助!干杯!