繁体   English   中英

java.lang.SecurityException:权限拒绝:实现内容提供者时打开提供者

[英]java.lang.SecurityException: Permission Denial: opening provider when implement content provider

我遇到了问题,我尝试在消费者应用中实施内容提供商:

这是我从App A(提供商)获得的Android清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.erlanggakmoekasan.imovie">
    <permission android:name="com.erlanggakmoekasan.imovie.READ_DATABASE" android:protectionLevel="normal" />
    <permission android:name="com.erlanggakmoekasan.imovie.WRITE_DATABASE" android:protectionLevel="normal" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true">
        <receiver android:name=".widgets.MoviesWidget">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/movies_widget_info" />
        </receiver>

        <activity android:name=".activity.TvShowActivitySearch" />
        <activity android:name=".activity.MovieActivitySearch" />
        <activity android:name=".activity.TvShowActivity" />
        <activity
            android:name=".activity.MainActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".activity.MovieActivity">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".activity.MainActivity" />
        </activity>
        <provider
            android:authorities="com.erlanggakmoekasan.imovie"
            android:name=".provider.MoviesProvider"
            android:exported="true"
            android:readPermission="com.erlanggakmoekasan.imovie.READ_DATABASE"
            android:writePermission="com.erlanggakmoekasan.imovie.WRITE_DATABASE" />
        <service
            android:name="com.erlanggakmoekasan.imovie.widgets.StackWidgetService"
            android:permission="android.permission.BIND_REMOTEVIEWS" />

    </application>

</manifest>

这是我从App B(消费者)获得的Android清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.erlanggakmoekasan.favoritemovies">

    <uses-permission android:name="android.permission.INTERNET"/>
    <permission android:name="com.erlanggakmoekasan.imovie.READ_DATABASE" />
    <permission android:name="com.erlanggakmoekasan.imovie.WRITE_DATABASE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".activity.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

我从应用程序A获得的提供商:

package com.erlanggakmoekasan.imovie.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.erlanggakmoekasan.imovie.utils.MoviesHelper;

import static com.erlanggakmoekasan.imovie.utils.MoviesContract.AUTHORITY;
import static com.erlanggakmoekasan.imovie.utils.MoviesContract.MoviesColumns.CONTENT_URI;
import static com.erlanggakmoekasan.imovie.utils.MoviesContract.MoviesColumns.TABLE_NAME;

public class MoviesProvider extends ContentProvider {
    private static final int MOVIES = 1;
    private static final int MOVIES_ID = 2;
    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static {

        // content://com.erlanggastudio.imovie/movies
        sUriMatcher.addURI(AUTHORITY, TABLE_NAME, MOVIES);

        // content://com.erlanggastudio.imovie/movies/id
        sUriMatcher.addURI(AUTHORITY,
                TABLE_NAME+ "/#",
                MOVIES_ID);
    }
    private MoviesHelper moviesHelper;

    @Override
    public boolean onCreate() {
        moviesHelper = MoviesHelper.getInstance(getContext());
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@Nullable Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        moviesHelper.open();
        Cursor cursor;
        switch (sUriMatcher.match(uri)) {
            case MOVIES:
                cursor = moviesHelper.queryProvider();
                break;
            case MOVIES_ID:
                cursor = moviesHelper.queryByIdProvider(uri.getLastPathSegment());
                break;
            default:
                cursor = null;
                break;
        }
        if (cursor!=null){

            cursor.setNotificationUri(getContext().getContentResolver(),uri);
        }
        return cursor;
    }

    @Nullable
    @Override
    public String getType(@Nullable Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@Nullable Uri uri, @Nullable ContentValues values) {
        moviesHelper.open();
        long added ;

        switch (sUriMatcher.match(uri)){
            case MOVIES:
                added = moviesHelper.insertProvider(values);
                break;
            default:
                added = 0;
                break;
        }

        if (added > 0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return Uri.parse(CONTENT_URI + "/" + added);
    }

    @Nullable
    public int delete(@Nullable Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        moviesHelper.open();
        int deleted;
        switch (sUriMatcher.match(uri)) {
            case MOVIES_ID:
                deleted =  moviesHelper.deleteProvider(uri.getLastPathSegment());
                break;
            default:
                deleted = 0;
                break;
        }

        if (deleted > 0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return deleted;
    }

    @Nullable
    public int update(@Nullable Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        moviesHelper.open();
        int movieUpdated ;
        switch (sUriMatcher.match(uri)) {
            case MOVIES_ID:
                movieUpdated =  moviesHelper.updateProvider(uri.getLastPathSegment(),values);
                break;
            default:
                movieUpdated = 0;
                break;
        }

        if (movieUpdated > 0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        return movieUpdated;
    }
}

我在App B中的主要活动:

package com.erlanggakmoekasan.favoritemovies.activity;

import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;

import com.erlanggakmoekasan.favoritemovies.R;
import com.erlanggakmoekasan.favoritemovies.adapter.MoviesAdapter;
import com.erlanggakmoekasan.favoritemovies.callback.MoviesCallback;
import com.erlanggakmoekasan.favoritemovies.model.Movie;

import java.lang.ref.WeakReference;
import java.util.ArrayList;

import static com.erlanggakmoekasan.favoritemovies.entity.MappingHelper.mapCursorToArrayList;
import static com.erlanggakmoekasan.favoritemovies.utils.MoviesContract.MoviesColumns.CONTENT_URI;

public class MainActivity extends AppCompatActivity implements MoviesCallback {

    private DataObserver myObserver;
    private RecyclerView moviesList;
    private MoviesAdapter moviesAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        moviesList = findViewById(R.id.movie_list);
        moviesAdapter = new MoviesAdapter(this);
        moviesList.setLayoutManager(new LinearLayoutManager(this));
        moviesList.setHasFixedSize(true);
        moviesList.setAdapter(moviesAdapter);
        HandlerThread handlerThread = new HandlerThread("DataObserver");
        handlerThread.start();
        Handler handler = new Handler(handlerThread.getLooper());
        myObserver = new DataObserver(handler, this);
        getContentResolver().registerContentObserver(CONTENT_URI, true, myObserver);
        new getData(this, this).execute();

    }

    @Override
    public void postExecute(Cursor movie) {

        ArrayList<Movie> listMovie = mapCursorToArrayList(movie);
        if (listMovie.size() > 0) {
            moviesAdapter.setListMovies(listMovie);
        } else {
            Toast.makeText(this, "Tidak Ada data saat ini", Toast.LENGTH_SHORT).show();
            moviesAdapter.setListMovies(new ArrayList<Movie>());
        }
    }


    private static class getData extends AsyncTask<Void, Void, Cursor> {
        private final WeakReference<Context> weakContext;
        private final WeakReference<MoviesCallback> weakCallback;


        private getData(Context context, MoviesCallback callback) {
            weakContext = new WeakReference<>(context);
            weakCallback = new WeakReference<>(callback);
        }

        @Override
        protected Cursor doInBackground(Void... voids) {
            return weakContext.get().getContentResolver().query(CONTENT_URI, null, null, null, null);
        }

        @Override
        protected void onPostExecute(Cursor data) {
            super.onPostExecute(data);
            weakCallback.get().postExecute(data);
        }

    }

    static class DataObserver extends ContentObserver {

        final Context context;

        DataObserver(Handler handler, Context context) {
            super(handler);
            this.context = context;
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            new getData(context, (MainActivity) context).execute();
        }
    }
}

错误是:

进程:com.erlanggakmoekasan.favoritemovies,PID:27146 java.lang.RuntimeException:无法启动活动ComponentInfo {com.erlanggakmoekasan.favoritemovies / com.erlanggakmoekasan.favoritemovies.activity.MainActivity}:java.lang.SecurityException:权限被拒绝:正在打开ProcessRecord {7b99e1ed0 27146:com.erlanggakmoekasan.favoritemovies / u0a307}(pid = 27146,uid = 10307)的提供者com.erlanggakmoekasan.imovie.provider.MoviesProvider需要com.erlanggakmoekasan.imovieka.READ_DATABASE或com.erlanggakmoe。

尝试调用getContentResolver().registerContentObserver(CONTENT_URI, true, myObserver);

来自应用B的任何解决我问题的方法???

App B需要com.erlanggakmoekasan.imovie.READ_DATABASEcom.erlanggakmoekasan.imovie.WRITE_DATABASE <uses-permission>元素。

另外,您需要确保:

  • App A 始终安装在App B之前,或者

  • App B具有 App A 相同的 <permission>元素, 并且 App A和App B均由相同的签名密钥签名

自定义权限在Android中无法很好地运行。 如果可能,请将这两个应用程序合并为一个应用程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM