最近作业里面有一个需求:在每一天的固定时间点之后用户第一次解锁时进行消息推送。
本想通过AlarmManager传递PendingItent打开后台service实现,但是发现程序退出之后或者锁屏状态下service不能正常启动(不知道是不是我的方法有问题)。
经过一番摸索发现了下面的方法:
设定静态BroadcastReciver通过AlarmManager延时发送自定义的消息启动,然后在BroadcastReciver里面动态注册监听解锁。直接上代码:(大多数情况下需要申请自启动权限和无省电优化)
public class ScreenUnlockReceiver extends BroadcastReceiver {
private static final String TAG = "Receiver";
public static final String ACTION_FIRST_UNLOCK_REMIND_REGISTER = "action.ready_remind_service";
static ScreenUnlockReceiver receiver = null;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.equals(ACTION_FIRST_UNLOCK_REMIND_REGISTER)) {
KeyguardManager mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if (mKeyguardManager != null)
if (!mKeyguardManager.inKeyguardRestrictedInputMode()) {//如果到点了是解锁状态就直接提醒
NotificationUtils.remindSubmit(context);
} else {//否则注册监听
registerRemindReceiver(context);
Log.i(TAG, "register");
}
} else if (action != null && action.equals(Intent.ACTION_USER_PRESENT)) {//监听到解锁
NotificationUtils.remindSubmit(context);
unregisterRemindReceiver(context);
Log.i(TAG, "unregister");
} else {
Log.i(TAG, "no equals");
}
}
private void unregisterRemindReceiver(Context context) {
if (receiver != null)
context.getApplicationContext().unregisterReceiver(receiver);
}
private void registerRemindReceiver(Context context) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_PRESENT);
receiver = new ScreenUnlockReceiver();
context.getApplicationContext().registerReceiver(receiver, intentFilter);
}
}
定时工具类:
根据安卓版本不同需要调用不同的方法来设置提醒,由于各家系统的策略不同通常会有一两分钟的误差。
public class AlarmUtils {
private static final int REQUEST_CODE = 1;
private static final String TAG = "AlarmUtils";
public static int hour,minute,second;//想设定的时间
public static void setAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = getPendingIntent(context);
long readyTime = getReadyTime(hour,
minute,
second).getTimeInMillis();
multiVersionSetAlarm(readyTime, alarmManager, pendingIntent);
}
private static void multiVersionSetAlarm(long readyTime, AlarmManager alarmManager, PendingIntent pendingIntent) {
if (alarmManager != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC,
readyTime, pendingIntent);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
readyTime, pendingIntent);
else alarmManager.set(AlarmManager.RTC_WAKEUP,
readyTime, pendingIntent);
}
}
private static PendingIntent getPendingIntent(Context context) {
Intent intent = new Intent(context, ScreenUnlockReceiver.class);
intent.setAction(ScreenUnlockReceiver.ACTION_FIRST_UNLOCK_REMIND_REGISTER);
return PendingIntent.getBroadcast(context,//getApplicationContext(),
REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT);
}
private static Calendar getReadyTime(int hour, int minute, int second) {
Calendar scheduledTime = Calendar.getInstance();
Log.i(TAG, "getReadyTime: ");
scheduledTime.set(Calendar.HOUR_OF_DAY, hour);
scheduledTime.set(Calendar.MINUTE, minute);
scheduledTime.set(Calendar.SECOND, second);
if (Calendar.getInstance().after(scheduledTime))
scheduledTime.add(Calendar.DATE, 1);//今天的预定时间已过则设置为下一天的
Log.i(TAG, scheduledTime.toString());
return scheduledTime;
}
}
弹出提醒框工具类:
public class NotificationUtils {
private static final int OPEN_MAIN_ACTIVITY_REQUEST_CODE = 1;
private static final String REMIND_SUBMIT_CHANNEL_ID = "reminder_notification_channel";
private static final int REMIND_SUBMIT_ID = 1;
public static void remindSubmit(Context context) {
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
REMIND_SUBMIT_CHANNEL_ID,
REMIND_SUBMIT_CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, REMIND_SUBMIT_CHANNEL_ID)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle(context.getString(R.string.notify_title))
.setContentText(context.getString(R.string.notify_text))
.setDefaults(Notification.DEFAULT_VIBRATE)
.setContentIntent(contentIntent(context));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
}
notificationManager.notify(REMIND_SUBMIT_ID, builder.build());
}
private static PendingIntent contentIntent(Context context) {
Intent startActivityIntent = new Intent(context, MainActivity.class);
return PendingIntent.getActivity(
context,
OPEN_MAIN_ACTIVITY_REQUEST_CODE,
startActivityIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
}