1. 程式人生 > >Android 實現應用更新適配 Android O (Android 8.0)

Android 實現應用更新適配 Android O (Android 8.0)

之前寫過一篇 Android 實現應用更新(適配Anndroid N),本篇主要講解Android O(Android 8.0)上應用更新的適配問題,應用更新的完整實現請結合上一篇文章一起,文末也會給出完整程式碼連結。

最近測試反饋在Android 8.0的手機上,提示應用更新,更新時會出現下載失敗,並且通知欄也沒有顯示下載的進度的情況,即使下載成功也不會彈出應用安裝介面。

實測發現確實是有這樣的問題。當targetSdkVersion小於26時,沒有問題,當targetSDK等於26時,就會出現上述問題。
上述問題實際上是三個問題:
(1)APK檔案下載失敗
(2)通知欄不顯示
(3)下載成功沒有跳出應用安裝介面

於是馬上想到了應該是Android O(Android 8.0)的新特性導致的。

-APK檔案下載失敗

通過檢視日誌資訊,是因為在本地SD卡建立下載檔案失敗。
而建立下載檔案失敗,日誌資訊竟然是沒有許可權,怎麼可能,明明點選更新時,動態申請了“讀寫”許可權,這裡“讀寫”許可權打雙引號,是因為程式碼中申請的其實是READ_EXTERNAL_STORAGE讀儲存許可權,這在Android O(Android 8.0)之前是沒有任何問題的,因為讀寫是一組許可權,同屬儲存許可權,只要申請了同組許可權中的一個,同組中的其他在清單檔案中列出了的許可權也就被授予了。但是Android O(Android 8.0)執行時許可權有了變動,就是系統只會授予應用明確請求的許可權,
然而一旦使用者為應用授予某個許可權,則所有後續對該許可權組中許可權的請求都將被自動批准,但是還是需要去申請,這點和Android O(Android 8.0)之前不同。

由於這裡建立下載檔案,實際上是往儲存中寫檔案,需要寫儲存許可權WRITE_EXTERNAL_STORAGE,於是將程式碼點選更新時申請READ_EXTERNAL_STORAGE改為申請WRITE_EXTERNAL_STORAGE。執行測試,APK檔案是可以下載成功了。第一個問題得到解決。

-通知欄不顯示問題

在Android O(Android 8.0)之前的手機上,更新下載APK檔案時,通知欄會顯示下載進度的通知,然而Android O(Android 8.0)的手機上,targetSDK等於26時,下載檔案並沒有通知欄顯示。檢視官網Android O行為變更,發現通知的建立與顯示發生了變化,建立通知之前還需要建立一個NotificationChannel。按照官網的示例對通知的顯示做了相容性處理:(完整程式碼,文末會給出連結

)

 private void notifyUser(int progress) {

        if (Build.VERSION.SDK_INT >= 26) {

            if (mNotificationChannel == null) {
                //建立 通知通道  channelid和channelname是必須的(自己命名就好)
                mNotificationChannel = new NotificationChannel("1",
                        "Channel1",NotificationManager.IMPORTANCE_HIGH);
                mNotificationChannel.enableLights(true);//是否在桌面icon右上角展示小紅點
                mNotificationChannel.setLightColor(Color.GREEN);//小紅點顏色
                mNotificationChannel.setShowBadge(true); //是否在久按桌面圖示時顯示此渠道的通知
                mNotificationManager.createNotificationChannel(mNotificationChannel);
            }

            int notificationId = 0x1234;
            Notification.Builder builder = new Notification.Builder(getApplicationContext(), "1");
            builder.setOnlyAlertOnce(true);
            builder.setSmallIcon(R.mipmap.ic_launcher)
                    .setContentText("正在下載新版本,請稍後...")
                    .setAutoCancel(true);
            if (progress > 0 && progress <= 100) {
                builder.setProgress(100, progress, false);
            } else {
                builder.setProgress(0, 0, false);
            }

            builder.setContentIntent(progress >= 100 ? this.getContentIntent() :
                    PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT));

            Notification notification = builder.build();
            mNotificationManager.notify(notificationId, notification);

        } else {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this,null);
            builder.setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                    .setContentTitle(getString(R.string.app_name));
            if (progress > 0 && progress <= 100) {
                builder.setProgress(100, progress, false);
            } else {
                builder.setProgress(0, 0, false);
            }
            builder.setAutoCancel(true);
            builder.setWhen(System.currentTimeMillis());
            builder.setContentIntent(progress >= 100 ? this.getContentIntent() :
                    PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT));
            mNotification = builder.build();
            mNotificationManager.notify(0, mNotification);
        }
    }

這裡要特別宣告一點的是 builder.setOnlyAlertOnce(true);這句程式碼,
因為在測試的時候發現,通知更新進度的時候,手機會一直有提示音,加上這句程式碼後就不會一直有提示音了。

然後測試發現下載APK檔案時,通知欄就會正常顯示通知顯示APK下載進度了。
第二個問題也得到了解決。

-APK檔案下載成功沒有正常跳到應用安裝介面

Android O (Android 8.0) 中,Google 移除掉了容易被濫用的“允許未知來源”應用的開關,在安裝 Play Store 之外的第三方來源的 Android 應用的時候,竟然沒有了“允許未知來源”的檢查框,如果你還是想要安裝某個被自己所信任的開發者的 app,則需要在每一次都手動授予“安裝未知應用”的許可。

首先在AndroidManifest.xml 清單檔案中新增安裝未知來源應用的許可權

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

然後在使用者點選更新時判斷是否開啟了該應用的“允許安裝未知來源”的許可權,沒有的話,就引導使用者去開啟該應用的“允許安裝未知來源”的許可權,判斷程式碼如下:(完整程式碼,文末會給出連結)

private void downloadAPK(){
      boolean hasInstallPerssion = getPackageManager().canRequestPackageInstalls();
            if (hasInstallPerssion ) {
               //安裝應用的邏輯
            } else {
               //跳轉至“安裝未知應用”許可權介面,引導使用者開啟許可權,可以在onActivityResult中接收許可權的開啟結果
                Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP);
            }
          }

//接收“安裝未知應用”許可權的開啟結果
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_UNKNOWN_APP) {
            downloadAPK();
        }
    }

這樣點選更新時引導使用者開啟“允許安裝未知來源”的許可權後,APK檔案下載成功後也
成功的跳轉到應用安裝介面。第三個問題也得到了解決。

至此應用更新在Android O(Android 8.0)上的問題就都得到了解決,成功的適配了Android O。