2017-03-03 63 views
2

缺少权限在我的应用程序的所有活动都登录保护:
在其onCreate/onShow每个活动检查-callback用户是否登录如果是这样,什么都不会发生。但是,如果用户没有登录,那么这些回调将用户重定向到一个LoginActivity和完成当前活动:重新发送意图失败,因为在URI

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

如果权限沿着Activity/Intent链传递,则在LoginActivity中重新发送原始Intent。这可以通过以下方式实现:

  1. 重定向-Intents是原始Intent的副本。
  2. 重新发送前,Intent被明确。

例如SomeActivity使用Intent的副本用于启动SomeActivity重定向到LoginActivity

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

Intent origIntent = getIntent().getParcelableExtra(EXTRA_ORIGINAL_INTENT); 
Intent redirectIntent = new Intent(origIntent); // copy ... 
redirectIntent.setClass(this, SomeActivity.class); // ... explicit now 
finish(); 
startActivity(redirectIntent); 
0

一般来说,你缺少的是FLAG_GRANT_READ_URI_PERMISSION

当您从外线得到Uri(例如,EXTRA_STREAMACTION_SEND),你应该获准至少读通过Uri标识的内容。这本身就是is a bit tricky to set up

但是,该许可授予仅针对接收Intent的组件(例如,对ACTION_SEND作出响应的您的活动)。如果您尝试将工作委派给其他任何人(另一项活动,一项服务等),那么该组件将没有权限。

所以,你有几种选择:

之一将是您的认证/授权的东西转换成一个片段或可原位使用UI的其他位,而不是启动另一个活动。这将允许您将用户全部保留在一个地方,并且该地点可以读取内容。

另一种方法是在将用户重定向到LoginActivity之前使用内容。

另一个办法是不finish()原来的活动,并使用FLAG_ACTIVITY_REORDER_TO_FRONTLoginActivity把原来的活动的现有实例回到前台。理论上,它应该仍然具有读取内容的权限。您的问题来自您正在销毁原始实例并创建一个新实例,而新实例没有读取权限。

另一种方法是将尝试添加在LoginActivityIntentFLAG_GRANT_READ_URI_PERMISSION,后来,那您是通过EXTRA_ORIGINAL_INTENT额外传递Intent。我的猜测是,这是行不通的。

上述主题的变化将不仅仅放在EXTRA_ORIGINAL_INTENTIntent,还提取其Uri之类的东西,在的LoginActivityIntent数据方面:

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)EXTRA_ORIGINAL_INTENTIntent

基本上,在后面的场景中,您希望您的原始活动授予对LoginActivity的读取访问权限,因此LoginActivity可以将读取权限授予原始活动的新实例。

最后,您使用的原始活动的任何实例都需要具有对内容的读取访问权限,并且由于您已获得开始访问权限,所以由您来确保实例具有该访问权限。

+0

感谢您的想法。我已经使用授权标志并明确设置了数据/附加组件。但它没有奏效。不过我想我明白了重新发送意图的方式。现在,当重定向时,我通过设置正确的目标活动类(例如“SendActivity”)将意图“转换”为明确的意图。似乎我不允许重新发送这种隐含的意图,但明确的意图按预期工作。这就是我想要做的事情;-) – Biggie