PendingIntent, Notification,broadcastReceiver使用遇到的坑

转载自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);
    }

你可能感兴趣的:(android)