将敏感应用数据作为电子邮件附件发送时,正确的权限处理是什么?

时间:2010-11-14 20:42:57

标签: android

我无法为我的应用授予“反向权限” 希望以受控方式提供敏感数据。

我的应用程序是时间跟踪器,因为时间跟踪日志 可以被认为是个人信息,我已经创建了一个权限 用于访问它并为其分配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发生在一些完全不同的实际上 不相关的包裹让我感到困惑的是如何授予许可 应该工作。

所以最终我的问题是,鉴于日志是敏感数据, 我如何允许它作为附件通过电子邮件发送,同时尊重 用户的隐私(例如,没有制作附件世界 可读的)?

3 个答案:

答案 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)

其他应用无法访问您应用的数据。只需使用私人存储空间。您有几种选择:

  1. 将数据传输到数据库的Sava。 App数据库仅对创建它的应用程序可见。其他应用将无法看到此数据。发送电子邮件时,只需查询数据库并创建文本附件。

  2. 通过Context.openFileOutput()创建私人文件。