我无法为我的应用授予“反向权限” 希望以受控方式提供敏感数据。
我的应用程序是时间跟踪器,因为时间跟踪日志 可以被认为是个人信息,我已经创建了一个权限 用于访问它并为其分配android.permission- group.PERSONAL_INFO权限组。
要从手机导出时间日志,我正在添加发送功能 日志作为电子邮件附件。附件由a生成 受我新添加的权限保护的内容提供商。我的 发送电子邮件的代码如下所示:
String email = "someone@example.com";
Uri uri = TimeLog.CSVAttachment.CONTENT_URI;
Intent i = new Intent(Intent.ACTION_SEND, uri);
i.setType("text/csv");
i.putExtra(Intent.EXTRA_EMAIL, new String[]{email});
i.putExtra(Intent.EXTRA_SUBJECT, "Time log");
i.putExtra(Intent.EXTRA_TEXT, "Hello World!");
i.putExtra(Intent.EXTRA_STREAM, uri);
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(i);
在我的HTC手机上运行时,我会在Gmail之间进行弹出式选择 和HTC邮件。选择Gmail,我在Gmail应用中遇到了这个例外:
ERROR/AndroidRuntime(8169): Caused by: java.lang.SecurityException:
Permission Denial: reading com.mycompany.timelog.TimeLog uri
content://com.mycompany.timelog/csv_attachment from pid=8169,
uid=10035 requires com.mycompany.timelog.permission.READ_TIME_LOG
我确实在我的提供商处设置了android:grantUriPermissions="true"
但是
这没有帮助。我有一个关于为什么会这样的理论。我有
预期FLAG_GRANT_READ_URI_PERMISSION授予Gmail权利
访问我的内容提供商,但我认为真正发生的是
此权限授予
com.android.internal.app.ResolverActivity因为有多个
Intent和Android的一个匹配为。创建一个包装器活动
向用户显示选择。
所以,我尝试将其硬编码到我的应用程序中仅用于测试:
grantUriPermission("com.google.android.gm", uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
这允许Gmail正确显示电子邮件,我可以按 “发送”。不幸的是,在GMail关闭后,我得到了这个例外 com.google.process.gapps:
ERROR / AndroidRuntime(7617):java.lang.SecurityException:Permission
拒绝:阅读com.mycompany.timelog.TimeLog uri
内容://com.mycompany.timelog/csv_attachment from pid = 7617,
uid = 10011需要com.mycompany.timelog.permission.READ_TIME_LOG
请注意,这来自不同的PID和UID。这是因为 对openAssetFile的实际调用是从某个同步提供程序发生的 属于不同包的组件 (com.google.android.googleapps?)。
虽然我有一些希望最终找到授予权限的方法
我的ACTION_SEND
意图的最终接收者,呼叫的事实
openAssetFile发生在一些完全不同的实际上
不相关的包裹让我感到困惑的是如何授予许可
应该工作。
所以最终我的问题是,鉴于日志是敏感数据, 我如何允许它作为附件通过电子邮件发送,同时尊重 用户的隐私(例如,没有制作附件世界 可读的)?
答案 0 :(得分:4)
亲爱的人们,
似乎谷歌本身以另一种方式解决了这个问题,我在试图解决同样的问题时偶然发现了这个问题。
如果您查看方法com.android.contacts.detail.ContactLoaderFragment
中找到的private Uri getPreAuthorizedUri(Uri uri)
:
mContext.getContentResolver().call(
ContactsContract.AUTHORITY_URI,
ContactsContract.Authorization.AUTHORIZATION_METHOD,
null,
uriBundle);
哪个解析为com.android.providers.contacts.ContactsProvider2
,其中类似的call
方法将uri添加到mPreAuthorizedUris
- 方法中使用的地图query/update/...
。
该调用的返回值放在Intent中,然后使用。
答案 1 :(得分:1)
这是一个很好的方法,不幸的是,你看到你可能会在框架中遇到一些阻止你这样做的问题。目前存在一些授予uri权限的问题,这些权限使得该功能没有应有的功能(其中许多将在Gingerbread中得到解决),而且在Gmail之上似乎并不期望这种情况发生并处理保留只要需要,就可以获得授权。
这些数据有多大?如果它不是太大,那么如何将它作为字符串直接包含在Intent中呢?
答案 2 :(得分:0)
其他应用无法访问您应用的数据。只需使用私人存储空间。您有几种选择:
将数据传输到数据库的Sava。 App数据库仅对创建它的应用程序可见。其他应用将无法看到此数据。发送电子邮件时,只需查询数据库并创建文本附件。
通过Context.openFileOutput()
创建私人文件。