Android14 適配之——現(xiàn)有 App 安裝到 Android14 手機(jī)上需要注意些什么?

致讀者:本人簡書即將停止更新魔种,如需聯(lián)系請(qǐng)加V析二,或公號(hào)見,謝謝~

好久不見~ 最近幾個(gè)月變化挺大的节预,不論是自己的家庭還是社會(huì)環(huán)境叶摄,把我們能做的做好,慢慢適應(yīng)新的變化安拟,這也是一種不可或缺的能力吧蛤吓!

Android14 即將正式發(fā)布,作為開發(fā)者需要注意哪些內(nèi)容糠赦?長話短說会傲,一起來看看吧~

主要分為兩部分:
一是影響所有的 Android 應(yīng)用锅棕,這些改動(dòng)會(huì)影響所有的 App,只要你的 App 安裝在了 Android14 的設(shè)備上淌山,都會(huì)受到這些影響裸燎;
二是當(dāng) targetSdkVersion 升級(jí)到 34 后,我們的 App 所受到的影響泼疑。這一篇先來說說第一部分的內(nèi)容德绿,即現(xiàn)有 App 安裝到 Android14 手機(jī)上,會(huì)有哪些影響退渗。

1. SCHEDULE_EXACT_ALARM 權(quán)限默認(rèn)關(guān)閉

這個(gè)權(quán)限的全稱是 android.permission.SCHEDULE_EXACT_ALARM脆炎,用于是否開啟設(shè)置精確鬧鐘的權(quán)限。精確的鬧鐘適用于用戶指定時(shí)間的通知氓辣,或是在確切的時(shí)間需要執(zhí)行的操作秒裕。

如果 App 的 targetSdkVersion 設(shè)置的是 33(Android13)或更高,在 Android14 的設(shè)備上運(yùn)行時(shí)钞啸,這個(gè)權(quán)限就是默認(rèn)關(guān)閉的几蜻。所以,當(dāng) App 中有用到精確鬧鐘体斩,需要在確切的時(shí)間點(diǎn)去做操作梭稚,那么就需要在 Manifest 文件中顯式地申請(qǐng)這個(gè)權(quán)限并需要在使用時(shí)動(dòng)態(tài)向用戶獲取該權(quán)限。

具體地說就是絮吵,當(dāng)使用 AlarmManager 中的
setExact(int type, long triggerAtMillis, PendingIntent operation)弧烤、
setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation)
setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation)
這三個(gè)函數(shù)時(shí)蹬敲,如果 targetSdkVersion >= 33暇昂,且在 Android14 設(shè)備上沒有顯式申請(qǐng)?jiān)摍?quán)限,則會(huì)拋出一個(gè) SecurityException 異常伴嗡。

特殊情況:
1)如果用戶通過“備份與恢復(fù)”功能將 App 傳輸?shù)揭粋€(gè) Android14 的設(shè)備上急波,則此 App 的該權(quán)限默認(rèn)仍是關(guān)閉的;
2)如果一個(gè) App 已經(jīng)開啟了該權(quán)限瘪校,當(dāng)設(shè)備升級(jí)到 Android14 后澄暮,此 App 的該權(quán)限是開啟的狀態(tài);
3)當(dāng)精確鬧鐘是通過 OnAlarmListener 設(shè)置的阱扬,則無需申請(qǐng)?jiān)摍?quán)限泣懊。例如:setExact(int type, long triggerAtMillis, String tag, AlarmManager.OnAlarmListener listener, Handler targetHandler) 這個(gè)方法就無需申請(qǐng)。

用的比較多的 API:
1)boolean canScheduleExactAlarms() 判斷是否可以設(shè)置精確鬧鐘(API >= 31 才有此判斷方法)麻惶;
2)AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED 廣播消息常用來監(jiān)聽用戶開啟或關(guān)閉該權(quán)限的回調(diào)(API >= 31 才有此廣播消息類型)馍刮。

不建議的使用場景:
1)如果 App 在生命周期內(nèi)安排重復(fù)性的操作,可以使用 Handler 中的 postAtTime 等來替代用踩。相反渠退,如果是要設(shè)置 30min 后或者明天下午 2 點(diǎn)的操作忙迁,則建議使用;
2)安排在后臺(tái)進(jìn)行的一些操作碎乃,例如:下載更新App或者上傳日志等姊扔。建議使用 WorkManager 而不是精確鬧鐘;
3)當(dāng)系統(tǒng)處于空閑時(shí)梅誓,在大概的時(shí)間點(diǎn)處理事務(wù)恰梢,則可以調(diào)用非精確鬧鐘的一些 API 處理,例如使用 setAndAllowWhileIdle() 而不是 setExactAndAllowWhileIdle() 方法梗掰;
4)用戶指定的在大概特定時(shí)間點(diǎn)發(fā)生的嵌言,或者在一個(gè)時(shí)間窗口內(nèi)發(fā)生的事務(wù);

適配流程:
1)調(diào)用 alarmManager.canScheduleExactAlarms() 檢查是否有該權(quán)限及穗;
2)如果沒有權(quán)限摧茴,則需要通過 Intent,設(shè)置 ActionACTION_REQUEST_SCHEDULE_EXACT_ALARM 并加上應(yīng)用包名調(diào)起設(shè)置頁面埂陆,讓用戶賦予權(quán)限苛白,返回后在 onResume 回調(diào)中判斷是否權(quán)限是否已申請(qǐng)。

下面是一個(gè)例子:

// code 1
// MyFragment.kt 中的代碼
    private val ALARM_REQUEST_CODE = 123
    private var getExactSchedulePermission = false
    @RequiresApi(Build.VERSION_CODES.S)
    private fun scheduleAlarm() {
        // 創(chuàng)建一個(gè) Intent焚虱,用于指定定時(shí)任務(wù)觸發(fā)時(shí)要執(zhí)行的操作
        val intent = Intent(requireContext(), AlarmReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(
            requireContext(),
            ALARM_REQUEST_CODE,
            intent,
            PendingIntent.FLAG_IMMUTABLE
        )

        // 獲取 AlarmManager 實(shí)例
        val alarmManager = requireActivity().getSystemService(Context.ALARM_SERVICE) as AlarmManager

        // 觸發(fā)時(shí)間(這里使用相對(duì)時(shí)間)
        val triggerTime = SystemClock.elapsedRealtime() + 5000 // 5秒后觸發(fā)

        // 設(shè)置定時(shí)任務(wù)
        if (alarmManager.canScheduleExactAlarms()) {
            alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, pendingIntent)
        } else {
            // 如果沒有權(quán)限則打開設(shè)置頁购裙,讓用戶授予該 App 的精確鬧鐘權(quán)限
            startActivity(Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM))
            getExactSchedulePermission = true
        }
    }

    @RequiresApi(Build.VERSION_CODES.S)
    override fun onResume() {
        super.onResume()
        if (getExactSchedulePermission) {
            scheduleAlarm()
            getExactSchedulePermission = false
        }
    }

// AlarmReceiver.kt
class AlarmReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Toast.makeText(context, "Alarm triggered!", Toast.LENGTH_SHORT).show()
    }
}

當(dāng)運(yùn)行 scheduleAlarm() 方法后,過 5 秒就會(huì)有 Toast 出現(xiàn)~

日歷或鬧鐘應(yīng)用需要在應(yīng)用停止運(yùn)行時(shí)發(fā)送日歷提醒鹃栽、喚醒鬧鐘或提醒躏率。這些應(yīng)用可以請(qǐng)求 USE_EXACT_ALARM 常規(guī)權(quán)限。系統(tǒng)將在安裝時(shí)授予 USE_EXACT_ALARM 權(quán)限民鼓,擁有此權(quán)限的應(yīng)用將能夠像具有 SCHEDULE_EXACT_ALARM 權(quán)限的應(yīng)用一樣設(shè)置精確鬧鐘薇芝。

小結(jié):能不用就不用。如果之前已用到精確鬧鐘摹察,則需要新增權(quán)限獲取邏輯恩掷。

2. 動(dòng)態(tài)廣播當(dāng) App 進(jìn)入緩存態(tài)時(shí)將會(huì)入隊(duì)保存

在 Android14 中倡鲸,我們使用 Context 上下文注冊(cè)的動(dòng)態(tài)廣播接收器供嚎,可以在 App 進(jìn)入緩存狀態(tài)時(shí),將已發(fā)送還未接收的廣播放入到一個(gè)隊(duì)列中保存峭状。當(dāng) App 離開緩存狀態(tài)(比如進(jìn)入前臺(tái))克滴,則系統(tǒng)會(huì)傳遞所有已加入隊(duì)列的廣播。某些廣播的多個(gè)實(shí)例可以合并為一個(gè)廣播优床。

而在 Manifest 文件中注冊(cè)的靜態(tài)廣播接收器劝赔,則不能進(jìn)入隊(duì)列,它們會(huì)在 App 從緩存狀態(tài)中被移除銷毀時(shí)胆敞,進(jìn)行廣播傳遞着帽。

什么是緩存狀態(tài)下的 App杂伟?簡單理解就是在后臺(tái)的 App,目前不在前臺(tái)的進(jìn)程仍翰,因此赫粥,如果系統(tǒng)其他地方需要內(nèi)存,系統(tǒng)可以根據(jù)需要自由地終止這些進(jìn)程予借。當(dāng)然終止的順序是最老未使用的最先被終止越平。

3. App 只能終止自己的后臺(tái)進(jìn)程

從 Android14 開始,調(diào)用 killBackgroundProcesses() 時(shí)灵迫,只能終止自己應(yīng)用的后臺(tái)進(jìn)程秦叛。如果傳入另一個(gè)應(yīng)用的軟件包名稱,此方法對(duì)該應(yīng)用的后臺(tái)進(jìn)程沒有影響瀑粥,并且 Logcat 中會(huì)顯示以下消息:

Invalid packageName: com.example.anotherapp

官方給出的解釋是:

您的應(yīng)用不應(yīng)使用 killBackgroundProcesses() API挣跋,也不得以其他方式嘗試影響其他應(yīng)用的進(jìn)程生命周期,即使在舊版操作系統(tǒng)上也是如此狞换。Android 旨在讓緩存應(yīng)用在后臺(tái)運(yùn)行浆劲,并在系統(tǒng)需要內(nèi)存時(shí)自動(dòng)終止它們。如果您的應(yīng)用不必要地終止其他應(yīng)用哀澈,則由于之后需要完全重啟這些應(yīng)用牌借,因此可能會(huì)降低系統(tǒng)性能并增加耗電量,這比恢復(fù)現(xiàn)有緩存應(yīng)用所消耗的資源要多得多割按。

該 API 是 ActivityManager 提供的膨报,完整的方法聲明:

// code 2
public void killBackgroundProcesses (String packageName)

此外,使用它還需要在 Manifest 文件中申請(qǐng)權(quán)限 Manifest.permission.KILL_BACKGROUND_PROCESSES.

經(jīng)測(cè)試适荣,我發(fā)現(xiàn)這個(gè) API 有點(diǎn)奇怪:被殺死的后臺(tái)進(jìn)程馬上又會(huì)重啟现柠,額。弛矛。够吩。這是什么操作?丈氓?

測(cè)試代碼比較簡單周循,就是在另外一個(gè)進(jìn)程中開啟一個(gè) Service,然后調(diào)用 killBackgroundProcesses 方法即可万俗,根據(jù)打印的 Service 生命周期可看出湾笛,該 Service 確實(shí)先被殺死然后又走了一次 onCreateonStartCommand 生命周期闰歪,代碼和結(jié)果如下所示:

// code 3
// Manifest 文件聲明 Service 在另一個(gè)進(jìn)程中啟動(dòng)
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<service
    android:name=".MyService"
    android:process="com.secondProcess" />

// 啟動(dòng) Service
startService(Intent(requireContext(), MyService::class.java))
// 殺死后臺(tái)進(jìn)程
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
activityManager.killBackgroundProcesses(context.packageName)

log 打印結(jié)果:
[圖片上傳失敗...(image-a5f2f4-1697555899201)]
從圖上可知嚎研,在 Android14 的設(shè)備上,調(diào)用 killBackgroundProcesses 方法可以殺死自己 App 的后臺(tái)進(jìn)程库倘,但會(huì)立即重新啟動(dòng)临扮。在源碼中也找到了下面的代碼论矾,雖然已被廢棄:

// code 3
    @Deprecated
    public void restartPackage(String packageName) {
        killBackgroundProcesses(packageName);
    }

看來這個(gè) API 就是用來重啟 App 的后臺(tái)進(jìn)程的?

試了下在 Android14 設(shè)備上的 A App 中調(diào)用此 API 去殺死 B App 的后臺(tái)進(jìn)程杆勇,確實(shí)沒有任何作用拇囊;但如果是在 Android14 以下的設(shè)備上調(diào)用,確實(shí)可以殺死 B App 的后臺(tái)進(jìn)程靶橱。感興趣的同學(xué)也可試一試寥袭。

小結(jié):killBackgroundProcesses API 并沒有什么卵用~(歡迎大佬指點(diǎn))

4. 安全方面

在 Android14 系統(tǒng)手機(jī)上,將無法安裝 targetSdkVersion < 23(低于Android6.0)的 App关霸。

媒體包名稱在 Android14 上可能會(huì)被隱藏传黄。目前媒體庫支持按照 OWNER_PACKAGE_NAME 列查詢某包名下的所有媒體文件,一個(gè)應(yīng)用存儲(chǔ)的媒體文件是帶有它自己的包名信息的队寇。這些信息將在 Android14上被隱藏膘掰,除非滿足以下條件之一:
1)存儲(chǔ)媒體文件的應(yīng)用包名稱始終對(duì)其他應(yīng)用可見(自己開放給所有其他 App);
2)查詢媒體庫的應(yīng)用獲得了 QUERY_ALL_PACKAGES 權(quán)限(其他 App 向用戶申請(qǐng)獲得了權(quán)限)佳遣。

舉個(gè)栗子:
當(dāng)一個(gè)應(yīng)用存儲(chǔ)了一個(gè)媒體文件(例如一張照片或一個(gè)視頻)识埋,它會(huì)在媒體庫中記錄該文件的信息,包括該文件的所有者包名零渐。其他應(yīng)用可以查詢媒體庫以獲取這些信息窒舟,以便在自己的應(yīng)用中顯示該文件或與之交互。

在 Android14 及以后的版本中诵盼,如果存儲(chǔ)媒體文件的應(yīng)用的包名不是始終對(duì)其他應(yīng)用程序可見的惠豺,則在查詢媒體庫時(shí),所有者包名將被隱藏或替換為匿名值风宁。例如洁墙,如果一個(gè)應(yīng)用包名為“com.example.app”,它存儲(chǔ)了一個(gè)媒體文件戒财,但它的包名被隱藏了热监,那么在查詢媒體庫時(shí),所有者包名可能會(huì)被替換為“com.android.providers.media”饮寞。

但是孝扛,如果存儲(chǔ)媒體文件的應(yīng)用具有始終對(duì)其他應(yīng)用可見的包名,或者查詢媒體庫的應(yīng)用程序具有QUERY_ALL_PACKAGES 權(quán)限骂际,則可以看到媒體庫中的完整所有者包名疗琉。例如,一個(gè)應(yīng)用名為“com.example.app”歉铝,它存儲(chǔ)了一個(gè)媒體文件,并且它的包名始終對(duì)其他應(yīng)用程序可見凑耻,那么在查詢媒體庫時(shí)太示,所有者包名將顯示為“com.example.app”柠贤。

5. 用戶體驗(yàn)方面

5.1 可單獨(dú)對(duì)照片和視頻訪問權(quán)限進(jìn)行授權(quán)

如果你的 App 以 Android13 或更高版本為目標(biāo)平臺(tái)(即 targetSdkVersion >= 33),且在 Android14 的設(shè)備上運(yùn)行時(shí)类缤,用戶可以授予對(duì)其照片和視頻的部分訪問權(quán)限臼勉,即單獨(dú)設(shè)置 READ_MEDIA_IMAGESREAD_MEDIA_VIDEO

即申請(qǐng) READ_MEDIA_IMAGES 權(quán)限時(shí)餐弱,僅會(huì)顯示手機(jī)上所有圖片給用戶進(jìn)行選擇宴霸;申請(qǐng) READ_MEDIA_VIDEO 權(quán)限時(shí),僅會(huì)顯示手機(jī)上所有的視頻給用戶進(jìn)行選擇膏蚓。用戶可以更加細(xì)致地選擇將哪些照片或視頻授權(quán)給 App 讀取使用瓢谢。

新的系統(tǒng)對(duì)話框長這樣:
[圖片上傳失敗...(image-ff46c4-1697555899201)]

1)選擇照片和視頻: Android14 中的新功能。用戶選擇希望提供給應(yīng)用的具體照片和視頻驮瞧。
2)全部允許:用戶授予對(duì)設(shè)備上的所有照片和視頻的完整訪問權(quán)限氓扛。
3)不允許:用戶拒絕授予所有訪問權(quán)限。

注意:
1)當(dāng)應(yīng)用已經(jīng)在使用系統(tǒng)的 照片選擇器论笔,則無需執(zhí)行任何操作即可支持此變更采郎;
2)READ_MEDIA_IMAGESREAD_MEDIA_VIDEO 僅在 Android13 或以上的版本才能使用;

新增了一個(gè) READ_MEDIA_VISUAL_USER_SELECTED 權(quán)限狂魔,屬于 Dangerous 級(jí)別蒜埋。用于在用戶點(diǎn)擊自定義的照片選擇器需要申請(qǐng)?jiān)L問照片和視頻的權(quán)限時(shí)使用,這樣就不用去申請(qǐng) READ_MEDIA_IMAGESREAD_MEDIA_VIDEO 這兩個(gè)權(quán)限了最楷。

小結(jié):開發(fā)者不用管理茎,新的權(quán)限很雞肋,暫時(shí)用不上管嬉,之前讀取照片和視頻的相關(guān)邏輯也不用改皂林。

5.2 更安全的全屏通知展示

在 Android11(API level 30)上就可以調(diào)用 Notification.Builder.setFullScreenIntent 方法在鎖屏上展示一些全屏的通知了,不過得在 Manifest 文件中申請(qǐng) USE_FULL_SCREEN_INTENT 權(quán)限蚯撩。

全屏通知是為了讓用戶立即注意到的高優(yōu)先級(jí)通知而設(shè)計(jì)的础倍,例如來電或用戶配置的鬧鐘,在展示全全屏通知時(shí)胎挎,用戶只能上滑退出沟启,如下圖所示的系統(tǒng)提示。

[圖片上傳失敗...(image-717c8e-1697555899201)]

從 Android14 開始犹菇,允許使用此權(quán)限的應(yīng)用程序僅限于那些只提供通話和警報(bào)的應(yīng)用德迹。對(duì)于其他應(yīng)用,Google Play 商店會(huì)撤銷它們默認(rèn)的 USE_FULL_SCREEN_INTENT 權(quán)限揭芍。

可以使用新的 API NotificationManager.canUseFullScreenIntent() 檢查應(yīng)用是否有權(quán)限胳搞;如果沒有,可以用新的 ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT 來啟動(dòng)用戶可以授予該權(quán)限的設(shè)置頁面。

奇怪的是我在 Android14 官方的虛擬機(jī)上并沒有打開通知成功肌毅,更不用說打開全屏通知了筷转。不過確實(shí)可以打開設(shè)置全屏通知權(quán)限開關(guān)的頁面,如下是全屏通知權(quán)限設(shè)置圖及主要相關(guān)代碼:

[圖片上傳失敗...(image-bf5990-1697555899201)]

// code 4
val notificationBuilder = NotificationCompat.Builder(requireContext())
    .setSmallIcon(R.drawable.ic_lock_idle_alarm)
    .setContentTitle("Notification Title")
    .setContentText("Notification text")
// 創(chuàng)建一個(gè)PendingIntent,點(diǎn)擊Notification時(shí)打開指定頁面
val intent = Intent(context, NotificationFullActivity::class.java)
val fullScreenIntent =
    PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE)
    notificationBuilder.setFullScreenIntent(fullScreenIntent, true)  // 打開全屏通知
//            notificationBuilder.setContentIntent(fullScreenIntent)  // 打開普通頁面

val notificationManager =
    requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Android 8.0 Oreo以上需要設(shè)置通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    val channelId = "your_channel_id"
    val channelName: CharSequence = "Your Channel Name"
    val importance = NotificationManager.IMPORTANCE_HIGH
    val channel = NotificationChannel(channelId, channelName, importance)
    channel.description = "Channel description"
    notificationManager.createNotificationChannel(channel)
    notificationBuilder.setChannelId(channelId)
}
notificationManager.notify(5, notificationBuilder.build())
if (notificationManager.canUseFullScreenIntent()) {
    notificationManager.notify(5, notificationBuilder.build())
} else {
    // 打開設(shè)置頁
    val intent = Intent(Settings.ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT)
    intent.data = Uri.fromParts("package", requireActivity().packageName, null)
    startActivity(intent)
}

如果哪位大佬在 Android14 設(shè)備上成功地打開了全屏通知悬而,麻煩交流一下呜舒,謝謝。

小結(jié):大部分 App 用不上這個(gè)全屏通知功能笨奠,個(gè)人覺得并不是很重要袭蝗。。般婆。

5.3 關(guān)于不可關(guān)閉通知用戶體驗(yàn)方式的變更

如果應(yīng)用向用戶顯示不可關(guān)閉的前臺(tái)通知的話需要注意:Android14 中允許用戶關(guān)閉此類通知到腥。即之前通過 Notification.Builder#setOngoing(true)NotificationCompat.Builder#setOngoing(true) 設(shè)置 Notification.FLAG_ONGOING_EVENT 來阻止用戶關(guān)閉前臺(tái)通知的應(yīng)用要小心了。FLAG_ONGOING_EVENT 的行為已發(fā)生變化腺兴,用戶在 Android14 上可以關(guān)閉此類通知左电。

以下情況,此類通知仍不可關(guān)閉:
1)當(dāng)手機(jī)處于鎖定狀態(tài)時(shí)页响;
2)如果用戶選擇全部清除通知操作(有助于防止意外關(guān)閉)篓足;

此外,下列的幾種情況并沒有變更:
1)使用 CallStyle 創(chuàng)建的通知闰蚕,即來電通知的樣式栈拖;
2)設(shè)備策略控制器(DPC)和針對(duì)企業(yè)的支持包;

小結(jié):Android 的通知管理只會(huì)越來越嚴(yán)格没陡,早就應(yīng)該管管了涩哟。其實(shí)就算 Android14 手機(jī)上沒有這個(gè)功能,目前絕大多數(shù)手機(jī)廠商已經(jīng)都可以禁止 App 彈出通知了盼玄,所以這個(gè)也沒啥贴彼。。埃儿。

以上就是本篇的所有內(nèi)容器仗,主要根據(jù)官方文檔自己實(shí)踐操作了一番,可以看出童番,現(xiàn)有的 App 如果直接安裝到 Android14 的手機(jī)上精钮,并不會(huì)有太多的問題,許多東西其實(shí)并不用另外處理剃斧,當(dāng)然建議還是根據(jù)本篇內(nèi)容查漏補(bǔ)缺比較好轨香。如果還想了解 targetSdkVersion 升級(jí)到 34(Android14)還需要注意哪些內(nèi)容,歡迎關(guān)注我幼东,咱們下篇見臂容!

更多內(nèi)容科雳,歡迎關(guān)注工種號(hào):修之竹
或者查看 修之竹的 Android 專輯

贊人玫瑰,手留余香策橘!歡迎點(diǎn)贊炸渡、轉(zhuǎn)發(fā)~ 轉(zhuǎn)發(fā)請(qǐng)注明出處~

參考文獻(xiàn)

  1. Android 14 官方文檔 https://developer.android.com/about/versions/14
  2. https://developer.android.google.cn/about/versions/14/behavior-changes-all?hl=zh-cn
  3. https://developer.android.google.cn/about/versions/14/changes/schedule-exact-alarms?hl=zh-cn
  4. https://developer.android.google.cn/guide/components/activities/process-lifecycle?hl=zh-cn
  5. https://developer.android.google.cn/about/versions/14/behavior-changes-14
  6. Android 14 快速適配要點(diǎn); 戀貓de小郭; https://juejin.cn/post/7231835495557890106?searchId=202307240025039D8229C74EA62159077B
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末娜亿,一起剝皮案震驚了整個(gè)濱河市丽已,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌买决,老刑警劉巖沛婴,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異督赤,居然都是意外死亡嘁灯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門躲舌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丑婿,“玉大人,你說我怎么就攤上這事没卸「睿” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵约计,是天一觀的道長诀拭。 經(jīng)常有香客問我,道長煤蚌,這世上最難降的妖魔是什么耕挨? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮尉桩,結(jié)果婚禮上筒占,老公的妹妹穿的比我還像新娘。我一直安慰自己蜘犁,他們只是感情好翰苫,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沽瘦,像睡著了一般革骨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上析恋,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天良哲,我揣著相機(jī)與錄音,去河邊找鬼助隧。 笑死筑凫,一個(gè)胖子當(dāng)著我的面吹牛滑沧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巍实,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼滓技,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了棚潦?” 一聲冷哼從身側(cè)響起令漂,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎丸边,沒想到半個(gè)月后叠必,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妹窖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年纬朝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骄呼。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡共苛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜓萄,到底是詐尸還是另有隱情隅茎,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布绕德,位于F島的核電站患膛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏耻蛇。R本人自食惡果不足惜踪蹬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望臣咖。 院中可真熱鬧跃捣,春花似錦、人聲如沸夺蛇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刁赦。三九已至娶聘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間甚脉,已是汗流浹背丸升。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牺氨,地道東北人狡耻。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓墩剖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親夷狰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岭皂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容