通知既可以在Activity也可以在BroadcastReceiver中创建,但是一般只有当程序进入到后台的时候才需要使用通知。故而在Activity中创建通知比较少见,一般在BroadcastReceiver或者Service中创建。

使用通知需要得到Notification对象,在AndroidX库中提供了NotificationCompat类的构造器来构建Notification对象。即:

new NotificationCompat.Builder(@NonNull Context context, @NonNull String channelId);

由于每个应用程序都希望自己有更高的打开率,故而大家都想办法来通知用户,以博取更高的使用率。但是,这样就会使用户手机的状态栏被各种通知信息堆满。

故而在Android 8.0(API Level 26)开始引入了通知渠道的概念。

也就是说,每个通知都要有一个对应的渠道。每个应用程序都可以自由地创建当前应用有哪些渠道,但是这些渠道的控制权掌握在用户手中。用户可以自由的抉择是否需要关闭这个渠道。

在上面使用NotificationCompatBuilder构造器来创建Notification对象的API中我们看见第二个参数为字符串类型的channelId,也即是需要指定渠道ID,这个ID需要和我们在创建通知的时候指定的渠道ID相匹配才行。

1. Android 8.0之前创建通知方式和Android 8.0之后创建通知方式案例

也就是说,我们需要创建对应的通知渠道。比如:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // >= 26
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            String channelId = "weizu"; // 通道ID
            // 1. 创建通知管理器
            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationChannel channel = new NotificationChannel(channelId, "simple test", 
            				NotificationManager.IMPORTANCE_DEFAULT);
            manager.createNotificationChannel(channel);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, channelId);
            // 2. 创建通知(标题、内容、图标)
            Notification notification = builder.setContentTitle("This is the title.")
                    .setContentText("This is the content.")
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), 
                    			R.drawable.ic_launcher_foreground))
                    .build();
            // 3. 发送通知
            manager.notify(1, notification);
        }else{
            // 1. 创建通知管理器
            NotificationManager manager = (NotificationManager) getApplicationContext()
            						.getSystemService(Context.NOTIFICATION_SERVICE);
            // 2. 创建通知(标题、内容、图标)
            NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
            Notification notification = builder.setContentTitle("This is the title.")
                    .setContentText("This is the content.")
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), 
                    				R.drawable.ic_launcher_foreground))
                    .build();

            // 3. 发送通知
            manager.notify(1, notification);
        }
    }
});

大致都可以分为三个步骤:
① 创建通知管理器NotificationManager对象;在API level 26之后,需要指定通道channelId来创建通知管理器对象。
② 使用NotificationCompat.Builder来实例化builder实例,进而得到Notification实例;
③ 使用通知管理器发送通知;

android 开发 通知移除通知角标 android顶部通知_Android

2. 响应通知

如果我们希望在点击通知的时候有相应的反应,那么我们需要使用PendingIntent
PendingIntentIntent都可以用来启动ActivityService和广播等,不同之处在于PendingIntent倾向于在某个合适的时机执行某个动作,而Intent是立即执行。所以可以将PendingIntent理解为延迟执行的Intent。主要用于闹钟、通知、桌面部件等

builder建造Notification的时候,可以使用setContentIntent(PendingIntent)来关联一个PendingIntent对象,即:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
    String channelId = "weizu"; // 通道ID
    // 1. 创建通知管理器
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    NotificationChannel channel = new NotificationChannel(channelId, "simple test", NotificationManager.IMPORTANCE_DEFAULT);
    manager.createNotificationChannel(channel);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, channelId);
    // 2. 创建PendingInent
    Intent intent = new Intent(MainActivity.this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this,
            0, intent, 0);
    // 3. 创建通知(标题、内容、图标)
    Notification notification = builder.setContentTitle("This is the title.")
            .setContentText("This is the content.")
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground))
            .setContentIntent(pendingIntent)
            .build();
    // 4. 发送通知
    manager.notify(1, notification);
}

对于PendingIntent实例的获取有三种方法,分别对应Activity、广播和Service

  • PendingIntent.getService(Context context, int requestCode, Intent intent, int flags);
  • PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags);
  • PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags);

Notification中关联了一个PendingIntent用于延迟执行。

可以发现在点击后,通知并没有消失,我们需要添加相应的代码。有两种方式:

  • builder的时候使用setAutoCancel(true);
  • 使用manager对象的cancel(通知id)方法;
Notification notification = builder.setContentTitle("This is the title.")
        .setContentText("This is the content.")
        .setSmallIcon(R.drawable.ic_launcher_background)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), 	
        					R.drawable.ic_launcher_foreground))
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)  // here
        .build();

或者在设置的启动的ActivityonCreate方法中使用:

NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(1); // id

指定通知的ID即可取消显示。

3. 设置通知样式

3.1 设置通知紧急程度

在创建NotificationChannel的时候,可以指定紧急程度,比如:

NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(channelId, "simple test",
        	NotificationManager.IMPORTANCE_HIGH);

这里我们指定为IMPORTANCE_HIGH:

android 开发 通知移除通知角标 android顶部通知_android 开发 通知移除通知角标_02


一共五个等级。

3.2 设置通知震动

Notification notification = builder.setContentTitle("This is the title.")
        .setContentText("This is the content.")
        .setSmallIcon(R.drawable.ic_launcher_background)
        .setContentIntent(pendingIntent)
        .setVibrate(new long[]{100, 200, 300, 400}) // 静止时间,震动时长,依次类推
        .setAutoCancel(true)
        .build();

Thanks

  • 第一行代码