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でコンテンツプロバイダーを指定する必要がありますか?
申し訳ありませんが、私はまだこれの孤立した例を持っていません。何かをまとめる作業をします。
前もって感謝します
@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}
を使用すると、フレーバーごとにアプリケーションパッケージが異なるフレーバーベースのプロジェクト構造で役立ちます。
より多くのソリューションまたは情報については、これが採用されました ここから
ホットフィックスの場合、
compileSdkVersion 25
targetSDKVersion 25
あなたはAndroid O機能を無視します。それはあなたの一日を節約します!
ホットフィックスにとって重要:
しかし、この解決策は無効になります。
2018年8月:APIレベル26(Android 8.0)以上を対象とする新しいアプリが必要です。 2018年11月:APIレベル26以上を対象とするために必要な既存のアプリの更新。 2019年以降:毎年targetSdkVersion要件が前進します。各Androidデザートリリース後1年以内に、新しいアプリとアプリの更新は、対応する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));
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の実装を避けることができました。
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 {
同じ問題を探していたときに、この質問にリダイレクトされました。ただし、この特定の質問は、特定のライブラリの実装に関するものです。 Android Oで新たに導入された changes によるこのエラーを克服するには、特定の権限を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;
}
}
2つの簡単な手順があります。
次のように、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;
}
}
それでおしまい。準備できた。
これは完全な作業コードです GithubでのSQLiteの読み取り/書き込み/更新操作の場合。お役に立てば幸いです!
パッケージがapplicationIdと異なる場合は、applicationIdを使用する必要があります
<provider
Android:name="com.activeandroid.content.ContentProvider"
Android:authorities="${applicationId}"
Android:exported="false" />