用于内容的 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 示例!<provider android:name="WeatherDataProvider" android:exported="true"
谢谢,这不仅让我对这个特殊情况有了更清晰的认识,而且更普遍地了解了内容提供者和小部件之间的交互。以上是关于用于内容的 Widget RemoteViewsFactory 中的 Android 权限拒绝的主要内容,如果未能解决你的问题,请参考以下文章
Android 笔记 AutoCompleteTextView day8
无法从 CoreData 加载 5 个随机数据以用于 Widget,有啥想法可以支持吗?