KC Blog

Android 15 Beta版本釋出!開發者如何應對新的版本限制?

13 min read
DebugAndOptimize#Android
前言

Android 15 於近日發布了 Beta版

新版本稱作 VanillaIceCream 香草冰淇淋

以下是roadmap:

其中詳細日程可參考:官網

Android 15上所有應用會影響
軟體包行為修改
* 在class `ApplicationInfo` 中

過去存在一個名為FLAG_STOPPED的標籤

其行為是指目前是否app為停止狀態

過去停止狀態的判定為 用戶強制停止應用程式時被設定,應用程式會保持此狀態。

  • 另一方便要讓系統判定app離開停止狀態的話

過去可以透過使用者點擊開啟app、或一些互動視窗打開app可以改變狀態

↪ 這邊是官方原文

directly launching the app or indirectly interacting with the app.

(through the sharesheet or a widget, selecting the app as live wallpaper, etc.)

指出android14可透過使用者點擊開啟app一些互動視窗間接打開

其中舉的例子有sharesheetwidget選擇當作壁紙等等

  • 對比最新Android 15 系統中的 FLAG_STOPPED 有以下修改與擴充。

    1. 現在當系統判定為 FLAG_STOPPED時會停止所有pending intents的操作

    2. 當系統發現離開 FLSG_STOPPED時 會發送ACTION_BOOT_COMPLETED廣播

      官方指出可讓開發者透過此廣播恢復pending intent.

    ↪ 這邊是官方原文說明15對FLAG_STOPPED判定的調整:

Apps should only be removed from the stopped state through direct or indirect user action.

也就是說只有 直接或非直接的動作 會改變被系統判定為停止狀態

  • 從上述可以理解出對此狀態判定更嚴格了

    ↪ 不過上述原文看起來沒有明確指出何謂indirect user action.

    後續有遇到可參考

  • 另外可以透過 Application StartInfo.wasForceStopped() 方法判斷上述狀態。

支援16 KB page sizes
  • 官方針對RAM運用的策略做優化

過去android只支援4 KB memory page sizes

現在提升到16 KB page sizes

並預計明年上到Google Play(15上已有,但不確定是不是到時候會強制16KB編譯的app ✨)

將page size提升主要是為了優化ram密集型的工作,使其用起來更有效率

不過這是針對軟體的優化

主要是針對未來製造商陸續研發出更大、更高效能的ram時app能順利運行且具有兼容性

page size 是用來表示記憶體裡面的操作單位,通常是2的次方,如:2KB、4KB、8KB等。

  • app開發者影響:

    ↪ 若有使用Ndk編譯、直接或間接使用到SDK編譯可能會需要重新配置16 KB page sizes的app

短期內專案應該不太受影響

未來等正式上線Google play 可能會遇到16 KB page sizes 相關問題

✅ 遇到兼容問題可以參考官網調整編譯方式

  • 判別是不是會受到影響可透過android studioAPK Analyzer來判斷編譯的是否用到native code(或指令反編譯去看)

    ↪ 把apk拖到android studio 內

    ↪ 查看lib資料夾是否出現任意.so檔(全稱shared object)

若出現則表示你的appnative code編譯出來的

沒出lib 或 .so 則代表可能native code

✅ 官方指出有用到native code則需要rebuild app to 16KB device.

這邊有幾種初判斷參考:

↪ 使用到任何C/C++ (native) code,通常是加入NDK相關,或JNI等等。

↪ 使用的任何第三方庫用到任意native labraries。

↪ 使用任意第三方的builder若使用任意native libraries。

  • 下圖是16 KB page sizes這項功能優化後

對系統效能的提升

新增 Private space功能
此功能為新增一個隱藏app的空間或類似應用鎖

需輸入密碼才能打開存取應用

不過官方目前上面提示有bug

實測模擬器也找不到該功能

不過官方有提到該功能會限制app可見性

Because apps in the private space have restricted visibility,

後面可以用的時候可再看看自己的app放進去會不會有問題

如:不確定像是QueryAllPackagesPermission`的功能會不會跟預期不同

到時候可再試試

最小Target SDK 改為 24
* 跟上版android 14類似,一樣是為了避免用太舊的api鑽一些漏洞

android 15上 target需要大於24才能安裝

裝不了會顯示INSTALL_FAILED_DEPRECATED_SDK_VERSION

一樣可以用下列指令 安裝不符合規定的apk

adb install --bypass-low-target-sdk-block FILENAME.apk

UI/UX調整

UI/UX調整
* 移除開發者選項中的`predictive back animations`

並且讓開發者可在app中設置

<application
    ...
    android:enableOnBackInvokedCallback="true"
    ... >
...
</application>

✅ 看看predictive back animations是什麼 :參考

棄用
日常淘汰部份api: 參考api棄用
以Android 15為目標的應用會影響
foreground services相關調整
* 禁止在BOOT_COMPLETED廣播時啟動以下foreground service - dataSync - camera - mediaPlayback - phoneCall - mediaProjection - microphone

↪ 若強行啟動會拋ForegroundServiceStartNotAllowedException

  • 針對dataSync的終極審判

    ↪ dataSync的service現在每24hr內只能跑6hr,時間到了系統會呼叫Service.onTimeout(int, int)

    此時必需在收到timeout幾秒內呼叫Service.stopSelf()

    ↪ 若時間到了沒有呼叫stopSelf,則出現錯誤

    A foreground service of ##fgs_type did not stop within its timeout: ##component_name.

    ↪ 當系統呼叫Service.onTimeout(int, int)則該service不再被認為是foreground service

    ↪ 在目前beta2版本拋出的錯誤視為ANR,但在後續會改成exception.

    ↪ 上述限制為所有dataSync service共同遵守,如:24hr內已經執行4hr dataSync,則接下來其他dataSync只能執行2hr ↪ 或者官方推薦遷移成其他方式:替代方案

  • 新增forground service type:mediaProcessing

    ↪ 此type跟上面dataSync有相同的規則

    mediaProcessing的service現在每24hr內只能跑6hr,時間到了系統會呼叫Service.onTimeout(int, int)

    此時必需在收到timeout幾秒內呼叫Service.stopSelf()

    ↪ 當系統呼叫Service.onTimeout(int, int)則該service不再被認為是foreground service

    ↪ 官方提供的替代方案與上方dataSync不同:替代方案

  • 上述type要reset timer 文件中是提到

用戶把app移到前景才會reset

  • 也可嘗試使用special case

    • 點此查看
    • 不過官方會需要提供說明並經過審核才能上架
限制透過持有SYSTEM_ALERT_WINDOW來啟動foreground service的限制
* 之前透過SYSTEM_ALERT_WINDOW來啟動foreground service 即使app是在背景也可以work

現在需加一個步驟:需透過TYPE_APPLICATION_OVERLAY起動一個overlay window且需要是可見的

↪ 若未達成上述新需求則拋ForegroundServiceStartNotAllowedException.

勿擾模式行為變更
  • Target sdk Android 15 以上的app不再支援設置勿擾模式Do Not Disturb (DND)global statepolicy

↪ 影響到之前透過setInterruptionFilter(INTERRUPTION_FILTER_ALL)做設置的app

針對OpenJDK 17的改變
  • Android 15針對此調整了api使用方式,有用到可以再注意

使用以下function format 字串時新增exception

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

↪ 當誤用$0的時候會拋出 IllegalFormatArgumentIndexException: Illegal format argument index = 0

//work
val formattedString = String.format("Name: %1$s, Age: %2$d", name, age);
//exception
val formattedString = String.format("Name: %0$s, Age: %1$d", name, age);
  • 針對此issue 調整Random class 現在Random.ints()不會返回跟Random.nextInt()相同的值 所以現在不應該預期兩者是==
    • Random.ints(long)
    • Random.ints(long, int, int)
    • Random.ints(int, int)
    • Random.ints()
更安全的後台啟動Activity
* 從 Android 10 起後台 activity 啟動就受到限制,而 `Android 15 透過添加其他控制`,來`防止惡意後台應用程式`將其他應用程式帶到前台。 * 現在新增一種flag能設定,背景activity無法打開另一個app的activity
<application android:allowCrossUidActivitySwitchFromBelow="false" >

實際修改為:要打開的activity跟stack最上層 app UID不匹配的話則無法打開 ↪ 用來防止app打開另一個不同的app

  • 其他針對後台啟動activity的限縮
    • 現在PendingIntent預設關掉背景啟動activity(block background activity launches)
使用者體驗UI改善
* 此調整針對使用者體驗調整,此處大概描述下: - `Edge-to-edge enforcement`:邊到邊強制執行,android 15上會對畫面直邊緣強制內縮 不過有提到使用`material 3`不會受此影響,實測`使用material 3的app`確實與原本UI一至

其他UI如有可能受影響可注意

↪ 上方第三個圖為使用windowInsets.getInsets之類的去做調整後

或者可以使用material 3

  • elegantTextHeight attribute defaults to true:預設elegantTextHeight屬性為true
  • Stable configuration:針對configuration相關的行為調整,可能影響螢幕轉向、system bar尺寸的判斷相關

    直接點此看

  • Locale-aware default line height for EditText:根據不同語言來調整edittext的高度可能變不同

    ✅ 可再看看如果變動後是否可接受

如要取消可以直接把 useLocalePreferredLineHeightForMinimum attribute 設為 false

  • TextView width changes for complex letter shapes:預設文字的寬度指派規則有所調整

使得複雜的文字有更多空間

✅ 若想停用/啟用可直接設定attribute setShiftDrawingOffsetForStartOverhang

  • 其他UI/UX細節直接參考這邊比較完整:點此
Camera and media新增限制
* 若要請求`音頻焦點 (audio focus)`現在必需是`top app` 或是`audio-related foreground service`否則返回 AUDIOFOCUS_REQUEST_FAILED * 目前會被判定是`audio-related foreground service`有: - mediaPlayback - camera - microphone - phoneCall

✅ 學習音頻焦點 (audio focus) 直接點此看

Updated non-SDK restrictions
* 日常版本更新都有的:直接點此看
✅  `非SDK`:涵蓋範圍內的 Java 的方法。此類介面是 SDK 的內部實作細節,可能隨時會被修改,且不對開發者另行通知。