第七章(通知——Notification,适配Android 8.0奥利奥的NotificationChannel)

通知(Notification)

简介:

通知是Android系统中一个有特色的功能,当某个程序希望向用户发出一些提示信息,而该应用程序又不在前台运行,就可以借助通知来实现,发出一条通知后,手机状态栏中就会显示一个通知的图标,下拉状态栏后就能看到通知的详细内容。

通知的基本使用方法

通知的用法是比较灵活的既可以在活动里创建,可以在广播接收器里创建,也可以在服务里创建,下面看具体使用步骤

  1. 无论在哪里创建通知,整体的步骤都是相同的,首先需要一个NotificationManager来对通知进行管理,可以调用Context的getSystemService()方法获得,该方法接收一个字符串参数用于确定获取系统的哪一个服务,这里传入Context.NOTIFICATION_SERVICE就行了

  NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);//需要一个NotificationManager来对通知进行管理
  1. 接下来需要使用一个Builder构造器来创建Notification对象,但是Android的每一个版本都对部分功能有或多或少的修改,所以就得使用support中提供的兼容API。support-v4库中提供了一个NotificationCompat类,使用这个类的构造器来创建Notification对象就能在所有的Android版本上兼容了
Notification notification = new NotificationCompat.Builder(this, "chat")//用NotificationCompat是为了兼容SDK>=26的Android版本

这里要传入一个ChannelId,目的是为了兼容SDKVersion大于等于26的系统,因为Android从26以后就引入了通知渠道。那什么是通知渠道呢,就是每条通知都要属于一个通知渠道,每个App都可以自由地创建多个通知渠道,这些通知渠道的控制权都在用户的手上,用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。
当你的targetSDKVersion小于26时NotificationCompat.Builder(this),是可用的,但是当你的targetSDKVersion大于等于26时就会显示这个方法已经过时。所以我们一开始就要去适配,判断当前Version是什么版本,关于channelId我们待会再讲。

  1. 这个Builder的一系列set方法返回的都是这个Builder所以可以一连串地进行多项设置,然后调用build方法创建Notification对象,最后让通知管理器去发出这条广播,调用它的notify方法,第一个参数是id,要保证每个通知所指定的id都是不同的。
NotificationManager manager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Notification notification= new NotificationCompat.Builder(this,"chat")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setWhen(System.currentTimeMillis())//指定通知被创建的时间
                .setContentTitle("收到一条聊天消息")
                .setContentText("今晚吃什么")
                .setNumber(1)//设置角标的数量
                .setPriority(NotificationCompat.PRIORITY_MAX)//设置重要程度,这里设置的是最大值,会立即出//现在屏幕顶部,还有其他的值可以自行查看
                .build();
        manager.notify(1,notification);

这样我们的通知就发出了。

  1. 点击这个通知发现没反应,这涉及到一个新的概念PendingIntent,它与Intent类似,可以用于启动活动、服务以及发送广播。不同的是Intent倾向于立即去执行某个动作,而PendingIntent更倾向于在某个合适的实际去执行某个动作。可以将PendingIntent理解为延迟执行的Intent。PendingIntent提供了几个静态方法获取它的实例:getActivity()、getBroadcast()和getService()方法,这几个方法传的参数是相同的,第一个是Context,第二个一般用不到传0就行了,第三个传入的是Intent,我们通过这个Intent来构建PendingIntent的意图。第四个参数用于指定PendingIntent的行为,通常传入0就可以了。 然后在创建Notification的时候调用setContentIntent方法将PendingIntent传进去就可以了。
    下面我们实现点击这条通知打开AnotherActivity,并传递一条值给AnotherActivity
    MainActivity
 public void sendChatMsg(View view) {
        NotificationManager manager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        Intent intent=new Intent(this,AnotherActivity.class);
        intent.putExtra("data","今晚吃什么");
        PendingIntent pi=PendingIntent.getActivity(this,0,intent,0);
        Notification notification= new NotificationCompat.Builder(this,"chat")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setWhen(System.currentTimeMillis())
                .setContentTitle("收到一条聊天消息")
                .setContentText("今晚吃什么")
                .setNumber(1)//设置角标的数量
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setContentIntent(pi)
                .build();
        manager.notify(1,notification);

    }

AnotherActivity

public class AnotherActivity extends AppCompatActivity {
private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_another);
        textView=(TextView)findViewById(R.id.textview);
        Intent intent=getIntent();
        String data=intent.getStringExtra("data");
        textView.setText(data);
    }
}
image

以上代码能在8.0以下的版本运行,不能再8.0及以上的版本运行,因为我们根本没创建NotificationChannel,而8.0以下的不需要通知渠道,所以上面的那个NotificationCompat.Builder(this, "chat")所传入的chat是无效的。

  1. 下面就讲NotificationChannel 的使用,及适配8.0及以上版本的系统使用通知。
    我们只要在onCreate方法里面去判断当前的版本,如果大于26就创建两个对应的NotificationChannel就行了
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
            String channelId="chat";
            String channelName="聊天信息";
            int importance= NotificationManager.IMPORTANCE_HIGH;
            createNotificationChannel(channelId,channelName,importance);
            channelId="subscribe";
            channelName="订阅消息";
            importance=NotificationManager.IMPORTANCE_DEFAULT;
            createNotificationChannel(channelId,channelName,importance);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void createNotificationChannel(String channelId, String channelName, int importance) {
        NotificationChannel channel=new NotificationChannel(channelId,channelName,importance);
        channel.setShowBadge(true);//设置角标,默认是true
        NotificationManager manager=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        manager.createNotificationChannel(channel);
    }
    

NotificationChannel的构造传三个参数,第一个是ChannelId,第二个是通知渠道的名字,第三个是重要程度参数,这样创建了NotificationChannel之后就能在8.0及以上的版本上运行了。

  1. 由于所有的控制权都在用户手上,假如用户把通知渠道关闭了怎么办呢,我们一定要确保通知渠道打开了
  public void sendChatMsg(View view) {
        NotificationManager manager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
            NotificationChannel channel=manager.getNotificationChannel("chat");//因为是NotificationManager创建的Channel,所以通过mannager能获取
            if(channel.getImportance()==NotificationManager.IMPORTANCE_NONE){
                Intent intent=new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
                intent.putExtra(Settings.EXTRA_APP_PACKAGE,getPackageName());
                intent.putExtra(Settings.EXTRA_CHANNEL_ID,channel.getId());
                startActivity(intent);
                Toast.makeText(this,"请手动打开权限",Toast.LENGTH_SHORT).show();
            }
        }
        Intent intent=new Intent(this,AnotherActivity.class);
        intent.putExtra("data","今晚吃什么");
        PendingIntent pi=PendingIntent.getActivity(this,0,intent,0);
        Notification notification= new NotificationCompat.Builder(this,"chat")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setWhen(System.currentTimeMillis())
                .setContentTitle("收到一条聊天消息")
                .setContentText("今晚吃什么")
                .setNumber(1)//设置角标的数量
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setContentIntent(pi)
                .build();
        manager.notify(1,notification);

    }

通知渠道一旦创建之后就不能再通过代码修改了。既然不能修改的话那还怎么管理呢?为此,Android赋予了开发者读取通知渠道配置的权限,如果我们的某个功能是必须按照指定要求来配置通知渠道才能使用的,那么就可以提示用户去手动更改通知渠道配置。
这里我们对sendChatMsg()方法进行了修改,通过getNotificationChannel()方法获取到了NotificationChannel对象,然后就可以读取该通知渠道下的所有配置了。这里我们判断如果通知渠道的importance等于IMPORTANCE_NONE,就说明用户将该渠道的通知给关闭了,这时会跳转到通知的设置界面提醒用户手动打开。

image

  1. 当然开发者也可以删除通知渠道
       NotificationChannel channel=new NotificationChannel(channelId,channelName,importance);
        channel.setShowBadge(true);//默认是true
        NotificationManager manager=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        manager.createNotificationChannel(channel);
        manager.deleteNotificationChannel("subscribe");//传入channelId

除此之外NotificationCompat.Builder中提供了很丰富的API让创建出更多的通知效果自己慢慢去探索吧。

原创文章 43 获赞 6 访问量 786

猜你喜欢

转载自blog.csdn.net/qq_34088913/article/details/105946750