用于内容的 Widget RemoteViewsFactory 中的 Android 权限拒绝

Posted

技术标签:

【中文标题】用于内容的 Widget RemoteViewsFactory 中的 Android 权限拒绝【英文标题】:Android Permission denial in Widget RemoteViewsFactory for Content 【发布时间】:2012-10-22 15:25:56 【问题描述】:

我有一个小部件,我试图用它在列表视图中显示来自应用程序本地数据库的信息。

我正在使用 RemoteViewsService.RemoteViewsFactory 接口来加载列表的内容。如果我运行在 onDataSetChanged 方法中重新加载列表的代码块。应用程序崩溃并显示以下消息:

11-01 16:40:39.540: E/ACRA(27175): DataDisplay fatal error : Permission Denial: reading com.datadisplay.content.ContentProviderAdapter uri content://com.datadisplay.provider.internalDB/events from pid=573, uid=10029 requires the provider be exported, or grantUriPermission()

但是,在类的构造函数中运行的相同代码可以正常工作。当然,我还需要在 onDataSetChanged 方法中使用它来进行更新和填充。

这是我的供应商在清单中的条目:

    <provider android:name="com.datadisplay.content.ContentProviderAdapter"
        android:authorities="com.datadisplay.provider.internalDB"
        android:exported="true"
        android:enabled="true"
        android:grantUriPermissions="true">
            <grant-uri-permission android:pathPattern="/events/"/>
    </provider>

我同时导出它并授予 Uri 权限,如错误消息请求,但它仍然失败。我发现了这个问题,这家伙遇到了问题,但最终删除了他的自定义权限并且它起作用了。我没有任何这样的自定义权限,但仍然没有运气:

Widget with content provider; impossible to use ReadPermission?

如果有人有见识,我将不胜感激,这令人难以置信的沮丧,哈哈。

【问题讨论】:

【参考方案1】:

发生这种情况是因为 RemoteViewsFactory 是从远程进程调用的,并且该上下文正在用于权限强制执行。 (远程调用者没有使用你的提供者的权限,所以它会抛出一个 SecurityException。)

要解决此问题,您可以清除远程进程的身份,以便针对您的应用而不是远程调用者检查权限强制执行。以下是您可以在整个平台上找到的常见模式:

final long token = Binder.clearCallingIdentity();
try 
    [perform your query, etc]
 finally 
    Binder.restoreCallingIdentity(token);

【讨论】:

你摇滚。这帮助我解决了我的问题。 感谢您提供真正的解决方案。请注意,此方法可以使您的提供程序不被导出,因为您使用自己的身份而不是默认设置的传入 IPC 的身份。【参考方案2】:

把它放在你的onDataSetChanged() 方法中:

    Thread thread = new Thread() 
        public void run() 
            query();
        
    ;
    thread.start();
    try 
        thread.join();
     catch (InterruptedException e) 
    

query() 方法中从数据库中获取数据。我不知道为什么在单独的线程中获取数据有助于解决这个问题,但它确实有效!我是从其中一个 Android 示例中得到的。

【讨论】:

解决了这个问题。当然,另一个出现在它的位置。但至少这个问题解决了。谢谢! 之所以有效,是因为 query() 发生在不同的线程上,该线程没有当前的 Binder 远程调用上下文。请参阅下面关于如何清除当前线程上的调用者身份的答案。【参考方案3】:

如果这仅发生在 4.2 而不是其余版本,则需要设置 android:exported="true",因为默认值已更改: http://developer.android.com/about/versions/android-4.2.html

默认情况下不再导出内容提供程序。也就是说,android:exported 属性的默认值现在是“false”。如果其他应用能够访问您的内容提供程序很重要,您现在必须显式设置 android:exported="true"。

【讨论】:

+1,对于 Android 4.2,这就是解决方案!未更新的 sdk 示例! &lt;provider android:name="WeatherDataProvider" android:exported="true" 谢谢,这不仅让我对这个特殊情况有了更清晰的认识,而且更普遍地了解了内容提供者和小部件之间的交互。

以上是关于用于内容的 Widget RemoteViewsFactory 中的 Android 权限拒绝的主要内容,如果未能解决你的问题,请参考以下文章

如何刷新 Widget 数据?

UE4笔记:利用Widget设计一个切换材质功能

Android 笔记 AutoCompleteTextView day8

无法从 CoreData 加载 5 个随机数据以用于 Widget,有啥想法可以支持吗?

php EMPTY WIDGET用于在wordpress中创建单个小部件的插件代码。

WordPress边栏 - 显示所有小部件标题,然后显示所有小部件内容