Android 通知栏——Notification

    在 Android 开发中,通知栏是一个比较常见的功能,我们来看看如何来实现一些简单的通知栏。

    实现通知栏主要由两个类:Notification 和 NotificationManager,但是由于 API 版本的不同导致实现方式会有所不同,所以 Google 提供了 v4 包里面的 NotificationCompat 和 NotificationManagerCompat 来实现:

    先看一个最简单的通知栏:

// 简单通知
    private void setSimpleNoti(){
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        // 设置标题
        builder.setContentTitle("简单通知");
        // 设置内容
        builder.setContentText("通知内容");
        // 设置小图标,没有大图标时,小图标会放在大图标的位置
        builder.setSmallIcon(R.mipmap.ic_launcher);
        NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
        // tag 和 id 是为了用来区分 notification
        managerCompat.notify("NOTIFICATION",0101,builder.build());
    }

    这是一个最简单的通知栏,如果你要使用通知栏,这三个是必须填写的,那么如果是一个普通的通知栏需要什么东西呢?

// 普通通知
    private void setNormalNoti(){
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        // 设置标题
        builder.setContentTitle("普通通知");
        // 设置内容
        builder.setContentText("通知内容");
        builder.setSmallIcon(R.mipmap.ic_launcher);
        // 设置大图标
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));
        // 设置通知灯光(LIGHTS)、铃声(SOUND)、震动(VIBRATE)、(ALL 表示都设置)
        builder.setDefaults(Notification.DEFAULT_ALL);
        // 灯光三个参数,颜色(argb)、亮时间(毫秒)、暗时间(毫秒),灯光与设备有关
        builder.setLights(Color.RED,200,200);
        // 铃声,传入铃声的 Uri(可以本地或网上)我这没有铃声就不传了
        builder.setSound(Uri.parse(""));
        // 震动,传入一个 long 型数组,表示 停、震、停、震 ... (毫秒)
        builder.setVibrate(new long[]{0,200,200,200,200,200});
        NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
        managerCompat.notify("NOTIFICATION",0102,builder.build());
    }

    那么我们怎么给通知栏设置点击事件呢?因为通知栏已经不在这个 Activity 里了,我们设置平时使用的 Intent 就不行了,这个时候 Android 给我们提供了一个 PendingIntent,来看一下怎么使用: 

// 设置 pendingIntent 
    private PendingIntent setPendingIntent(String msg) {
        // 普通的 Intent,可以传值
        Intent intent = new Intent(NotificationActivity.this, NotificationActivity.class);
        intent.putExtra("notification", msg);
        // 获取 pendingIntent,传入四个参数,这些参数大家都能看懂,第四个是一些 Flag,表示你这个通知栏会怎么变化,一般使用这个
        return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    // 解析 Intent
    private void parseIntent() {
        String msg = getIntent().getStringExtra("notification");
        if (msg != null) {
            Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
        }
    }

    因为我们点击通知栏就打开这个 Activity,所以就在这个 Activity 解析 Intent 的值,接下来为两个通知栏设置 Intent:

        // 简单通知栏设置 Intent
        builder.setContentIntent(setPendingIntent("简单通知"));
        // 普通通知栏设置 Intent
        builder.setContentIntent(setPendingIntent("普通通知"));

    看一下效果图:


    不知道大家有没有发现一个问题,就是我们不管点击的普通通知栏还是简单通知栏,Toast 显示的都是普通通知,这是因为:系统在使用 PendingIntent 时,会先看你的 Intent 是否是同一个,如果是同一个就直接使用已经存在的 PendingIntent,所以我们需要给 Intent 设置过滤器,我们使用 intent.setAction() 就行:

intent.setAction("notification:"+msg);

    我们再来看看效果图:


    这样这个问题就不存在了。

    如果我们想要点击通知栏后就让通知栏消失或者强制消失,调用这个方法就行:

        // 通知栏点击后自动消失
        builder.setAutoCancel(true);
        // 强制消失,传入 tag 和 id
        managerCompat.cancel("notification",0101);

    上面我们看到,一般的通知栏是可以右滑删除的,那我们怎么让它右滑不能删除了:

// 后台运行,无法右滑删除
        builder.setOngoing(true);

进度条

    一般我们在下载文件时,还会用到通知栏来显示进度条:

// 进度条通知栏
    private void setProgress(){
        final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setContentTitle("源码下载");
        builder.setContentText("等待下载中...");
        builder.setSmallIcon(R.mipmap.ic_launcher);
        final NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
        managerCompat.notify("notification",0103,builder.build());
        // 使用子线程,模拟下载
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <= 100; i++) {
                    // 设置进度条,三个参数表示:进度条最大值、当前值、确定在干啥:false
                    builder.setProgress(100,i,false);
                    builder.setContentText("文件已下载:"+i+"%");
                    managerCompat.notify("notification",0103,builder.build());
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                builder.setContentText("文件下载完成");
                managerCompat.notify("notification",0103,builder.build());
            }
        }).start();
    }

    效果图:

Android 通知栏——Notification_第1张图片

    一般来说,我们会在通知栏添加一些按钮来进行一些操作,比如我们试一下:

// 设置按钮
    private void setButton(){
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setContentTitle("按钮测试");
        builder.setContentText("点一下按钮");
        builder.setSmallIcon(R.mipmap.ic_launcher);
        // 添加按钮,这三个参数相信大家都能明白
        builder.addAction(R.mipmap.ic_launcher,"按钮一",setPendingIntent("执行按钮1"));
        builder.addAction(R.mipmap.ic_launcher,"按钮二",setPendingIntent("执行按钮2"));
        NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
        managerCompat.notify("notification",0104,builder.build());
    }

     效果图:

Android 通知栏——Notification_第2张图片

    Android 6.0 以后还推出了悬浮通知栏:

// 悬浮通知栏,HIGH 或者 MAX 都可以
        builder.setDefaults(NotificationCompat.PRIORITY_HIGH);
        builder.setPriority(NotificationCompat.PRIORITY_HIGH);

    效果图:

Android 通知栏——Notification_第3张图片

    然而,对于我们的需求来说,有时候系统自带的通知栏是不够我们使用的,怎么办呢?我们就可以自定义通知栏:

// 自定义通知栏
    private void setCustomNoti(){
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        // 实例化 RemoteViews,传入包名和布局 id
        RemoteViews views = new RemoteViews(getPackageName(),R.layout.notification_view);
        // 改变布局的 Text 的属性,传入 id 和 属性,也可以设置颜色,字体大小等 
        views.setTextViewText(R.id.tv_custom_notification,"自定义通知栏");
        // 改变布局的图片,有不同的方法,可以传入 id、bitmap 等
        views.setImageViewResource(R.id.iv_custom_notification,R.mipmap.ic_launcher);
        // 设置点击事件,传入 id 和 PendingIntent
        views.setOnClickPendingIntent(R.id.btn_custom_notification_clean,setPendingIntent("自定义按钮"));
        // 设置 View
        builder.setContent(views);
        builder.setSmallIcon(R.mipmap.ic_launcher);
        NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
        managerCompat.notify("notification",0105,builder.build());
    }

    效果图:

    Android 通知栏——Notification_第4张图片

    注意:1. 自定义通知栏的 RemoteViews 的布局只支持一些简单控件和布局,FrameLayout、LinearLayout、RelativeLayout、AnalogClock、button、Chronometer、ImageButton、ImageView 、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper、ViewStub。不知道有没有写对,大家可以查一查,千万不要放一些不支持的布局或控件,或报错的。

     2. 上面设置的 PendingIntent,都是开启一个新的 Activity,也可以用来绑定服务等其它操作,大家不要被束缚了思想。

    3. Notification 还支持一些 Style,如:长文本、媒体等,可以直接实例化一个 Style:

android.support.v4.media.app.NotificationCompat.MediaStyle style = new android.support.v4.media.app.NotificationCompat.MediaStyle();
        NotificationCompat.BigTextStyle style1 = new NotificationCompat.BigTextStyle();
        builder.setStyle(style);

    这样就行,它会导致通知栏的一些布局有不一样的效果,大家可以试试,但是需要注意的是,这些 Style 需要不同的 API 版本支持,使用的时候需要小心,避免程序出错。

项目地址:源代码







你可能感兴趣的:(Android,小题)