1. 程式人生 > >Android各版本迭代改動與適配集合

Android各版本迭代改動與適配集合

## 前言 今天分享的面試題是: Android在版本迭代中,總會進行很多改動,那麼你熟知各版本都改動了什麼內容?又要怎麼適配呢? ## Android4.4 * 釋出`ART`虛擬機器,提供選項可以開啟。 * `HttpURLConnection`的底層實現改為了OkHttp。 ## Android5.0 * `ART`成為預設虛擬機器,完全代替Dalvik虛擬機器。 * `Context.bindService()` 方法需要顯式 Intent,如果提供隱式 intent,將引發異常。 ## Android6.0 * 增加執行時許可權限制 如果你的應用使用到了危險許可權,比如在執行時進行檢查和請求許可權。`checkSelfPermission()`方法用於檢查許可權,`requestPermissions()` 方法用於請求許可權。 * 取消支援Apache HTTP Android 6.0 版移除了對 `Apache HTTP`相關類庫的支援。要繼續使用 Apache HTTP API,您必須先在 build.gradle 檔案中宣告以下編譯時依賴項: ```java android {useLibrary 'org.apache.http.legacy'} ``` 有的小夥伴可能不熟悉這是啥,簡單說下: > Apache HttpClient 是Apache開源組織提供的一個開源的專案,它是一個簡單的HTTP客戶端(並不是瀏覽器),可以傳送HTTP請求,接受HTTP響應。 所以說白了,其實就是一個請求網路的專案框架。 ## Android 7.0 * Android 7.0 引入一項新的應用簽名方案 APK Signature Scheme v2 * Toast導致的BadTokenException * 在Android7.0系統上,Android 框架強制執行了 StrictMode API 政策禁止向你的應用外公開 file:// URI。 如果一項包含檔案 file:// URI型別 的 Intent 離開你的應用,應用失敗,並出現 `FileUriExposedException` 異常,如呼叫系統相機拍照錄制視訊,或裁切照片。 這一點其實就是限制了在應用間共享檔案,如果需要在應用間共享,需要授予要訪問的URI臨時訪問許可權,我們要做的就是註冊`FileProvider`: 1)宣告FileProvider。 ```xml ``` 2)編寫xml檔案,確定可訪問的目錄 ```xml ``` 3)使用FileProvider ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Uri uri = FileProvider.getUriForFile(CameraActivity.this, "app的包名.fileProvider", photoFile); } else { Uri uri = Uri.fromFile(photoFile); } ``` ## Android8.0 * 修改執行時許可權錯誤 在 `Android 8.0` 之前,如果應用在執行時請求許可權並且被授予該許可權,系統會錯誤地將屬於同一許可權組並且在清單中註冊的其他許可權也一起授予應用。 對於針對 Android 8.0 的應用,系統只會授予應用明確請求的許可權。然而,一旦使用者為應用授予某個許可權,則所有後續對該許可權組中許可權的請求都將被自動批准。 也就是說,以前你申請了`READ_EXTERNAL_STORAGE`許可權,應用會同時給你授予同許可權組的`WRITE_EXTERNAL_STORAGE`許可權。如果Android8.0以上,只會給你授予你請求的`READ_EXTERNAL_STORAGE`許可權。如果需要`WRITE_EXTERNAL_STORAGE`許可權,還要單獨申請,不過系統會立即授予,不會提示。 * 修改通知 Android 8.0 對於通知修改了很多,比如通知渠道、通知標誌、通知超時、背景顏色。其中比較重要的就是通知渠道,其允許您為要顯示的每種通知型別建立使用者可自定義的渠道。 這樣的好處就是對於某個應用可以把許可權分成很多類,使用者來控制是否顯示哪些類別的通知。而開發者要做的就是必須設定這個渠道id,否則通知可能會失效。 ```java private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //分組(可選) //groupId要唯一 String groupId = "group_001"; NotificationChannelGroup group = new NotificationChannelGroup(groupId, "廣告"); //建立group notificationManager.createNotificationChannelGroup(group); //channelId要唯一 String channelId = "channel_001"; NotificationChannel adChannel = new NotificationChannel(channelId, "推廣資訊", NotificationManager.IMPORTANCE_DEFAULT); //補充channel的含義(可選) adChannel.setDescription("推廣資訊"); //將渠道新增進組(先建立組才能新增) adChannel.setGroup(groupId); //建立channel notificationManager.createNotificationChannel(adChannel); //建立通知時,標記你的渠道id Notification notification = new Notification.Builder(MainActivity.this, channelId) .setSmallIcon(R.mipmap.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .setContentTitle("一條新通知") .setContentText("這是一條測試訊息") .setAutoCancel(true) .build(); notificationManager.notify(1, notification); } } ``` * 懸浮窗 Android8.0以上必須使用新的視窗型別(`TYPE_APPLICATION_OVERLAY`)才能顯示提醒懸浮窗: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY }else { mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT } ``` * 不允許安裝未知來源的應用 Android 8.0去除了“允許未知來源”選項,所以如果我們的App有安裝App的功能(檢查更新之類的),那麼會無法正常安裝。