Android 待办类应用提醒功能的实现及其问题

待办类应用作为一款提升工作效率的实用工具,在Android平台上深受用户喜爱。其核心功能之一便是提醒功能,帮助用户及时完成待办事项。

Android待办类应用的提醒功能看似简单,但涉及到多种系统机制和细节处理,需要开发者仔细考量和优化。

方式一:AlarmManager

设置时间点时的闹钟,主要通过 AlarmManager 的 setExact 方法在 reminderTime 时间点触发发送广播,从而在应用的广播接收器中处理弹出提醒通知。

java 复制代码
    public static void setAlarm(Context context, AlarmManager alarmManager, TodoItem todoItem, long reminderTime) {
        Intent intent = new Intent(context, AlarmReceiver.class);
        AlarmIntentParams alarmIntentParams = new AlarmIntentParams(todoItem);
        intent.putExtra(AlarmReceiver.KEY_ALARM_PARAMS, AlarmIntentParams.toByteArray(alarmIntentParams));
        intent.setAction(AlarmReceiver.ACTION_ALARM_TODO_NOTIFICATION);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, alarmIntentParams.hashCode(),
                intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, reminderTime, pendingIntent);
    }

因为可能同时设置多个闹钟及其通知,需要构造唯一的 id ,这里通过alarmIntentParams.hashCode() 方法实现 ,主要参数为 AlarmIntentParams 的属性合集的 hash 值

java 复制代码
public int hashCode() {
        return Objects.hash(id, content, time, repeat, important);
}

取消定时的闹钟,需要构造设置闹钟时完全一样的PendingIntent

java 复制代码
    public static void cancelAlarm(Context context, AlarmManager alarmManager, TodoItem todoItem, long reminderTime) {
        Intent intent = new Intent(context, AlarmReceiver.class);
        AlarmIntentParams alarmIntentParams = new AlarmIntentParams(todoItem);
        intent.putExtra(AlarmReceiver.KEY_ALARM_PARAMS, AlarmIntentParams.toByteArray(alarmIntentParams));
        intent.setAction(AlarmReceiver.ACTION_ALARM_TODO_NOTIFICATION);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, alarmIntentParams.hashCode(),
                intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        alarmManager.cancel(pendingIntent);
    }

在广播接收器中做提醒通知

java 复制代码
public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        mContext = context;
        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        String action = intent.getAction();
        android.util.Log.e("maxx", "AlarmReceiver action=" + action);
        NotificationManager mTodoNotificationManager = context.getSystemService(NotificationManager.class);
        if(action.equals(ACTION_ALARM_TODO_NOTIFICATION)){
            byte[] b = intent.getByteArrayExtra(KEY_ALARM_PARAMS);
            AlarmIntentParams params = AlarmIntentParams.toParcelable(b,AlarmIntentParams.CREATOR);
            // 通过获取的参数,显示对应的通知内容,及其通知的按钮Action事件
        }
   }
}

只需要在 AndroidManifest.xml 中声明 AlarmReceiver 组件即可,无需额外配置

xml 复制代码
<receiver android:name=".AlarmReceiver" />

此类实现会有2个问题:

问题1:实现的提醒铃声是集成在通知中的,由系统通知自己实现,无法自己控制铃声的暂停或播放,也无法抢夺音频焦点,在其他应用来通知,并同样有铃声,此时我们的通知铃声就自动停止播放,并且不再恢复。在调节音量的时,我们的通知铃声也会自动停止。

问题2:在应用被清理后台后,AlarmManager 的 setExact 设置的闹钟不再发送广播,通知功能失效,需要添加android:sharedUserId="android.uid.system",将赋予 system sharedUserId 的应用在被杀掉进程后设置的闹钟仍发送广播,当然这需要内置应用打系统才行。在手机重启后,通知也会功能失效,因为在重启后所有 AlarmManager 设置的闹钟都会被重置失效,需要监听开机广播,重新设置闹钟。

当然还可以通过假的清理后台来骗过用户实现,最近任务应用中添加白名单,将需要的应用添加到白名单中即可不杀掉应用进程。

方式二:通过日历

要在 Android 应用中向日历添加事件,您需要使用日历提供程序 API,该 API 提供对日历数据的访问,并允许您创建、修改和删除事件。以下是分步指南:

1. 请求日历权限:

  • 在您的应用的清单文件中,添加访问日历所需的权限:
xml 复制代码
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />

2. 检查日历访问:

  • 在访问日历之前,请验证用户是否已授予所需的权限。您可以使用checkSelfPermission()方法来检查权限。
java 复制代码
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED ||
    ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR}, REQUEST_CODE_CALENDAR_PERMISSIONS);
    } else {
        // Proceed with calendar access
    }

3.创建ContentResolver:

  • 获取一个ContentResolver对象来与日历提供程序交互。
java 复制代码
ContentResolver contentResolver = getContentResolver();

4. 构建活动内容价值:

  • 创建一个ContentValues对象来存储事件的详细信息。
java 复制代码
ContentValues eventValues = new ContentValues();

eventValues.put(CalendarContract.Events.CALENDAR_ID, DEFAULT_CALENDAR_ID); // Replace with your calendar ID
eventValues.put(CalendarContract.Events.TITLE, "Event Title");
eventValues.put(CalendarContract.Events.DESCRIPTION, "Event Description");
eventValues.put(CalendarContract.Events.EVENT_LOCATION, "Event Location");

// Set start and end times in milliseconds
long startTimeMillis = System.currentTimeMillis();
long endTimeMillis = startTimeMillis + 3600000; // 1 hour in milliseconds

eventValues.put(CalendarContract.Events.DTSTART, startTimeMillis);
eventValues.put(CalendarContract.Events.DTEND, endTimeMillis);

eventValues.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());

5.插入事件:

  • 使用ContentResolver将事件插入日历。
java 复制代码
Uri calendarUri = CalendarContract.Events.CONTENT_URI;
Uri eventUri = contentResolver.insert(calendarUri, eventValues);

if (eventUri != null) {
    // Event successfully added
} else {
    // Handle insertion failure
}

6.附加选项:

  • 您可以通过向对象添加相应的值来为事件添加更多详细信息,例如参加者、提醒和警报ContentValues
  • 您可以使用ContentResolver根据事件的 ID 或其他条件来查询、更新或删除事件。

记住要妥善处理潜在的错误,例如权限拒绝或插入失败。

相关推荐
似霰24 分钟前
安卓adb shell串口基础指令
android·adb
fatiaozhang95273 小时前
中兴云电脑W102D_晶晨S905X2_2+16G_mt7661无线_安卓9.0_线刷固件包
android·adb·电视盒子·魔百盒刷机·魔百盒固件
CYRUS_STUDIO4 小时前
Android APP 热修复原理
android·app·hotfix
鸿蒙布道师4 小时前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师4 小时前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
大耳猫4 小时前
【解决】Android Gradle Sync 报错 Could not read workspace metadata
android·gradle·android studio
ta叫我小白5 小时前
实现 Android 图片信息获取和 EXIF 坐标解析
android·exif·经纬度
dpxiaolong6 小时前
RK3588平台用v4l工具调试USB摄像头实践(亮度,饱和度,对比度,色相等)
android·windows
tangweiguo030519877 小时前
Android 混合开发实战:统一 View 与 Compose 的浅色/深色主题方案
android
老狼孩111227 小时前
2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
android·机器人·自动化·lua·脚本开发·懒人精灵·免root开发