Android 15 變更及適配攻略

在這里插入圖片描述

2025年的第一篇Android適配,比以往來的更晚一些。廢話不多說,我們開始!!

準備工作

首先將我們項目中的 targetSdkcompileSdk 升至 35。

  • 推薦使用Android Studio Koala Feature Drop | 2024.1.2或更高版本。
  • AGP版本最低升級到8.3.0
plugins {id 'com.android.application' version '8.3.0' apply false
}

影響Android 15上所有應用

1.最低可安裝的目標 API 級別提升

Android 15要求應用的targetSDK最低為24,否則無法安裝。這塊和之前Android 14一樣,以后每年應該都會加1,所以注意提前處理,避免新系統無法安裝。

2.16KB頁面大小支持

影響范圍

使用任何NDK庫的應用都需要重新編譯以支持16KB頁面大小的設備。這點之前還是默認開啟的,后面調整為了不強制適配。但是自 2025 年 11 月 1 日起,提交到 Google Play 且以 Android 15 及更高版本的設備為目標平臺的所有新應用和現有應用更新都必須支持 64 位設備上的 16 KB 頁面大小。

它帶來的性能提升有以下幾點:

  • 應用啟動時間平均縮短3.16%,部分應用可達30%

  • 應用啟動時耗電量平均減少4.56%

  • 相機啟動速度:熱啟動平均加快4.48%,冷啟動平均加快6.60%

  • 系統啟動時間平均改善8%

適配步驟

  • 升級AGP版本到8.3或更高,推薦AGP 8.5.1 或更高版本。

  • 使用16KB ELF對齊編譯應用

  • 檢查引用特定頁面大小的代碼

具體操作,參考官方文檔。

我們是做出海項目的,所以比較關注這塊,目前使用到的三方sdk都有支持。比如我們項目中使用了MMKV,雖然MMKV 2.x版本支持16KB頁面大小,但不支持32位,所以還不能直接升級使用。1.3.x版本支持32位,但不支持16KB頁面大小。作者開始也明確不會支持,本來還打算自己修改重新編譯。好在前一陣谷歌有了上架的限制,作者也對MMKV 1.3.x版本做了相關適配支持,這里也是表示感謝。

3.當用戶強制停止應用時,widget被停用

如果用戶在搭載 Android 15 的設備上強制停止應用,系統會暫時停用該應用的所有widget。這些 widget 會灰顯,用戶無法與其互動。這是因為從 Android 15 開始,當系統強制停止應用時,會取消應用的所有待處理 intent

系統會在用戶下次啟動應用時重新啟用這些微件。

影響以Android 15或更高版本為目標平臺的應用

以下都是影響targetSDK >= 35的應用,適配時需要重點關注

1.edge-to-edge

首先說個影響面比較大的,那就是edge-to-edge,翻譯過來就是邊到邊,應用的顯示區域延伸到了全屏,不會避開狀態欄/導航欄區域。

首先狀態欄/手勢導航條區域默認將透明,三鍵導航默認不透明度為80%。

比如我之前都會給布局添加android:fitsSystemWindows="true"和設置狀態欄顏色進行沉浸狀態欄的適配,但是由于Android 15狀態欄現在變為透明,且setStatusBarColorR.attr#statusBarColor 已廢棄,對 Android 15 沒有任何作用。所以出現了下面的情況:
請添加圖片描述

狀態欄透明,因此顏色為頁面的背景色,和標題欄顏色不同。

請添加圖片描述

未添加android:fitsSystemWindows="true"的布局,底部按鈕繪制在系統導航欄后面。

適配方法:

簡單粗暴的方法就是停用edge-to-edge,可以創建values-v35,在theme中添加windowOptOutEdgeToEdgeEnforcement并設為true:


<resources xmlns:tools="http://schemas.android.com/tools"><style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">...<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item></style></resources>

不過windowOptOutEdgeToEdgeEnforcement在以Android 16為目標平臺的應用將不再生效,無法停用edge-to-edge。所以這個只是緩兵之計,如果你的適配工作量比較大且緊急,可以使用此方法。

精細化適配方法,首先注意兩點:

  • setStatusBarColor 在Android 15上不生效。
  • setNavigationBarColor 只針對三鍵導航欄有效果,手勢導航條無效。

如果你使用Compose的話:

  • 使用Material 3 組件(androidx.compose.material3),例如 TopAppBarBottomAppBarNavigationBar,這些組件不會受到影響,因為它們會自動處理insets
  • 使用Material 2 組件(androidx.compose.material),或者自定義的 Composables,這些組件不會自動處理insets 。需要自己設置padding

非compose應用:

  • 在應用布局中添加android:fitsSystemWindows="true",但是需要檢查狀態欄顏色是否符合UI要求。
  • 未添加android:fitsSystemWindows="true"的布局,相信大多數都處理了狀態欄,所以需要檢查頁面底部在系統導航欄后面的情況。同時查看導航欄顏色是否符合UI要求。
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM) {ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.root), new OnApplyWindowInsetsListener() {@NonNull@Overridepublic WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) {Insets statusBarInsets = insets.getInsets(WindowInsetsCompat.Type.statusBars());Insets navigationBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars());v.setPadding(navigationBarInsets.left,statusBarInsets.top, // 如果之前處理了狀態欄,可以改為0navigationBarInsets.right,navigationBarInsets.bottom);return insets;}});
}

2.前臺服務相關變更

前臺服務超時限制

系統會限制某些前臺服務在應用處于后臺時允許運行的時長。目前,此限制僅適用于 dataSyncmediaProcessing 前臺服務類型。

限制規則:

  • 24小時內總共只能運行6小時

  • 達到限制后,系統調用Service.onTimeout(int, int)方法,服務將不再被視為前臺服務。

  • 服務有幾秒鐘時間調用Service.stopSelf(),如果服務未調用,系統會拋出內部異常。

  • 用戶將應用打開到前臺可重置計時。再開一個 dataSync 時間也不會重新計時。

適配代碼參考:

public class MyDataSyncService extends Service {@Overridepublic int onTimeout(int startId, int fgsType) {Log.w("ForegroundService", "服務超時,類型: " + fgsType);// 實現onTimeout方法,同時必須在幾秒內調用stopSelf()stopSelf();return super.onTimeout(startId, fgsType);}@Overridepublic IBinder onBind(Intent intent) {return null;}
}

如果24小時內已經運行了 6 個小時,則無法啟動另一個dataSync前臺服務,系統會拋出ForegroundServiceStartNotAllowedException,并顯示類似“前臺服務類型 dataSync 的時間限制已用完”的錯誤消息。

public class MainActivity extends AppCompatActivity {private void startDataSyncService() {Intent serviceIntent = new Intent(this, MyDataSyncService.class);try {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {startForegroundService(serviceIntent);} else {startService(serviceIntent);}} catch (ForegroundServiceStartNotAllowedException e) {Log.e("Service", "前臺服務啟動被限制: " + e.getMessage());// 使用WorkManager等替代方案scheduleWorkWithWorkManager();}}private void scheduleWorkWithWorkManager() {// 使用WorkManager作為替代方案OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(DataSyncWorker.class).setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()).build();WorkManager.getInstance(this).enqueue(workRequest);}
}
BOOT_COMPLETED廣播接收器限制

在啟動 BOOT_COMPLETED 廣播接收器方面存在新限制前臺服務。BOOT_COMPLETED 接收器不能啟動以下類型的前臺服務:

  • dataSync
  • camera
  • mediaPlayback
  • phoneCall
  • mediaProjection
  • microphone(自 Android 14 起,microphone 就受到此限制)

如果 BOOT_COMPLETED 接收器嘗試啟動任何上述類型的前臺 服務,系統會拋出ForegroundServiceStartNotAllowedException

public class BootReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {// ? 不能在BOOT_COMPLETED中啟動這些類型的前臺服務// Intent serviceIntent = new Intent(context, DataSyncService.class);// context.startForegroundService(serviceIntent);// ? 可以使用WorkManager調度任務實現你的需求OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(BootWorker.class).setInitialDelay(5, TimeUnit.SECONDS).build();WorkManager.getInstance(context).enqueue(workRequest);}}
}
SYSTEM_ALERT_WINDOW權限限制

持有SYSTEM_ALERT_WINDOW權限的應用需要有可見的overlay窗口才能啟動前臺服務,也就是說,應用需要先啟動 TYPE_APPLICATION_OVERLAY 窗口,并且該窗口需要處于可見狀態,然后您才能啟動前臺服務。否則系統會拋出 ForegroundServiceStartNotAllowedException

public class OverlayService extends Service {private View overlayView;private WindowManager windowManager;@Overridepublic void onCreate() {super.onCreate();createOverlayWindow();}private void createOverlayWindow() {windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);overlayView = LayoutInflater.from(this).inflate(R.layout.overlay_layout, null);WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);windowManager.addView(overlayView, params);// 檢查窗口可見性overlayView.setOnWindowVisibilityChangedListener(new View.OnWindowVisibilityChangeListener() {@Overridepublic void onWindowVisibilityChanged(int visibility) {if (visibility == View.VISIBLE) {// 可見時才可以安全啟動前臺服務startForegroundServiceSafely();}}});}private void startForegroundServiceSafely() {if (overlayView != null && overlayView.getWindowVisibility() == View.VISIBLE) {try {Intent serviceIntent = new Intent(this, MyForegroundService.class);startForegroundService(serviceIntent);} catch (ForegroundServiceStartNotAllowedException e) {Log.e("Service", "前臺服務啟動失敗: " + e.getMessage());}}}
}

3.提高 intent 安全性

  • Intent必須有``action`
  • 與目標 intent 過濾器匹配
Intent intent = new Intent(context, targetClass);
// 確保Intent有action
intent.setAction(Intent.ACTION_VIEW);
try {context.startActivity(intent);
} catch (ActivityNotFoundException e) {Log.e("Intent", "無法啟動Activity", e);
}    

4.OpenJDK API 變更

Android 15 繼續推進 Android 核心庫的現代化,以與最新 OpenJDK LTS 版本(OpenJDK 17)的功能保持一致。這些變更可能會影響針對 Android 15(API 級別 35)的應用兼容性,特別是在字符串格式化、集合處理和隨機數生成等方面。

字符串格式化 API 變更

Android 15 對以下字符串格式化 API 的參數索引、標志、寬度和精度驗證變得更加嚴格:

  • String.format(String, Object[])

  • String.format(Locale, String, Object[])

  • Formatter.format(String, Object[])

  • Formatter.format(Locale, String, Object[])

使用參數索引 0 時會拋出異常:

// 錯誤示例 - 會拋出異常
String result = String.format("%0s", "test");
// IllegalFormatArgumentIndexException: Illegal format argument index = 0// 正確做法 - 使用索引 1
String result = String.format("%1$s", "test");// 或者不使用索引
String result = String.format("%s", "test");
Arrays.asList(…).toArray() 的組件類型變更

使用 Arrays.asList(…).toArray() 時,生成的數組的組件類型現在是 Object,而不是底層數組元素的類型。因此,以下代碼會拋出 ClassCastException:

String[] elements = (String[]) Arrays.asList("a", "b", "c").toArray();

適配方案

  1. 使用類型安全的方法‘
// 正確做法 - 指定數組類型
List<String> list = Arrays.asList("a", "b", "c");
String[] array = list.toArray(new String[0]);
  1. 使用 List.of()(推薦)
// 使用 Java 9+ 的 List.of()
List<String> list = List.of("a", "b", "c");
String[] array = list.toArray(new String[0]);
語言代碼處理方式變更

使用 Locale API 時,希伯來語、意第緒語和印度尼西亞語的語言代碼不再轉換為已廢棄的形式(希伯來語:iw、意第緒語:ji、印度尼西亞語:in)。為其中一種語言區域指定語言代碼時,請改用 ISO 639-1 中的代碼(希伯來語:he、意第緒語:yi、印度尼西亞語:id)。

例如:

舊文件夾:
- values-iw/(希伯來語)
- values-ji/(意第緒語)
- values-in/(印度尼西亞語)新文件夾:
- values-he/(希伯來語)
- values-yi/(意第緒語)
- values-id/(印度尼西亞語)

其他還有PDF的優化,HDR 余量控制,請求音頻焦點的限制等變更。因為我實際也沒有適配,這里就不說明了,有需要的可以查看官方文檔。

參考

  • Android 15 功能和變更列表

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86157.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86157.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86157.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue項目使用defer優化頁面白屏,性能優化提升,秒加載!!!

defer表示延遲加載&#xff0c;針對大量節點的渲染加載&#xff0c;結合使用關鍵幀requestAnimationFrame的形式來分片加載&#xff0c;可以優化白屏時間 知識補充&#xff1a; requestAnimationFrame requestAnimationFrame 是根據幀數來執行回調函數的&#xff0c;就是屏幕…

sentinel與seata組件在微服務中的基本作用

微服務基礎內容&#xff1a; 在微服務中&#xff0c;首先學習了微服務的橫向拆分與縱向拆分&#xff0c;縱向拆分指按照功能拆分模塊&#xff0c;橫向拆分指將高復用的模塊單獨拆分&#xff0c;使縱向拆分的模塊去調用這部分內容。 學習了基本拆分后&#xff0c;需要知道微服…

微信點餐小程序—美食物

本項目是基于WAMP Server 和PHP 動態網頁技術構建的微信小程序點餐系統&#xff0c;該系統主要分為前端&#xff08;微信小程序&#xff09;和后端&#xff08;基于PHPMySQL服務器端&#xff09; 整體架構流程 1、前端部分 用戶界面&#xff1a;展示菜品、處理用戶點餐操作、…

記錄Idea運行控制臺亂碼處理方案

記錄Idea運行控制臺亂碼處理方案 方法1&#xff1a;修改運行配置 打開 Run/Debug Configurations在對應的運行配置中 → 找到 VM Options → 添加&#xff1a; -Dfile.encodingUTF-8 -Dsun.jnu.encodingUTF-8重新運行程序 方法2&#xff1a;強制指定輸出流編碼 在代碼中顯…

JVM對象內存分配機制全解析

jvm創建對象的內存分配過程 1、逃逸對象在棧上分配 通過在棧上為對象分配內存,使對象占用的內存空間隨著方法結束棧幀彈出而銷毀,避免了GC垃圾收集器回收對象,減小GC的壓力; 棧上分配內存依賴逃逸分析和標量替換。 逃逸分析: 分析對象的動態作用域逃逸:當一個對象在方…

揭秘OSPF核心:LSA類型與路由計算

一、區域內路由計算 同一區域內中的所有路由器有相同的LSDB LSA關鍵字段&#xff1a; 【1】LS Age&#xff08;鏈路狀態老化時間&#xff09;&#xff1a;LSA生存的時間&#xff0c;單位秒 【2】Option&#xff08;選項字段&#xff09; 【3】LS Type&#xff08;鏈路狀…

英文摘要給成中文摘要模型

你現在使用的 UNIMO 項目&#xff08;PaddlePaddle/Research/NLP/UNIMO&#xff09;&#xff0c;默認是做英文摘要任務&#xff0c;如你在 README 中看到的數據集是 CNN/DailyMail&#xff0c;它是一個 英文摘要數據集。不過&#xff0c;這個項目的架構完全支持中文&#xff0c…

前端面試專欄-主流框架:13.vue3組件通信與生命周期

&#x1f525; 歡迎來到前端面試通關指南專欄&#xff01;從js精講到框架到實戰&#xff0c;漸進系統化學習&#xff0c;堅持解鎖新技能&#xff0c;祝你輕松拿下心儀offer。 前端面試通關指南專欄主頁 前端面試專欄規劃詳情 Vue3組件通信與生命周期深度解析 在Vue3的開發體系…

自動化交易優化網格策略

一、動態參數調整 1. 網格間距優化 - 波動率自適應&#xff1a;使用平均真實波幅&#xff08;ATR&#xff09;指標動態調整間距。例如&#xff0c;當ATR值上升20%時&#xff0c;將間距從原定的1%擴大至1.5%&#xff1b;ATR下降時則縮小間距至0.8%。可通過Python的TA-Lib庫實時計…

測試平臺ui自動化demo說明

1. 要啟動celery worker windows 開發時&#xff0c;用第二行 。&#xff08;試過&#xff0c;可以&#xff09;&#xff0c;第一行的沒試過。 celery -A myproject worker --loglevelinfo # windows電腦用下面的&#xff0c;并且settings中還要加那個solo celery -A your_p…

五大主要Token類型之字符標記Token

如大家所了解的&#xff0c;在數字化時代&#xff0c;我們每天都會與Token&#xff08;令牌&#xff09;打交道——無論是在線支付、登錄社交媒體&#xff0c;還是調用API接口&#xff0c;都離不開這一關鍵技術。 今天我們主要來學習&#xff1a;字符標記Token 在自然語言處理…

可理解性輸入:洗澡習慣

一、開場與淋浴準備 Today we’re going to learn bathroom English. Let’s get started. So the first thing we want to do. Make sure we have our towel and we’ll hang it on the towel rack before we have a shower. Because if we have a shower and then forget ou…

GO Echo框架面試題及參考答案

目錄 Echo 框架的核心結構是什么?Echo 和 Context 分別扮演什么角色? 如何創建一個 Echo 實例?簡述常見配置項。 e.Start () 與 e.StartServer () 的區別是什么? Echo 如何實現基于先后順序路由匹配? 如何注冊 GET、POST、PUT、DELETE 等不同 HTTP 方法的路由? Echo…

Java 中LinkedList 總結

406.根據身高重建隊列 力扣題目鏈接(opens new window) 假設有打亂順序的一群人站成一個隊列&#xff0c;數組 people 表示隊列中一些人的屬性&#xff08;不一定按順序&#xff09;。每個 people[i] [hi, ki] 表示第 i 個人的身高為 hi &#xff0c;前面 正好 有 ki 個身高…

大模型微調:從零到實踐,掌握AI大模型的核心技能

大模型微調&#xff1a;從零到實踐&#xff0c;掌握AI大模型的核心技能 引言 大規模語言模型&#xff08;如DeepSeek、通義千問&#xff09;的出現&#xff0c;徹底改變了自然語言處理的格局。這些模型不僅在學術界取得了突破性進展&#xff0c;在工業界也得到了廣泛應用。 …

Flutter - 原生交互 - 相冊

環境 Flutter 3.29 macOS Sequoia 15.4.1 Xcode 16.3 iOS 13.4.1 iOS 18.5 集成image_picker 在Flutter中可以使用image_picker插件實現從相冊中獲取圖片 添加插件 flutter中訪問相冊image_picker插件 flutter pub add image_pickerflutter pub getXcode工程的GenerateP…

node.js在vscode的配置

文章目錄 概要1. 使用和webstrom一樣的快捷鍵2. 讓vscode的主題變成webstrom3. 如何在 Node.js 環境下寫代碼3.1 使用 ESLint配置規則3.2 配置.vscode/settings.json 4. Prettier安裝5. 其它問題解決 概要 node.js在webstrom編輯器中可以完美使用代碼提示、錯誤提示等功能&…

Android14音頻子系統-Audio HAL分析

文章目錄 1&#xff09;概述2&#xff09;HAL的打開流程3&#xff09;HAL庫的實現(Qualcomm)4&#xff09;tinyalsa5&#xff09;數據結構6&#xff09;代碼流程 1&#xff09;概述 1、回顧HAL、tinyalsa與linux driver的關系 2、與AudioFlinger的關系 3、 1、如何判斷當前…

前端與 Spring Boot 后端無感 Token 刷新 - 從原理到全棧實踐

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有堅忍不拔之志 &#x1f390; 個人CSND主頁——Micro麥可樂的博客 &#x1f425;《Docker實操教程》專欄以最新的Centos版本為基礎進行Docker實操教程&#xff0c;入門到實戰 &#x1f33a;《RabbitMQ》…

【AI智能體】新手教程-通過 Chat SDK 搭建網頁在線客服

通過扣子搭建的智能體可以一鍵發布為 Chat SDK&#xff0c;快速部署到你的自建網站中&#xff0c;作為在線智能客服面向網站的用戶提供 AI 答疑服務。本文檔介紹通過 Chat SDK 搭建網頁版在線客服的詳細操作步驟。 場景說明 網站作為企業和組織與用戶互動的重要平臺&#xff…