第七章(通知——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让创建出更多的通知效果自己慢慢去探索吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容