自定义选择器活动:SecurityException UID n无权访问content:// uri

时间:2018-07-04 19:31:15

标签: android android-intent android-intent-chooser

我正在构建一个Chooser应用程序,该应用程序将替换本机的Android Share对话框。除我尝试通过长按图像>共享图像从Chrome共享图像外,它都可以正常工作。

我发现Google+没有捕获到异常(崩溃),因此我可以通过Logcat进行查看:

  • 在Google上进行图片搜索。
  • 选择一张图片(这应该显示预览)
  • 长按图片
  • 选择“共享图片”
  • 弹出我的选择器活动
  • 选择Google +
  • Google+因以下错误而崩溃:
  

java.lang.SecurityException:UID 10130没有对content://com.android.chrome.FileProvider/images/screenshot/15307295588677864462883877407218.jpg [user 0]的权限

我的代码(简体):

@Override
public void onCreate() {
    handleIntent();
}

private void handleIntent() {

    // Get intent and payload
    mIntent = getIntent();
    mPayloadIntent = (Intent) mIntent.getParcelableExtra(Intent.EXTRA_INTENT);

    // Nullify some things for queryIntentActivities (or no results will be found)
    mPayloadIntent.setComponent(null);
    mPayloadIntent.setPackage(null);

    // Retrieve a list of targets we can send mPayloadIntent to..
    List<ResolveInfo> targets = context.getPackageManager().queryIntentActivities(mPayloadIntent, 0);
    // etc...

}

private void onClickTarget(ResolveInfo target) {

    // Prepare..
    ComponentName compName = new ComponentName(
                target.activityInfo.applicationInfo.packageName,
                target.activityInfo.name);

    // Build a 'new' shareIntent
    Intent shareIntent = new Intent(mPayloadIntent);
    shareIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
    shareIntent.setComponent(compName);

    // Start the targeted activity with the shareIntent
    startActivity(shareIntent);
    finish();

}

AndroidManifest.xml:

<activity
    android:name=".ActShareReplace"
    android:label="Sharedr"
    android:theme="@style/AppTheme.TransparentActivity"
    >
    <intent-filter>
        <action android:name="android.intent.action.CHOOSER" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

如果我查看Intent.ACTION_CHOOSER的文档,它会显示:

  

如果需要通过选择器授予URI权限,除了内部的EXTRA_INTENT之外,还必须指定要在ACTION_CHOOSER Intent上授予的权限。这意味着使用setClipData(ClipData)来指定要授予的URI以及相应的FLAG_GRANT_READ_URI_PERMISSION和/或FLAG_GRANT_WRITE_URI_PERMISSION。

我不确定这是我的应用程序必须执行的操作,还是调用选择器活动的应用程序的责任-但我认为是后者。我的应用无法为其接收的意图设置URI权限,可以吗?

无论如何,如果我检查mIntentmPayloadIntent上的多余字符和标志,则会得到:

mIntent仅具有附加功能,没有标志(据我所知):

  

android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER   IntentSender {4fa3901:android.os.BinderProxy@3aec3a6}(android.content.IntentSender)

     

android.intent.extra.INTENT   意图{act = android.intent.action.SEND typ = image / jpeg flg = 0x80001 clip = {image / jpeg U:content://com.android.chrome.FileProvider/images/screenshot/15307316967108618905905323381238187.jpg}(有其他功能) )}(android.content.Intent)

     

android.intent.extra.TITLE   通过(java.lang.String)共享

mPayloadIntent:

  

android.intent.extra.STREAM   content://com.android.chrome.FileProvider/images/screenshot/1530731945132897653908815339041.jpg(android.net.Uri $ HierarchicalUri)

  • FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
  • FLAG_ACTIVITY_NEW_DOCUMENT
  • FLAG_GRANT_READ_URI_PERMISSION

因此mPayloadIntent 没有FLAG_GRANT_READ_URI_PERMISSION,但是mIntent 没有。根据文档,应该如此。

我已经了解到我的应用有可能消耗了URI权限,所以I tried caching the file myself,但是当我尝试通过ContentResolver访问URI时,我会收到一个-您猜到了-权限错误。

然后,我意识到我可能不必缓存文件,因为Android的本机Chooser Activity似乎也没有这样做。这就是我现在所在的位置。回到第一广场。

这是Chrome错误吗?一个Android错误?还是我做错了什么?

我很乐意归咎于Chrome并提交错误报告,但是从事类似项目(并遇到相同问题)的某人告诉我,Whatsapp也存在类似问题。它还通过content:// uri共享图像。

出于完整性考虑,我正在使用Android 8.1的Pixel 2016进行测试。我不知道另一个人(遇到WA的同一问题)正在使用什么。

1 个答案:

答案 0 :(得分:4)

  

这是Chrome错误吗?一个Android错误?还是我做错了什么?

我的猜测是这是一个客户端错误,来自于直接创建ACTION_CHOOSER Intent对象而不是通过Intent.createChooser()创建对象的人。 Intent.createChooser()似乎正在从您所称的mPayloadIntent中提取标志并将其添加到mIntent

您应该可以自己进行测试。创建一个剪贴簿应用,该应用创建一个ACTION_SEND指向某个内容(例如,由Intent投放)的EXTRA_STREAM FileProvider。然后,尝试通过三种方式调用选择器:

  1. 通过Intent包裹Intent.createChooser()

  2. 通过Intent ACTION_CHOOSER包装Intent,在此遵循文档中的说明,并将标记放在两个Intent对象上

    < / li>
  3. 通过Intent ACTION_CHOOSER包装Intent,在此跳过ACTION_CHOOSER Intent

  4. 上的标志>

如果我是对的,则#1和#2可以工作,而#3将以与您看到的相同的基本故障模式失败。

如果到目前为止,我的理论仍然有效,请尝试再次运行这三个应用程序,但这一次使用系统选择器。我的猜测是,作为核心操作系统的一部分,系统选择器确实会获得一些特殊的好处,并且所有这三种都可以使用。否则,Chrome和WhatsApp的开发人员将在测试中遇到此问题并予以解决。

而且,如果所有这些理论都成立了……您一定会感到困惑。我认为使用Intent.createChooser()的人比直接使用ACTION_CHOOSER的人多,因为Intent.createChooser()更简单。而且,使用ACTION_CHOOSER的人中的一部分人可能实际上遵循了文档...

haha​​hahahahahahahaha ... gasp ... haha​​hahahahahahahahahaha!

...对于这些,您还可以。而且,某些使用ACTION_CHOOSER的人可能在Uri中拥有EXTRA_STREAM,这是世界可读的(这不是一个好主意,但在这里对您有用)。仅适用于手动创建ACTION_CHOOSER的错误客户端,无法正确设置Intent标志,但是 do 正确保护其内容,您将无法正确处理Intent