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

2023-12-08

我有问题,我尝试在我的消费者应用程序中实现内容提供程序:

这是我来自应用程序 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:无法启动活动 组件信息{com.erlanggakmoekasan.favoritemovies/com.erlanggakmoekasan.favoritemovies.activity.MainActivity}: java.lang.SecurityException:权限拒绝:打开提供程序 com.erlanggakmoekasan.imovie.provider.MoviesProvider 来自 进程记录{7b99e1ed0 27146:com.erlanggakmoekasan.favoritemovies/u0a307} (pid=27146, uid=10307) 需要 com.erlanggakmoekasan.imovie.READ_DATABASE 或 com.erlanggakmoekasan.imovie.WRITE_DATABASE

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

来自应用程序 B 我的问题有什么解决办法吗???


应用B需求<uses-permission>元素为com.erlanggakmoekasan.imovie.READ_DATABASE or com.erlanggakmoekasan.imovie.WRITE_DATABASE.

此外,您还需要确保:

  • 应用程序A是always在应用 B 之前安装,或者

  • 应用程序B有完全相同的 <permission>元素如 App AandApp A 和 App B 使用相同的签名密钥进行签名

自定义权限在 Android 中效果不佳。如果可能,请将这两个应用程序合并为一个应用程序。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java.lang.SecurityException:权限拒绝:实现内容提供程序时打开提供程序 的相关文章

随机推荐

  • 即使用户强制关闭服务,如何自动重新启动服务?

    我希望服务在我的应用程序中始终运行 所以我想重新启动它 即使它被用户强制关闭 肯定有办法做到这一点 就像 Facebook 等应用程序正在做的那样 这不是使用推送通知完成的 即使互联网关闭 Facebook 也会重新启动其服务 首先 它是真
  • 绘制靠近折线的线

    我有一个三角形作为折线 我想绘制一个高度 我发出命令 line or line 正确的点 但 AutoCAD 绘制从顶点到相邻顶点的线 不仅在 AutoLISP 中 AutoCAD 也不允许我在多段线中绘制从顶点到边的中间的线 我怎样才能做
  • 使用 fuzzywuzzy 在数据框中创建一列匹配结果

    我遇到了使用 FuzzyWuzzy 库将所有 结果存储在数据框列中的挑战 我猜它可能需要循环 我一整天都在摸索这个问题 现在我想看看你们谁能帮我解决问题 会超级有帮助的 作为我想做的一个例子 这里有 2 个数据框表 主表 ID ITEM 1
  • 将数据附加到 S3 对象

    假设我有一台机器 我希望能够将其写入存储在 S3 存储桶上的某个日志文件 因此 机器需要具有对该存储桶的写入能力 但是 我不希望它能够覆盖或删除该存储桶中的任何文件 包括我希望其写入的文件 所以基本上 我希望我的机器能够仅将数据附加到该日志
  • 当没有数据类型可以容纳完整数字时将十六进制转换为十进制

    我正在使用 C 语言的 PIC 微处理器 它是 16F 因此它不能保存大于 32 位的整数 无符号int32是可用的最大数据大小 我从阅读器处收到一个 5 字节的 ID 代码 为了传输它 我必须逐位编码为 BCD 我无法将其冲刺为字符串 因
  • 使用 JavaScript 检测 NPAPI 支持

    如何从 JavaScript 检测浏览器是否支持 NPAPI 并非所有人都这样做 虽然我可以依赖用户代理 但如果存在的话 我宁愿采用一种更可靠的方式来实现 不幸的是 我无法简单地检测我的插件是否已加载 因为该插件可能尚未安装在支持的浏览器上
  • Playframework - Eclipse 无法检测到新模板[重复]

    这个问题在这里已经有答案了 可能的重复 如何让Eclipse看到Play中的变化 编译模板 我正在迈出 Play 的第一步 框架和我遇到了一些问题 我可以毫无问题地创建和消除一个项目 现在 如果我添加一个新视图 例如 sometest sc
  • 登录 Azure Web 应用程序失败,并显示“AADSTS50079:用户需要使用多重身份验证”

    我们有一个 Azure Web 应用程序 它通过 Azure 多因素身份验证进行身份验证并访问 Graph API 和 Power BI 我们已经设置了 Azure 应用程序注册所需的权限 我们使用 Redis 缓存将令牌详细信息存储在 N
  • Yii 2.0 Restful Web 服务 API

    有人使用 Yii 2 0 beta 中集成的 RESTful Web 服务吗 官方的说明文档看起来很简单 但对我来说不起作用 我正在使用基本模板 使用 gii 模块创建一个简单的 类别 模型扩展ActiveRecord 然后我创建了Cate
  • Ansible:如何增加IP地址?

    我将一个变量传递给 Ansible extra vars lan 10 10 10 1 我现在需要增加这个 IP 地址 以便最后一个八位字节是 2所以它将等于10 10 10 2 在 Ansible 中如何实现这一点 从 Ansible 2
  • SQL WHERE 子句中的加号是什么意思 (WHERE + userName = SYSTEM_USER)

    我一直在试图找到 where 子句中加号的含义 有人对此有什么想法吗 被卡住了一点 查询本身非常简单 无论有或没有加号 其工作方式都类似 我想删除它 除非它的存在是有原因的 SELECT userID from tblUser WHERE
  • 如何根据嵌入数组过滤文档?

    审核后这一页 特别是这个查询 db scores find results elemMatch gte 80 lt 85 我使用了以下导入 import static com mongodb client model Filters and
  • 将重载指针传递给成员函数信号作为 QObject::connect 的参数[重复]

    这个问题在这里已经有答案了 在 Qt 中 如果信号没有过载 它可以像这样传递给 connect 方法 QObject connect comboBox QComboBox currentTextChanged gt void 但如果信号过载
  • 如何在Python中获取列表中出现频率最高的10个字符串

    我有一个包含 93 个不同字符串的列表 我需要找到 10 个最频繁出现的字符串 并且返回必须按从最频繁到最不频繁的顺序排列 mylist and beware twas all all and and and and and and and
  • 半正矢公式中的连接运算

    我正在 PHP 中实现 Haversine 公式 如下所示 result mysqli query mysqli SELECT 6371 acos cos radians lat cos radians latitude cos radia
  • 新添加的元素 $.each 和 events

    我已经阅读了很多帖子 each并新增了元素 事件附件 StackOverflow 上当前有关此主题的许多问题似乎对我不起作用 on 通常推荐 因为它允许我们附加新元素并且仍然维护单个事件侦听器 处理程序 在我当前的代码中 1 input t
  • 检测可穿戴设备何时与 Android 手机连接/断开连接

    Pebble 手表有一个 Intent 当 Pebble 连接 断开连接时会全局发送 这允许手机应用程序知道手表是否已连接 我已进行搜索 但无法找到有关 Android Wear 类似功能的信息 如何知道可穿戴设备是否已连接到手机 是否可以
  • 生成 Linkedin 访问令牌

    我一直在尝试使用简单的 REST 客户端以及 Mozilla 的 REST 插件 我正进入 状态 HTTP 1 1 401 未经授权 响应 正文中的 error unauthorized client error description 客
  • .NET,每分钟都有事件(每分钟)。计时器是最好的选择吗?

    我想使用 C 在 Windows 窗体应用程序中每分钟 按时钟 做一些事情 我只是想知道最好的方法是什么 我可以使用计时器并将其间隔设置为 60000 但要让它按分钟运行 我必须精确地按分钟启用它 这不太可行 我可以使用计时器并将其间隔设置
  • java.lang.SecurityException:权限拒绝:实现内容提供程序时打开提供程序

    我有问题 我尝试在我的消费者应用程序中实现内容提供程序 这是我来自应用程序 A 提供商 的 Android 清单