PendingIntent, Notification,broadcastReceiver使用遇到的坑

原文链接:
https://www.itread01.com/content/1542816187.html

转载自https://www.itread01.com/content/1542816187.html

PendingIntent, Notification,broadcastReceiver使用遇到的坑

使用PendingIntent结合 alarmManager 传送定时广播,收到广播的时候显示notification的功能,遇到了好多坑。

先上程式码:

一、pendingIntent结合闹钟传送定时广播

 Intent intent = new Intent(KeyVaule.CLOCK_IN_ACTION_NAME);
        intent.putExtra(KeyName.SOURCE, KeyVaule.MANUAL_CLOCK_IN);
        intent.putExtra(KeyName.CARD_NO, cardNo);
        intent.putExtra(KeyName.TARGET_TIME, targetTime + "");

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ComponentName componentName = new ComponentName(context.getPackageName(),context.getPackageName() + ".receiver.AlarmReceiver");
            intent.setComponent(componentName);
        }

        //todo 问题:flag为PendingIntent.FLAG_UPDATE_CURRENT 可以更新发送intent的内容
        //todo 问题:requestcode 不变的话,最新的intent会覆蓋之前的
        PendingIntent pi = PendingIntent.getBroadcast(context, 3, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        //PendingIntent 和 闹钟 结合传送 定时广播
        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            am.setExact(AlarmManager.RTC_WAKEUP, targetTime, pi);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, targetTime, pi);
        }

二、广播接收器

public class AlarmReceiver extends BroadcastReceiver {

    private static final long TEN_HOUR = 10 * 60 * 60 * 1000;

    @Override
    public void onReceive(Context context, final Intent intent) {
        showNotification(context);

    }


 private void showNotification(Context context) {
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(System.currentTimeMillis());

        NotificationCompat.Builder builder;
        NotificationManager notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        String id = "channel_01";
        String name = "channel_name";

        if (notifManager == null) {
            notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            int importance = NotificationManager.IMPORTANCE_LOW;
            NotificationChannel mChannel = notifManager.getNotificationChannel(id);

            if (mChannel == null) {
                mChannel = new NotificationChannel(id, name, importance);
                mChannel.setDescription("");
                notifManager.createNotificationChannel(mChannel);
            }

            builder = new NotificationCompat.Builder(context, id);
            builder.setContentTitle("收到打卡闹钟")  // required
                    .setSmallIcon(R.mipmap.clock) // required
                    .setContentText("打卡时间:" + time)  // required
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setAutoCancel(true)
                    .setTicker("收到打卡闹钟");

        } else {
            builder = new NotificationCompat.Builder(context);
            builder.setContentTitle("收到打卡闹钟")                           // required
                    .setSmallIcon(R.mipmap.clock) // required
                    .setContentText("打卡时间:" + time)  // required
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setAutoCancel(true)
                    .setTicker("收到打卡闹钟")
                    .setPriority(Notification.PRIORITY_HIGH);
        }
        Notification notification = builder.build();
        notifManager.notify(111, notification);
    }


}

一、8.0以上传送普通广播必须指明receiver

8.0以上隐式广播限制

以前只要设定action隐式广播就可以接收到,8.0以上不可以了,需要指明接收器的包名。

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ComponentName componentName = new ComponentName(context.getPackageName(),context.getPackageName() + ".receiver.AlarmReceiver");
            intent.setComponent(componentName);
        }

二、PendingIntent的 requestcode 和flag 引数的影响

pendingintent 的requestcode和flag影响

pendingIntent结合闹钟 使用遇到的最大的问题是,如果把APPkill了,receiver就接收不到广播了!!!应该说闹钟到了,广播发送了,但是receiver被销毁了啊,接收不到广播了??求路过的大神给解释下!


// 获取 Broadcast 关联的 PendingIntent
PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)

// 获取 Activity 关联的 PendingIntent
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags, Bundle options)

// 获取 Service 关联的 PendingIntent
PendingIntent.getService(Context context, int requestCode, Intent intent, int flags)


1、使用alarmManager,通过PendingIntent向broadcastReceiver传递内容。
第二个引数requestCode相同的话后面的定时器会将前面的定时器"覆蓋"掉,只会启动最后一个定时器,
所以同一时间的定时器可以用同一个requestCode,不同时间的定时器用不同的requestCode。

2、使用notification,通过PendingIntent向Activity传递内容。
第二个引数requestCode不同,以及设定最后一个flags引数为PendingIntent.FLAG_UPDATE_CURRENT可以
保证每次点选notification进入activity,传的引数都是当前这个notification传过去的(Intent里附带
的引数)。如果requestCode相同,最后一个引数为PendingIntent.FLAG_UPDATE_CURRENT,那么所有未
点选的notification里的引数都会被更新为最后一个传过去的,也就是最新的。

flags的取值有四个:
FLAG_ONE_SHOT:获取的PendingIntent只能使用一次
FLAG_NO_CREATE:利用FLAG_NO_CREAT获取的PendingIntent,若描述的Intent不存在则返回NULL值
FLAG_CANCEL_CURRENT:如果描述的PendingIntent已经存在,则在产生新的Intent之前会先取消掉当前的
FLAG_UPDATE_CURRENT:能够新new一个 Intent

三、8.0以上使用notification必须要设定NotificationChannel

 private void showNotification(Context context) {
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(System.currentTimeMillis());

        NotificationCompat.Builder builder;
        NotificationManager notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        String id = "channel_01";
        String name = "channel_name";

        if (notifManager == null) {
            notifManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            int importance = NotificationManager.IMPORTANCE_LOW;
            NotificationChannel mChannel = notifManager.getNotificationChannel(id);

            if (mChannel == null) {
                mChannel = new NotificationChannel(id, name, importance);
                mChannel.setDescription("");
                notifManager.createNotificationChannel(mChannel);
            }

            builder = new NotificationCompat.Builder(context, id);
            builder.setContentTitle("收到闹钟")  // required
                    .setSmallIcon(R.mipmap.clock) // required
                    .setContentText("时间:" + time)  // required
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setAutoCancel(true)
                    .setTicker("收到闹钟");

        } else {
            builder = new NotificationCompat.Builder(context);
            builder.setContentTitle("收到闹钟")                           // required
                    .setSmallIcon(R.mipmap.clock) // required
                    .setContentText("时间:" + time)  // required
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setAutoCancel(true)
                    .setTicker("收到闹钟")
                    .setPriority(Notification.PRIORITY_HIGH);
        }
        Notification notification = builder.build();
        notifManager.notify(111, notification);
    }
点赞