最近在工作上遇到一個需求,供內部使用的APP,由於沒有上架至Google Paly,App有改版或者Bug修復時,使用者無法透過Google Play更新,因此有了App自行下載APK檔並自動開啟安裝畫面的需求(下載的權限驗證不再這裡討論)。
在這裡練習的APK(此專案的apk檔-VersionCode為2)下載網址為
https://github.com/SolinariWu/AutomaticallyOpenApk/raw/master/Solinari.apk
上一個例子有一個About的頁面,關於此APP的資訊,我們新增一個Update的按鈕。
about.xml
Android Manifest中加入權限
我們透過DownloadManager這個System Service來進行下載的動作,將路徑設置於外部公開空間(Public external storage),並針對Andriud 6.0以上版本的系統,檢查是否有讀取的權限。
About.java
撰寫一個DialogFragmentHelper.java,用來呼叫DialogFragment
再來,於About.java中撰寫一個類別DownloadObserver,繼承ContentObserver,用來觀察下載進度的變化 再來於About.java中DownloadNewVersion(),開啟進度對話框,並於DownloadManagerEnqueue()註冊ContentObserver(CONTENT_URI的值不能改變)
進度提示框完成了,再來就剩下自動開啟APK安裝畫面了,這裡我們可以選擇當ContentObserver觀察到100%時開啟APK檔,亦或者是設定一個BroadcastReceiver,當收到「ACTION_DOWNLOAD_COMPLETE」即開啟APK安裝畫面,我選擇後者,要選擇後者的話,我們需要暫存DownloadManager下載時所產生的DownloadID,這個ID可以讓我們在Android 6.0以上版本的手機,順利取得APK的Uri,,我們使用SharedPreferences來儲存這個ID值。
撰寫SharedPreferencesHelper.java
撰寫BroadcastReceiver之前,針對7.0以上版本的手機,在取得APK檔的Uri時,需要透FileProvider,才可以正常運作,先在Android Manifest中加入
並於res目錄底下新增一個xml資料夾並新增一個file_paths.xml
撰寫DownloadCompleteReceiver.java
最後,在DownloadManagerEnqueue()中註冊BroadcastReceiver並儲存DownloadID
大功造成!
參考文獻:DownloadManager+MaterialDialog下載進度和6.0安裝APK和"程式未安裝"問題
解決 Android N 上 錯誤:android.os.FileUriExposedException
Android 6.0 儲存權限
完整專案:Solinari GitHub
先看完成圖(系統Android 7.0, API 24)↓
在這裡練習的APK(此專案的apk檔-VersionCode為2)下載網址為
https://github.com/SolinariWu/AutomaticallyOpenApk/raw/master/Solinari.apk
上一個例子有一個About的頁面,關於此APP的資訊,我們新增一個Update的按鈕。
about.xml
Android Manifest中加入權限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
我們透過DownloadManager這個System Service來進行下載的動作,將路徑設置於外部公開空間(Public external storage),並針對Andriud 6.0以上版本的系統,檢查是否有讀取的權限。
About.java
執行效果如下(可以注意到左上角有下載圖示)↓
這時候,當左上角的下載圖示消失時,我們如果至我們設定下載路徑底下可以發現,APK檔已被成功下載下來了,但這距離我想要的效果還差了許多,在下載過程中,我想要使用者能直接一目瞭然目前的下載進度,而不需要拉下提示欄觀看,那要怎麼實現呢?
先設計一個進度對話框,download_apk_dialog.xml
撰寫一個DialogFragmentHelper.java,用來呼叫DialogFragment
再來,於About.java中撰寫一個類別DownloadObserver,繼承ContentObserver,用來觀察下載進度的變化 再來於About.java中DownloadNewVersion(),開啟進度對話框,並於DownloadManagerEnqueue()註冊ContentObserver(CONTENT_URI的值不能改變)
讓我們來看看效果↓
撰寫SharedPreferencesHelper.java
撰寫BroadcastReceiver之前,針對7.0以上版本的手機,在取得APK檔的Uri時,需要透FileProvider,才可以正常運作,先在Android Manifest中加入
並於res目錄底下新增一個xml資料夾並新增一個file_paths.xml
撰寫DownloadCompleteReceiver.java
最後,在DownloadManagerEnqueue()中註冊BroadcastReceiver並儲存DownloadID
大功造成!
參考文獻:DownloadManager+MaterialDialog下載進度和6.0安裝APK和"程式未安裝"問題
解決 Android N 上 錯誤:android.os.FileUriExposedException
Android 6.0 儲存權限
完整專案:Solinari GitHub