SecurityException:无法为用户0找到提供程序null;在Android 8.0上的ActiveAndroid上

时间:2017-08-28 18:37:15

标签: android securityexception activeandroid android-8.0-oreo

我有一个使用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

很抱歉,但我还没有一个孤立的例子。我会努力把事情放在一起。

提前致谢

10 个答案:

答案 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 tryyou 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)

有两个简单的步骤。

  1. 您需要在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>
    

  2. 并且您需要具有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,这对修复我的错误非常有帮助,我希望它对其他人有帮助!干杯!