2017-03-03 64 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