美文网首页
Notification 总结

Notification 总结

作者: 老柯南 | 来源:发表于2019-03-03 22:13 被阅读0次

Notification

Notification 能干什么,那些设计是和Notification相关的;这里直接从官网取图,直接看图;

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 有种实现类,分别是:
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

 // 根据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). 
        //通过一个类将数据都封装在这个类中,统一管理
        MockDatabase.BigTextStyleReminderAppData bigTextStyleReminderAppData =
                MockDatabase.getBigTextStyleData();

        // 1. Create/Retrieve Notification Channel for O and beyond devices (26+).
        //  在Android O 之后非常必要的操作,这里有个小细节关于在Kotlin中创建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 ,有必要执行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.
        // 创建 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 文字颜色,但是不会影响状态栏的图标;
3: 当有消息时,8.0系统 桌面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 的 创建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 之后需要创建Channel,创建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());
         // 根据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 效果

抬头通知会在您的应用发出通知时出现,并在片刻后消失,但仍会像往常一样在通知抽屉中显示。

可能触发抬头通知的示例条件包括:

  • 用户的活动处于全屏模式(应用程序使用 fullScreenIntent)。
  • 该通知具有高优先级,并在运行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(); //发送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 以后每秒只能发生一个Notification;

更多细节参考官网和官方Demo

相关文章

网友评论

      本文标题:Notification 总结

      本文链接:https://www.haomeiwen.com/subject/njcgyqtx.html