Android7.0、8.0應用內安裝apk的問題
文章轉載於http://www.aoaoyi.com/archives/840.html,部分個人修改的地方以紅色文字顯示。
Android開發避免不了應用內發起安裝應用,隨著Android版本的升級,許可權越來越收緊,安裝姿勢變了又變。接下來我來告訴大家針對不同Android版本正確發起應用內安裝。
首先將現有的Android版本進行分一下界限,Android 1.x~6.x 和Android 7.x 及Android 8.x。可以看下圖,如果看不懂,接下來我會詳細解說,如果你領悟了就不用往下看了。
如有一丁點不留神就會出現以下錯誤提示:
1、
1 2 |
|
Android7.0又引入“私有目錄被限制訪問”,“StrictMode API 政策”。” StrictMode API 政策” 是指禁止向你的應用外公開 file:// URI。 如果一項包含檔案 file:// URI型別 的 Intent 離開你的應用,應用失敗,並出現 FileUriExposedException 異常。
這個時候就需要使用FileProvider來解決這個問題。
2、提示解析包時出現問題
這個問題在Android8.0之後就會出現,解決方法就是AndroidManifest中新增下面許可權
1 |
|
3、沒有錯誤提示也不發起安裝器
解決方法是,在使用FileProvider的時候不要新增下面的Flag
1 |
|
對於第3條,我在Android7.0和Android8.0的機子上測試,無論是否新增Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);均不影響最後的安裝
是不是覺得我有點廢話,那我就不賣關子了,我把正確的姿勢告訴大家,請自覺搬凳子找位置且不要大聲喧譁,聽我細細道來:
第一步:在專案的res目錄下建立xml目錄,再建立file_paths.xml檔案。
內容如下:
1 2 3 4 5 6 |
|
如果不理解為什麼這麼建,那我下面再說,好吧。
第二步:在AndroidManifest.xml中新增許可權及FileProvider。
具體請往下看一眼:
許可權,這個不是危險許可權,不需要動態申請。
1 |
|
FileProvider的申請
1 2 3 4 5 6 7 8 9 |
|
需要注意的是,android:authorities=””,要新增APP的包名+.fileProvider。
第三步:程式碼實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
這裡面需要注意的是:if else裡面的寫法,flags不能加錯,不信你可以試試哦。
1 2 3 4 5 6 7 |
|
第四步:呼叫第三步即可
親自在三星的S8/S8+(Android 7.0.1),小米6(Android 8.0),一加5(Android 8.0),Mate10(Android 8.0),努比亞Z17(Android 7.0)小米2(Android 5.0.1)上測試,都沒有問題。
說了這麼多我來說一下FileProvider吧
如果你能穿越,那你就移步到官網:
如果不行,那就看我接下來瞎BB吧。
隨著Android 7.0的到來引入“私有目錄被限制訪問”,“StrictMode API 政策”,為了進一步提高私有檔案的安全性,Android不再由開發者放寬私有檔案的訪問許可權,之前我們一直使用”file:///”絕對路徑來傳遞檔案地址的方式,在接收方訪問時很容易觸發SecurityException的異常。
因此,為了更好的適配Android 7.0,例如相機拍照這類涉及到檔案地址傳遞的地方就用上了FileProvider,FileProvider也更好地進入了大家的視野。
其實FileProvider是ContentProvider的一個特殊子類,本質上還是基於ContentProvider的實現,FileProvider會把”file:///”的路徑轉換為特定的”content://”形式的content uri,接收方通過這個uri再使用ContentResolver去媒體庫查詢解析。
使用content://Uri的優點:
它可以控制共享檔案的讀寫許可權,只要呼叫Intent.setFlags()就可以設定對方app對共享檔案的訪問許可權,並且該許可權在對方app退出後自動失效。相比之下,使用file://Uri時只能通過修改檔案系統的許可權來實現訪問控制,這樣的話訪問控制是它對_所有_ app都生效的,不能區分app。
它可以隱藏共享檔案的真實路徑。
定義FileProvider
在AndroidManifest.xml的<application>節點中新增<provider>
1 2 3 4 5 6 7 8 9 |
|
android:authorities是用來標識provider的唯一標識,在同一部手機上一個”authority”串只能被一個app使用,衝突的話會導致app無法安裝。我們可以利用manifest placeholders來保證authority的唯一性。
android:exported必須設定成false,否則執行時會報錯java.lang.SecurityException: Provider must not be exported。
android:grantUriPermissions用來控制共享檔案的訪問許可權,也可以在java程式碼中設定。
指定路徑和轉換規則
FileProvider會隱藏共享檔案的真實路徑,將它轉換成content://Uri路徑,因此,我們還需要設定轉換的規則。android:resource=”@xml/provider_paths”這個屬性指定了規則所在的檔案。
res/xml/provider_paths.xml:
1 2 3 4 5 6 7 8 |
|