Android 8.0 Oreo 形为变更之 Notification Channels
最近(2018年11月15日)在上傳App升級包至Google Play時,遇到了如下問題:
即:當前App的Target API Level 為25(Android 7.1.1 Nougat),要求將App的Target API Level提升到26(Android 8.0 Oreo)或以上。
查閱資料發現,Google開發者在持續提高 Android 應用的安全性與性能一文中提到:
為了提升 App 安全性和性能,確保每個用戶都能夠獲取最佳體驗,探索和安裝自己喜歡的 App 和游戲,Google對Android 開發者提出了一些變更。從 2018 年下半年開始,Google Play 管理中心將要求 App 設定target?API Level為近期版本:
-
2018 年 8 月:新 App 需要將 target API 等級設定為 26(Android 8.0)或者更高
-
2018 年 11 月,現有 App 的更新包需要將 target API 等級設定為 26 或者更高
-
2019 年之后:每年 targetSdkVersion 會提出新的要求。Android 新版本系統發布一年內,App 的開發和更新都需要將 API 調整到相應或者更高等級。
現有但不再更新的 App 并不受影響。開發者可以自行選擇是否使用 minSdkVersion,依舊可以進行基于舊版本 Android 系統的 App 開發。
?
-
問題
為了能夠提交Google Play ,只得將App Target Level提升至26。然后打包、測試、提交市場。測試過程中發現無法接收到Push推送,并且是在Android8.0及以上的設備上無法接收到push,抓取到如下log:
11-15 19:01:05.794 1603 3283 E NotificationService: No Channel found for pkg=com.xxxxxxx.xxxxxx, channelId=null, id=1627843789, tag=null, opPkg=com.xxxxxxx.xxxxxx, callingUid=10719, userId=0, incomingUserId=0, notificationUid=10719, notification=Notification(channel=null pri=0 contentView=null vibrate=default sound=default defaults=0xffffffff flags=0x11 color=0x00000000 category=msg groupKey=com.xxxxxxxx.xxxxxx.notifygrp vis=PUBLIC)查看創建Notification的代碼,如下(Demo):
private void onLaunchNotificationBtnClick() {String textTitle = "This is Title";String textContent = "This is Content";//創建NotificationNotificationCompat.Builder builder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_launcher_foreground).setContentTitle(textTitle).setContentText(textContent).setPriority(NotificationCompat.PRIORITY_DEFAULT);//Launch NotificationNotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());notificationManagerCompat.notify(NOTIFICATION_ID, builder.build());}Log 如下:
11-17 16:06:51.670 13096-13096/com.example.cxc.fullscreendemo E/NotificationManager: notifyAsUser: tag=null, id=888, user=UserHandle{0} 11-17 16:06:51.678 1272-1875/? E/NotificationService: No Channel found for pkg=com.example.cxc.fullscreendemo, channelId=null, id=888, tag=null, opPkg=com.example.cxc.fullscreendemo, callingUid=10487, userId=0, incomingUserId=0, notificationUid=10487, notification=Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x0 color=0x00000000 vis=PRIVATE)關于Notification的介紹與使用可以參考: Notifications Overview
-
定位
參考 Android Developers?https://developer.android.com/guide/topics/ui/notifiers/notifications
Starting in Android 8.0 (API level 26), all notifications must be assigned to a channel or it will not appear. By categorizing notifications into channels, users can disable specific notification channels for your app (instead of disabling all your notifications), and users can control the visual and auditory options for each channel—all from the Android system settings (figure 11). Users can also long-press a notification to change behaviors for the associated channel.
即:從Android 8.0 (API level 26)開始,所有的notification必須關聯一個channel,否則將不會顯示。通過將Notification分到各個不同的Channel中,用戶可以禁掉App某個Channel中的通知(而不是禁止App的所有Notification),并且用戶可以在系統設置中控制各個Channel通知的形式,如是否有聲音。
關于Notification Channel的介紹及深入理解可以參考:Exploring Android O: Notification Channels
-
解決
先創建一個Notification Channel,然后將通知關聯到該Channel。
package com.example.cxc.fullscreendemo.notification;import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.os.Build;public class NotificationUtils {private static final String CHANEL_ID = "com.example.cxc.fullscreendeme.channelId";private static final String CHANEL_DESCRIPTION = "Channel描述";private static final String CHANEL_NAME = "Channel名稱";public static String createNotificationChannel(Context context) {// NotificationChannels are required for Notifications on O (API 26) and above.if (context != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// Initializes NotificationChannel.NotificationChannel notificationChannel =new NotificationChannel(CHANEL_ID,CHANEL_NAME,NotificationManager.IMPORTANCE_DEFAULT);notificationChannel.setDescription(CHANEL_DESCRIPTION);// Adds NotificationChannel to system. Attempting to create an existing notification// channel with its original values performs no operation, so it's safe to perform the// below sequence.NotificationManager notificationManager =(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);notificationManager.createNotificationChannel(notificationChannel);return CHANEL_ID;} else {// Returns null for pre-O (26) devices.return null;}} } private void onLaunchNotificationBtnClick() {String textTitle = "This is Title";String textContent = "This is Content";//創建Notification ChannelString channelId = NotificationUtils.createNotificationChannel(getApplicationContext());//創建Notification并與Channel關聯NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId).setSmallIcon(R.drawable.ic_launcher_foreground).setContentTitle(textTitle).setContentText(textContent).setPriority(NotificationCompat.PRIORITY_DEFAULT);//Launch NotificationNotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());notificationManagerCompat.notify(NOTIFICATION_ID, builder.build());}最后運行,可以正常顯示Notification:
關于每一個發布的Android版本,Android Developers上都對新功能及形為變更做了詳細的介紹,具體可以參考?Android Releases Versions.
?
最后,總結一下教訓,幸虧在提升target API Level至26后,測試發現了該問題,否則后果還是很嚴重的。2019年之后Google Play要求新發布或者更新的App必須是一年內發布的Android版本,未來可能更多的應用發布渠道(如應用寶)會跟進,所以提升targetSdkVersion勢在必行,也請各個應用開發者趕緊跟上步伐。
完整代碼請參考:https://github.com/cxcbupt/FullscreenDemo.git
References:
總結
以上是生活随笔為你收集整理的Android 8.0 Oreo 形为变更之 Notification Channels的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 持续提高 Android 应用的安全性与
- 下一篇: Java PECS