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);
    }

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PendingIntent 是 Android 系统提供的一个类,用于表示在未来某个时刻执行的 IntentPendingIntent 可以在应用程序的不同组件(如 Activity、Service、BroadcastReceiver)之间传递,并且可以在后台执行,即使应用程序已经退出或者设备进入睡眠状态。 PendingIntent 主要用于以下场景: 1. 触发操作:当用户点击通知或小部件时,可以使用 PendingIntent 启动一个 Activity、Service 或广播等来执行相应的操作。 2. 定时器:可以使用 PendingIntent 启动 AlarmManager 定时器,以在指定的时间或时间间隔后触发操作。 3. 操作链:可以使用 PendingIntent 将操作链接在一起,以便在后台执行多个操作。 PendingIntent 的用法包括以下步骤: 1. 创建一个 Intent 对象,用于描述要执行的操作,可以设置 Action、Data、Category、Extra 等属性。 2. 使用 PendingIntent 的静态方法 getActivity()、getService()、getBroadcast() 等创建一个 PendingIntent 对象,用于描述要执行的操作。 3. 将 PendingIntent 对象传递给其他组件,比如 Notification、Widget 等,以便在未来某个时刻触发操作。 4. 在指定的时刻或事件发生时,系统会自动启动 PendingIntent 对象所描述的操作,并且可以在后台执行。 需要注意的是,PendingIntent 对象是可以重复使用的,即多次启动同一个 PendingIntent 对象会执行相同的操作。如果要创建不同的 PendingIntent 对象,需要使用不同的请求码(requestCode)或设置不同的数据(setData())。 代码示例: ``` // 创建一个 Intent 对象,用于描述要执行的操作 Intent intent = new Intent(this, MainActivity.class); intent.putExtra("message", "Hello"); // 使用 PendingIntent 的静态方法 getBroadcast() 创建一个 PendingIntent 对象 PendingIntent pIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); // 将 PendingIntent 对象传递给 Notification,以便在未来某个时刻触发操作 NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setContentIntent(pIntent); // 在指定的时刻或事件发生时,系统会启动 PendingIntent 对象所描述的操作 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值