1. 程式人生 > >Android7.0、8.0應用內安裝apk的問題

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
Caused by: android.os.FileUriExposedException
: file:///storage/emulated/0/Download/myApp.apk exposed beyond app through Intent.getData()

Android7.0又引入“私有目錄被限制訪問”,“StrictMode API 政策”。” StrictMode API 政策” 是指禁止向你的應用外公開 file:// URI。 如果一項包含檔案 file:// URI型別 的 Intent 離開你的應用,應用失敗,並出現 FileUriExposedException 異常。
這個時候就需要使用FileProvider來解決這個問題。

2、提示解析包時出現問題
這個問題在Android8.0之後就會出現,解決方法就是AndroidManifest中新增下面許可權

1
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

3、沒有錯誤提示也不發起安裝器

解決方法是,在使用FileProvider的時候不要新增下面的Flag

1
_Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

對於第3條,我在Android7.0和Android8.0的機子上測試,無論是否新增Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);均不影響最後的安裝

是不是覺得我有點廢話,那我就不賣關子了,我把正確的姿勢告訴大家,請自覺搬凳子找位置且不要大聲喧譁,聽我細細道來:

第一步:在專案的res目錄下建立xml目錄,再建立file_paths.xml檔案。

內容如下:

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<paths>
 <root-path name="root" path="" />
 <external-path name="external_storage_root" path="." />
 <external-path name="external_storage_download" path="Download" />
</paths>

如果不理解為什麼這麼建,那我下面再說,好吧。

第二步:在AndroidManifest.xml中新增許可權及FileProvider。

具體請往下看一眼:

許可權,這個不是危險許可權,不需要動態申請。

1
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

FileProvider的申請

1
2
3
4
5
6
7
8
9
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities=".fileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
         android:name="android.support.FILE_PROVIDER_PATHS"
         android:resource="@xml/file_paths"/>
</provider>

需要注意的是,android:authorities=””,要新增APP的包名+.fileProvider。

第三步:程式碼實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public static void installApp(Context pContext, File pFile){
        if (null == pFile)
            return;
        if (!pFile.exists())
            return;
        Intent _Intent = new Intent();
        _Intent.setAction(Intent.ACTION_VIEW);
        Uri _uri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            _Intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            _uri = FileProvider.getUriForFile(pContext, pContext.getPackageName() + ".fileProvider", pFile);
        }else {
            _uri = Uri.fromFile(pFile);
            _Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        _Intent.setDataAndType(_uri, "application/vnd.android.package-archive");
        pContext.startActivity(_Intent);
    }

這裡面需要注意的是:if else裡面的寫法,flags不能加錯,不信你可以試試哦。

1
2
3
4
5
6
7
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
	_Intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
	_uri = FileProvider.getUriForFile(pContext, pContext.getPackageName() + ".fileProvider", pFile);
}else{
	_uri = Uri.fromFile(pFile);
	_Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
第四步:呼叫第三步即可

親自在三星的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
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

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
<paths xmlns:android="http://schemas.android.com/apk/res/android">
   <root-path name="root" path="" />
   <external
            
           

相關推薦

Android7.08.0應用安裝apk實現

最近,公司線上專案發現,部分手機應用內更新下載apk後安裝無反應的問題。由於測試我並未參與,得知同事的問題描述後誤認為是部分機型的相容性問題,費了半天勁。最後才發現是Andorid8.0許可權問題,很是惱火啊,哈哈。鑑於此,還是把不同Android版本正確發起應用內安裝的實現

Android7.08.0應用安裝apk的問題

文章轉載於http://www.aoaoyi.com/archives/840.html,部分個人修改的地方以紅色文字顯示。Android開發避免不了應用內發起安裝應用,隨著Android版本的升級,許可權越來越收緊,安裝姿勢變了又變。接下來我來告訴大家針對不同Android

Android7.08.0安裝apk以及安裝apk彈出“選擇開啟方式”的解決方案

目錄 問題描述 解決方案 問題描述 解決方案 問題描述 解決方案 最近在做一款APP,做自動更新的時候,安裝apk遇到了一些問題: FileUriExposedException異常; 無法跳轉到APP安裝頁面,無法進行版本更新升

華為手機8.0 應用安裝APK閃退問題

自動更新功能在安卓6.0 7.0下均沒問題華為安卓8.0手機閃退在網路上找了很多 都沒有解決耽誤了很長時間最後發現解決方法很簡單 只要在Mainfest.xml 中加入許可權編碼即可解決<uses-permissionandroid:name="android.perm

Android線上應用更新(站更新) 適配6.07.08.0

概要 線上應用內更新 在APP開發中是最基礎的一項功能。主要可以分為以下幾步: 獲取當前版本資訊; 獲取後臺線上版本資訊; 版本對比,提示更新 點選取消,跳過更新,進入app 點選確定,開始下載 下載結束,提示安裝 正文 這裡略過1—4步驟,

Android7.08.09.0的https抓包,charles解決方案

原文地址:https://blog.csdn.net/u011045726/article/details/76064048   Android7.0 和 Charles 的抓包 關於android手機在mac版charles上抓不到包這個問題困擾了很久,查閱了很多資料,發現是an

Android 系統自帶圖片裁剪功能(適配7.08.0對了還有小米手機)

前段時間寫了如何獲取相簿和拍照之後的照片並且進行顯示和上傳,這一次是如何進行圓形影象製作,經常看我寫的筆記的人會知道,我很懶。那麼我就懶的自定義了,目前需求就用原生的就好了,大神的輪子,我會在後面進行推薦。這篇筆記是依賴於:Android呼叫相簿、相機(相容6.0、7.0、8.0) 文

Android呼叫相簿相機(相容6.07.08.0)所需新增的許可權

在AndroidManifest.xml中新增: <!--讀寫記憶體塊許可權--> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/&

Android app 線上更新那點事兒(適配Android6.07.08.0

一、前言 app線上更新是一個比較常見需求,新版本釋出時,使用者進入我們的app,就會彈出更新提示框,第一時間更新新版本app。線上更新分為以下幾個步驟: 1, 通過介面獲取線上版本號,versionCode 2, 比較線上的versionCode 和本地的versi

Android 拍照及相簿選取圖片功能,已適配Android6.07.08.0

更換頭像或者上傳圖片功能已基本是每個 APP 所具備的基礎功能了,但這對於開發者來說是一個很麻煩的事情,除機型之外,適配版本就至少要考慮這幾種情況(6.0以下版本、6.0的動態許可權、7.0的FileProvider、8.0的特殊情況)。 今天來個總

Ubuntu 18.04上CUDA 9.0cuDNN7.0及Tensorflow 1.8安裝

http amd64 時間 com ++ dnn 7 清華 配置 示例 配置 筆者使用Dell Inspiron 7559筆記本電腦,顯卡為NVIDIA GTX 960M。 目標 由於本機顯卡僅有nvidia-384驅動包能夠良好支持(nvidia-387、nvidia-3

應用下載更新app適配Ansroid7.08.0

應用中使用的下載更新app的方式 1.使用Okhttp進行apk檔案下載 module的gradle中加入下面兩行,專案依賴Okhttp 2.訪問檔案適配android 7.0及以上版本 在Manifest中新增: 3.res資原始檔下建立目錄xml: 下載

阿里雲Linux下安裝MySql5.65.78.0版本和解除安裝以及遠端連線

在安裝的時候參考了很多部落格,但是發現還是 MySql的官網給的步驟最有效,最權威。 適合: Debian 7,8,9 Ubuntu 14.04,16.04,17.10,18.04 下面記錄下我安裝的步驟: 1,新增 MySQL APT儲存庫 首先我們需要

微軟URLRewriter.dll的url重寫在目標框架.Net Framework2.04.0應用程序池經典模式集成模式下的配置

原理 有一個 write 地址 ack 解決 targe 應用程序池 url重寫 大家參考幾篇園子裏面的這篇文章: 文章1:微軟URLRewriter.dll的url重寫的簡單使用 (講解了使用UrlReWriter.dll的下載、web.config如何在目標框架2.

MySQL5.65.78.0在線DDL對比情況

tro blog col tex img 當前 mysql5 color 官方網站 MySQL5.6的版本之後支持了在線DDL,這對於DBA來說是個福音,但是MySQL5.6、5.7和當前的最新版本8.0在各種DDL中的情況不太一樣,根據MySQL官方網站的說明整理一份在線

VS2012+OpenCV3.0+CMake3.8環境的OpenCV安裝/配置/新建工程

        OpenCV3.0版本相比2.x版本,不僅提供了新的特性,而且將眾多核心/依賴庫(opencv_core249.lib,opencv_highgui249d等)合成為opencv_wo

惠普暗夜精靈3plus配置ubuntu18.0.4cuda9.0cudnn7.0anaconda(python2.7)tensorflow-gpu1.8kerasopencv等

一、ubuntu18.0.4 新的版本核心為22,,安裝用u盤啟動,分割槽為/,swap,/boot。桌面版畫面更精緻,ubuntu圖形介面越來越漂亮。自帶整合顯示卡。 二、cuda9.0 先安裝顯示卡驅動,先遮蔽掉自帶的整合顯示卡驅動,重

1079: C語言程式設計教程(第三版)課後習題8.2---求方程 的根,用三個函式分別求當b^2-4ac大於0等於0和小於0時的根,並輸出結果。從主函式輸入abc的值。【兩種方法】

題目描述 求方程 的根,用三個函式分別求當b^2-4ac大於0、等於0、和小於0時的根,並輸出結果。從主函式輸入a、b、c的值。 輸入 a b c 輸出 x1=? x2=? 樣例輸入 4

Android Studio 第五十七期 - Android運行時權限4.08.0

運行時權限 代碼已經整理好,效果如下圖: 地址:https://github.com/geeklx/myapplication2018/tree/master/p001_fitandroid7Android Studio 第五十七期 - Android運行時權限4.0至8.0

usb2.0usb3.0usb3.1type-c 接口含義與區別

區別 wikipedia baidu 分享 3.0 沒有 速度 ID 外觀 簡單說: usb3.0比2.0的傳輸速率快,充電快,能向下兼容2.0 usb3.1比2.0的傳輸速率更快、充電更快,同兼容 先看下usb2.0接口 usb2.0 理論傳輸速率4