Notification 總結

Notification

Notification 能干什么供屉,那些設計是和Notification相關的讳侨;這里直接從官網(wǎng)取圖,直接看圖奏属;

notification statues bar 提示

swipe down show notifacation detail

heads-up notification

Lock screen
App icon badge
INBOX_STYLE
BIG_PICTURE_STYLE
MESSAGING_STYLE
A notification with basic details 一般Notification的樣式
通過setStyle方法修改了style的樣式可能就是這樣子的.png

可以直接回復消息跨跨,快捷回復等;

針對一般Notification的樣式
The most common parts of a notification are indicated in figure 7 as follows:

  1. Small icon: This is required and set with setSmallIcon().
  2. App name: This is provided by the system.
  3. Time stamp: This is provided by the system but you can override with setWhen() or hide it with setShowWhen(false).
  4. Large icon: This is optional (usually used only for contact photos; do not use it for your app icon) and set withsetLargeIcon().
  5. Title: This is optional and set with setContentTitle().
  6. Text: This is optional and set with setContentText().

setStyle() 抽象類Style 有種實現(xiàn)類囱皿,分別是:
1:BigTextStyle 處理大量文案樣式勇婴;
2: MediaStyle 處理多媒體通知樣式;
3: DecoratedCustomViewStyle 自定義包裝樣式嘱腥;
4: NessagingStyle 消息樣式耕渴;
5: BigPictureStyle 展示大圖樣式;
6: InboxStyle 展示消息在同一個box的樣式齿兔;

Style 繼承結構

大概步驟:
// Main steps for building a BIG_TEXT_STYLE notification:
// 0. Get your data
// 1. Create/Retrieve Notification Channel for O and beyond devices (26+)
// 2. Build the BIG_TEXT_STYLE
// 3. Set up main Intent for notification
// 4. Create additional Actions for the Notification
// 5. Build and issue the notification

 // 根據(jù)id,取消對應的notifcation
 NotificationManagerCompat notificationManagerCompat =
                NotificationManagerCompat.from(getApplicationContext());
        notificationManagerCompat.cancel(MainActivity.NOTIFICATION_ID);

簡單使用

  1. Create/Retrieve Notification Channel for O and beyond devices (26+)(必須)
  2. Build the BIG_TEXT_STYLE(可選)
  3. Set up main Intent for notification(可選)
  4. Create additional Actions for the Notification(可選)
  5. Build and issue the notification(必須)

下面是具體代碼 來著Google 官方demo

/*
     * Generates a BIG_TEXT_STYLE Notification that supports both phone/tablet and wear. For devices
     * on API level 16 (4.1.x - Jelly Bean) and after, displays BIG_TEXT_STYLE. Otherwise, displays
     * a basic notification.
     */
    private void generateBigTextStyleNotification() {
 
        // Main steps for building a BIG_TEXT_STYLE notification:
        //      0. Get your data
        //      1. Create/Retrieve Notification Channel for O and beyond devices (26+)
        //      2. Build the BIG_TEXT_STYLE
        //      3. Set up main Intent for notification
        //      4. Create additional Actions for the Notification
        //      5. Build and issue the notification

        // 0. Get your data (everything unique per Notification). 
        //通過一個類將數(shù)據(jù)都封裝在這個類中橱脸,統(tǒng)一管理
        MockDatabase.BigTextStyleReminderAppData bigTextStyleReminderAppData =
                MockDatabase.getBigTextStyleData();

        // 1. Create/Retrieve Notification Channel for O and beyond devices (26+).
        //  在Android O 之后非常必要的操作,這里有個小細節(jié)關于在Kotlin中創(chuàng)建channel,
        String notificationChannelId =
                NotificationUtil.createNotificationChannel(this, bigTextStyleReminderAppData);


        // 2. Build the BIG_TEXT_STYLE.
        //  使用style 樣式 
        BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle()
                // Overrides ContentText in the big form of the template.
                // 如果點擊展開消息內容的箭頭:bigText的內容會覆蓋在notification中設置的設置的內容(ContentText)分苇;
                .bigText(bigTextStyleReminderAppData.getBigText())
                // Overrides ContentTitle in the big form of the template.
                // 如果點擊展開消息內容的箭頭:bigContentTitle的內容會覆蓋notification中設置的內容(ContentTitle)
                .setBigContentTitle(bigTextStyleReminderAppData.getBigContentTitle())
                // Summary line after the detail section in the big form of the template.
                // Note: To improve readability, don't overload the user with info. If Summary Text
                // doesn't add critical information, you should skip it.
                // 設置總結消息提示 :<SummaryText 總結> 內容不能過長添诉,太長也會省略為 xxx.xxxxx... 的形式
                .setSummaryText(bigTextStyleReminderAppData.getSummaryText());


        // 3. Set up main Intent for notification 
        // (給PendingIntent 綁定的真正 Intent )這里可以使Activity 或者 Service,
        //  但是綁定PendingIntent 時需要注意API 的調用(具體事例中有)
        //  務必記得 單打開對應的Activity 或者 Service ,有必要執(zhí)行cancel 掉對應的notification
       
        Intent notifyIntent = new Intent(this, BigTextMainActivity.class);

        // When creating your Intent, you need to take into account the back state, i.e., what
        // happens after your Activity launches and the user presses the back button.

        // There are two options:
        //      1. Regular activity - You're starting an Activity that's part of the application's
        //      normal workflow.

        //      2. Special activity - The user only sees this Activity if it's started from a
        //      notification. In a sense, the Activity extends the notification by providing
        //      information that would be hard to display in the notification itself.

        // For the BIG_TEXT_STYLE notification, we will consider the activity launched by the main
        // Intent as a special activity, so we will follow option 2.

        // For an example of option 1, check either the MESSAGING_STYLE or BIG_PICTURE_STYLE
        // examples.

        // For more information, check out our dev article:
        // https://developer.android.com/training/notify-user/navigation.html

        // Sets the Activity to start in a new, empty task
        notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

        PendingIntent notifyPendingIntent =
                PendingIntent.getActivity(
                        this,
                        0,
                        notifyIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );


        // 4. Create additional Actions (Intents) for the Notification.
        // 創(chuàng)建 Actions (Intents)  效果直接看圖

        // In our case, we create two additional actions: a Snooze action and a Dismiss action.
        // Snooze Action.
        Intent snoozeIntent = new Intent(this, BigTextIntentService.class);
        snoozeIntent.setAction(BigTextIntentService.ACTION_SNOOZE);

        PendingIntent snoozePendingIntent = PendingIntent.getService(this, 0, snoozeIntent, 0);
        NotificationCompat.Action snoozeAction =
                new NotificationCompat.Action.Builder(
                        R.drawable.ic_alarm_white_48dp,
                        "Snooze",
                        snoozePendingIntent)
                        .build();


        // Dismiss Action.
        Intent dismissIntent = new Intent(this, BigTextIntentService.class);
        dismissIntent.setAction(BigTextIntentService.ACTION_DISMISS);

        PendingIntent dismissPendingIntent = PendingIntent.getService(this, 0, dismissIntent, 0);
        NotificationCompat.Action dismissAction =
                new NotificationCompat.Action.Builder(
                        R.drawable.ic_cancel_white_48dp,
                        "Dismiss",
                        dismissPendingIntent)
                        .build();


        // 5. Build and issue the notification.

        // Because we want this to be a new notification (not updating a previous notification), we
        // create a new Builder. Later, we use the same global builder to get back the notification
        // we built here for the snooze action, that is, canceling the notification and relaunching
        // it several seconds later.

        // Notification Channel Id is ignored for Android pre O (26).
        NotificationCompat.Builder notificationCompatBuilder =
                new NotificationCompat.Builder(
                        getApplicationContext(), notificationChannelId);

        GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder);

        Notification notification = notificationCompatBuilder
                // BIG_TEXT_STYLE sets title and content for API 16 (4.1 and after).
                .setStyle(bigTextStyle) // 設置樣式
                // Title for API <16 (4.0 and below) devices.
                .setContentTitle(bigTextStyleReminderAppData.getContentTitle())  //設置未展開時的標題
                // Content for API <24 (7.0 and below) devices.
                .setContentText(bigTextStyleReminderAppData.getContentText()) // 設置未展開時的內容
                .setSmallIcon(R.drawable.ic_launcher) // 設置頂部smallIcon
                .setLargeIcon(BitmapFactory.decodeResource( // 設置右側LargeIcon 注意顏色,白色可就看不到了
                        getResources(),
                        R.drawable.ic_action_name1))
                .setContentIntent(notifyPendingIntent)
                .setDefaults(NotificationCompat.DEFAULT_ALL) // 設置聲音 医寿,震動栏赴,默認等
                // Set primary color (important for Wear 2.0 Notifications). 這個顏色會同步到smallIcon , action 字體顏色
                .setColor(ContextCompat.getColor(getApplicationContext(), R.color.colorAccent))

                // SIDE NOTE: Auto-bundling is enabled for 4 or more notifications on API 24+ (N+)
                // devices and all Wear devices. If you have more than one notification and
                // you prefer a different summary notification, set a group key and create a
                // summary notification via
//                 .setGroupSummary(true)
//                 .setGroup(GROUP_KEY_YOUR_NAME_HERE)

                .setCategory(Notification.CATEGORY_MESSAGE) // 設置消息類型

                // Sets priority for 25 and below. For 26 and above, 'priority' is deprecated for
                // 'importance' which is set in the NotificationChannel. The integers representing
                // 'priority' are different from 'importance', so make sure you don't mix them.
                .setPriority(bigTextStyleReminderAppData.getPriority())

                // Sets lock-screen visibility for 25 and below. For 26 and above, lock screen
                // visibility is set in the NotificationChannel.
                .setVisibility(bigTextStyleReminderAppData.getChannelLockscreenVisibility())
.setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL) // 是否展示在桌面icon 上展示徽章 badge
                // Adds additional actions specified above.
                .addAction(snoozeAction)
                .addAction(dismissAction)

                .build();

        mNotificationManagerCompat.notify(NOTIFICATION_ID, notification);
    }
樣例圖

1:應用名 和 時間之間的內容是總結內容,SummaryText;
2: setColor 會影響圖標顏色靖秩,和 Actions 文字顏色须眷,但是不會影響狀態(tài)欄的圖標;
3: 當有消息時沟突,8.0系統(tǒng) 桌面icon 邊上的可以控制展示不展示

val id = "my_channel_01"
val name = getString(R.string.channel_name)
val descriptionText = getString(R.string.channel_description)
val importance = NotificationManager.IMPORTANCE_LOW
val mChannel = NotificationChannel(id, name, importance).apply {
    description = descriptionText
    setShowBadge(false) //關鍵代碼
}
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel)

Note :

1:Kotlin 的 創(chuàng)建NotificationCompat.Builder時花颗;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            channelID = "channelID"
            var channel = NotificationChannel(channelID, "this is name ", NotificationManager.IMPORTANCE_DEFAULT)
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }

        if (channelID == null) {
            //注意這里,如果channelID 為可空類型時惠拭,
            //不能使用NotificationCompat.Builder(this, channelID) 所以如此處理
            builder = NotificationCompat.Builder(this)
        } else {
            builder = NotificationCompat.Builder(this, channelID!!) 
        }

2: Android 8.0 之后需要創(chuàng)建Channel捎稚,創(chuàng)建Notification需要ChannelID;

// 代碼來著Google dome
 public static String createNotificationChannel(
            Context context,
            MockDatabase.MockNotificationData mockNotificationData) {

        // NotificationChannels are required for Notifications on O (API 26) and above.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            // The id of the channel.
            String channelId = mockNotificationData.getChannelId();

            // The user-visible name of the channel.
            CharSequence channelName = mockNotificationData.getChannelName();
            // The user-visible description of the channel.
            String channelDescription = mockNotificationData.getChannelDescription();
            //NotificationManager.IMPORTANCE_MAX;IMPORTANCE_HIGH;IMPORTANCE_DEFAULT;      
//IMPORTANCE_LOW;IMPORTANCE_MIN;IMPORTANCE_NONE;IMPORTANCE_UNSPECIFIED;
            int channelImportance = mockNotificationData.getChannelImportance();
            boolean channelEnableVibrate = mockNotificationData.isChannelEnableVibrate();
            int channelLockscreenVisibility =
                    mockNotificationData.getChannelLockscreenVisibility();

            // Initializes NotificationChannel.  構造(ID, 名字,重要程度)
            NotificationChannel notificationChannel =
                    new NotificationChannel(channelId, channelName, channelImportance);
            notificationChannel.setDescription(channelDescription);
            notificationChannel.enableVibration(channelEnableVibrate);
           // NotificationCompat.VISIBILITY_PRIVATE;VISIBILITY_PRIVATE;VISIBILITY_PUBLIC
            notificationChannel.setLockscreenVisibility(channelLockscreenVisibility);

            // 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 channelId;
        } else {
            // Returns null for pre-O (26) devices.
            return null;
        }
    }

3: PendingIntent中的綁定的intent 可以Activity是Service(比如 IntentService 的子類)今野;

從上面貼的示例代碼也可以看出葡公;
PendingIntent snoozePendingIntent = PendingIntent.getService(this, 0, snoozeIntent, 0);

PendingIntent notifyPendingIntent =
                PendingIntent.getActivity(
                        this,
                        0,
                        notifyIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );   

但是:按照我的理解,一般setContentIntent 綁定的是Acitivity ,addAction 綁定的是Service

4:取消notification記得使用条霜;不管是在activity 還是service

NotificationManagerCompat notificationManagerCompat =
                NotificationManagerCompat.from(getApplicationContext());
         // 根據(jù)Notification_ID 取消指定的Notification
        notificationManagerCompat.cancel(MainActivity.NOTIFICATION_ID);

官方刪除Notification如下:

  • The user dismisses the notification.
  • The user clicks the notification, and you called setAutoCancel() when you created the notification.
  • You call cancel() for a specific notification ID. This method also deletes ongoing notifications.
  • You call cancelAll(), which removes all of the notifications you previously issued.
  • If you set a timeout when creating a notification using setTimeoutAfter(), the system cancels the notification after the specified duration elapses. If required, you can cancel a notification before the specified timeout duration elapses.

Heads-up 效果

抬頭通知會在您的應用發(fā)出通知時出現(xiàn)催什,并在片刻后消失,但仍會像往常一樣在通知抽屜中顯示宰睡。

可能觸發(fā)抬頭通知的示例條件包括:

  • 用戶的活動處于全屏模式(應用程序使用 fullScreenIntent)蒲凶。
  • 該通知具有高優(yōu)先級,并在運行Android 7.1(API級別25)及更低級別的設備上使用鈴聲或振動拆内。setDefaults(NotificationCompat.DEFAULT_ALL)
  • 通知渠道對運行Android 8.0(API級別26)及更高版本的設備具有高度重要性旋圆。setPriority 以及 NotificationChannel(channelId, channelName, channelImportance)

Actions 的相應

  // 4. Create additional Actions (Intents) for the Notification.

       // In our case, we create two additional actions: a Snooze action and a Dismiss action.
       // Snooze Action.
       Intent snoozeIntent = new Intent(this, BigTextIntentService.class);
       snoozeIntent.setAction(BigTextIntentService.ACTION_SNOOZE);

       PendingIntent snoozePendingIntent = PendingIntent.getService(this, 0, snoozeIntent, 0);
       NotificationCompat.Action snoozeAction =
               new NotificationCompat.Action.Builder(
                       R.drawable.ic_alarm_white_48dp,
                       "Snooze",
                       snoozePendingIntent)
                       .build();

BigTextIntentService

public class BigTextIntentService extends IntentService {

    private static final String TAG = "BigTextService";

    public static final String ACTION_DISMISS =
            "com.example.android.wearable.wear.wearnotifications.handlers.action.DISMISS";
    public static final String ACTION_SNOOZE =
            "com.example.android.wearable.wear.wearnotifications.handlers.action.SNOOZE";

    private static final long SNOOZE_TIME = TimeUnit.SECONDS.toMillis(5);

    public BigTextIntentService() {
        super("BigTextIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "onHandleIntent(): " + intent);

        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_DISMISS.equals(action)) {
                handleActionDismiss(); //cancleNotification
            } else if (ACTION_SNOOZE.equals(action)) {
                handleActionSnooze(); //發(fā)送Notification
            }
        }
    }
}

RemoteInuput 類似Reply的

 // Create the RemoteInput.
        String replyLabel = getString(R.string.reply_label);
        RemoteInput remoteInput =
                new RemoteInput.Builder(BigPictureSocialIntentService.EXTRA_COMMENT)
                        .setLabel(replyLabel)
                        // List of quick response choices for any wearables paired with the phone
                        .setChoices(bigPictureStyleSocialAppData.getPossiblePostResponses())
                        .build();

        // Pending intent =
        //      API <24 (M and below): activity so the lock-screen presents the auth challenge
        //      API 24+ (N and above): this should be a Service or BroadcastReceiver
        PendingIntent replyActionPendingIntent;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Intent intent = new Intent(this, BigPictureSocialIntentService.class);
            intent.setAction(BigPictureSocialIntentService.ACTION_COMMENT);
            replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0);

        } else {
            replyActionPendingIntent = mainPendingIntent;
        }

        NotificationCompat.Action replyAction =
                new NotificationCompat.Action.Builder(
                        R.drawable.ic_reply_white_18dp,
                        replyLabel,
                        replyActionPendingIntent)
                        .addRemoteInput(remoteInput)
                        .build();

// 最后addAction(replyAction) 到Notificationbuilder
BigPictureSocialIntentService 中獲取輸入的關鍵代碼
    /*
     * Extracts CharSequence created from the RemoteInput associated with the Notification.
     */
    private CharSequence getMessage(Intent intent) {
        Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
        if (remoteInput != null) {
            return remoteInput.getCharSequence(EXTRA_COMMENT);
        }
        return null;
    }

補充 Notes:

1:如果多個通道使用Heads-up效果 會導致失效;
2: Beginning with Android 8.1 (API level 27), apps cannot make a notification sound more than once per second. If your app posts multiple notifications in one second, they all appear as expected, but only the first notification per second makes a sound.
8.1 以后每秒只能發(fā)生一個Notification麸恍;

更多細節(jié)參考官網(wǎng)和官方Demo

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末灵巧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子抹沪,更是在濱河造成了極大的恐慌刻肄,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件融欧,死亡現(xiàn)場離奇詭異敏弃,居然都是意外死亡,警方通過查閱死者的電腦和手機噪馏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門麦到,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人欠肾,你說我怎么就攤上這事隅要。” “怎么了董济?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵步清,是天一觀的道長。 經常有香客問我虏肾,道長廓啊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任封豪,我火速辦了婚禮谴轮,結果婚禮上,老公的妹妹穿的比我還像新娘吹埠。我一直安慰自己第步,他們只是感情好疮装,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粘都,像睡著了一般廓推。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上翩隧,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天樊展,我揣著相機與錄音,去河邊找鬼堆生。 笑死专缠,一個胖子當著我的面吹牛,可吹牛的內容都是我干的淑仆。 我是一名探鬼主播涝婉,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蔗怠!你這毒婦竟也來了墩弯?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蟀淮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后钞澳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怠惶,經...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年轧粟,在試婚紗的時候發(fā)現(xiàn)自己被綠了策治。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡兰吟,死狀恐怖通惫,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情混蔼,我是刑警寧澤履腋,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站惭嚣,受9級特大地震影響遵湖,放射性物質發(fā)生泄漏。R本人自食惡果不足惜晚吞,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一延旧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧槽地,春花似錦迁沫、人聲如沸芦瘾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽近弟。三九已至,卻和暖如春牡整,著一層夾襖步出監(jiān)牢的瞬間藐吮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工逃贝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谣辞,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓沐扳,卻偏偏與公主長得像泥从,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沪摄,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內容