在我的应用中,所有活动都受到登录保护:
每个活动都会检查其onCreate
/ onShow
- 回调用户是否已登录。如果是,则不会发生任何特殊情况。但是,如果用户未登录,则这些回调会将用户重定向到LoginActivity
并完成当前活动:
Intent loginIntent = new Intent(this, LoginActivity.class);
loginIntent.putExtra(EXTRA_ORIGINAL_INTENT, getIntent());
finish();
startActivity(loginIntent);
如上面的行所示,用于启动当前活动的原始Intent
会添加到loginIntent
的附加内容中。因此,LoginActivity
可以在成功登录后重新发送Intent
...理论上。但是,这并不总是有效。
从启动器启动时有效:
Intent with ACTION_MAIN --> MainActivity --> Redirect to LoginActivity -->
Redirect back to MainActivity after successful login
在Chrome上使用共享按钮时无效:
Intent with ACTION_SEND --> SendActivity --> Redirect to LoginActivity -->
Redirect back to SendActivity after successful login
问题是上次重定向尝试重新发送用于初始启动Intent
的原始SendActivity
:
// Resend original intent
startActivity((Intent) getIntent().getExtra(EXTRA_ORIGINAL_INTENT));
失败并出现异常:
Caused by: java.lang.SecurityException: Uid 10075 does not have permission to uri 0 @ content://com.android.chrome.FileProvider/images/screenshot/6471932623902346234.jpg
现在我的问题:
如何在不导致该权限例外的情况下重新发送Intent
?
如何传递所需的权限?
注意:我真的想要重定向行为,完成当前活动并重新发送Intent
。不能简单地将活动(MainActivity
,SendActivity
)保留在堆栈上,并由于各种原因从LoginActivity
返回它们。
答案 0 :(得分:1)
如果权限沿Intent
/ LoginActivity
链传递,则重新发送Activity
中的原始Intent
。这可以通过以下方式实现:
Intents
是原始Intent
。Intent
已明确显示。例如SomeActivity
使用用于启动LoginActivity
的{{1}}的副本重定向到Intent
:
SomeActivity
现在,成功登录后,Intent loginIntent = new Intent(getIntent()); // copy ...
loginIntent.setClass(this, LoginActivity.class); // ... explicit now
// maybe loginIntent.setAction(...) etc.
loginIntent.putExtra(EXTRA_ORIGINAL_INTENT, getIntent());
finish();
startActivity(loginIntent);
可以重定向回LoginActivity
:
SomeActivity
答案 1 :(得分:0)
一般来说,您遗失的是FLAG_GRANT_READ_URI_PERMISSION
。
当您从外线方(例如,Uri
上EXTRA_STREAM
)获得ACTION_SEND
时,您应该被授予至少阅读{{1}标识的内容的权限}。这本身就是is a bit tricky to set up。
但是,该权限授予仅适用于收到Uri
的组件(例如,您对Intent
做出响应的活动)。如果您尝试将工作委托给其他任何事件(其他活动,服务等),该组件将没有权限。
所以,你有几个选择:
一种方法是将您的身份验证/授权内容转换为可以 in situ 使用的片段或其他UI,而不是启动其他活动。这样您就可以将用户全部保存在一个位置,并且该位置具有对内容的读取权限。
另一种方法是在将用户重定向到ACTION_SEND
之前使用内容。
另一种方法是不LoginActivity
原始活动,并使用finish()
FLAG_ACTIVITY_REORDER_TO_FRONT
将原始活动的现有实例带回前台。从理论上讲,它应该仍然具有对内容的读取权限。您的问题来自于您正在销毁原始实例并创建一个新实例,并且新实例没有读取权限。
另一种方法是尝试在LoginActivity
FLAG_GRANT_READ_URI_PERMISSION
以及稍后通过LoginActivity
传递的Intent
上添加Intent
额外。我猜这是行不通的。
上述主题的变体不仅是将原始EXTRA_ORIGINAL_INTENT
放入Intent
,而且还提取其EXTRA_ORIGINAL_INTENT
以及{{1}的数据方面的内容}} Uri
:
LoginActivity
Intent
可能还需要在Intent loginIntent = new Intent(this, LoginActivity.class);
loginIntent.putExtra(EXTRA_ORIGINAL_INTENT, getIntent());
loginIntent.setData(getIntent().getData());
loginIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
LoginActivity
上拨打addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
。
基本上,在后一种情况下,您希望原始活动为Intent
授予读取权限,只是为了EXTRA_ORIGINAL_INTENT
可以将读取权限授予原始活动的新实例
最后,您使用的原始活动的任何实例都需要具有对内容的读取权限,并且由您授予访问权限,以确保实例具有该访问权限取决于您从...开始。