我正在构建一个Chooser应用程序,该应用程序将替换本机的Android Share对话框。除我尝试通过长按图像>共享图像从Chrome共享图像外,它都可以正常工作。
我发现Google+没有捕获到异常(崩溃),因此我可以通过Logcat进行查看:
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权限,可以吗?
无论如何,如果我检查mIntent
和mPayloadIntent
上的多余字符和标志,则会得到:
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)
因此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的同一问题)正在使用什么。
答案 0 :(得分:4)
这是Chrome错误吗?一个Android错误?还是我做错了什么?
我的猜测是这是一个客户端错误,来自于直接创建ACTION_CHOOSER
Intent
对象而不是通过Intent.createChooser()
创建对象的人。 Intent.createChooser()
似乎正在从您所称的mPayloadIntent
中提取标志并将其添加到mIntent
。
您应该可以自己进行测试。创建一个剪贴簿应用,该应用创建一个ACTION_SEND
指向某个内容(例如,由Intent
投放)的EXTRA_STREAM
FileProvider
。然后,尝试通过三种方式调用选择器:
通过Intent
包裹Intent.createChooser()
通过Intent
ACTION_CHOOSER
包装Intent
,在此遵循文档中的说明,并将标记放在两个Intent
对象上
通过Intent
ACTION_CHOOSER
包装Intent
,在此跳过ACTION_CHOOSER
Intent
如果我是对的,则#1和#2可以工作,而#3将以与您看到的相同的基本故障模式失败。
如果到目前为止,我的理论仍然有效,请尝试再次运行这三个应用程序,但这一次使用系统选择器。我的猜测是,作为核心操作系统的一部分,系统选择器确实会获得一些特殊的好处,并且所有这三种都可以使用。否则,Chrome和WhatsApp的开发人员将在测试中遇到此问题并予以解决。
而且,如果所有这些理论都成立了……您一定会感到困惑。我认为使用Intent.createChooser()
的人比直接使用ACTION_CHOOSER
的人多,因为Intent.createChooser()
更简单。而且,使用ACTION_CHOOSER
的人中的一部分人可能实际上遵循了文档...
hahahahahahahahahaha ... gasp ... hahahahahahahahahahahaha!
...对于这些,您还可以。而且,某些使用ACTION_CHOOSER
的人可能在Uri
中拥有EXTRA_STREAM
,这是世界可读的(这不是一个好主意,但在这里对您有用)。仅适用于手动创建ACTION_CHOOSER
的错误客户端,无法正确设置Intent
标志,但是 do 正确保护其内容,您将无法正确处理Intent
。