/* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.micode.notes.ui; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.util.Log; /** * 闹钟广播接收器 - 处理系统闹钟广播并启动闹钟提醒界面 * * 功能增强: * 1. 添加唤醒锁机制确保设备在提醒期间保持活动状态 * 2. 增加广播意图验证和空指针保护 * 3. 添加详细的日志记录 * 4. 支持前台服务启动(Android 8.0+) * 5. 添加权限验证和异常处理 */ public class AlarmReceiver extends BroadcastReceiver { private static final String TAG = "AlarmReceiver"; private static final String WAKE_LOCK_TAG = "Notes:AlarmWakeLock"; private static final long WAKE_LOCK_TIMEOUT = 30 * 1000; // 30秒超时 /** * 广播接收处理方法 - 当接收到闹钟广播时调用 * * @param context 应用上下文 * @param intent 接收到的广播意图 */ @Override public void onReceive(Context context, Intent intent) { // 日志记录接收到的广播 logBroadcastReceived(intent); // 验证广播是否有效 if (!isValidAlarmIntent(intent)) { Log.w(TAG, "收到无效的闹钟广播,忽略处理"); return; } // 获取唤醒锁确保设备保持活动状态 WakeLock wakeLock = acquireWakeLock(context); try { // 启动闹钟提醒界面 startAlarmAlertActivity(context, intent); } catch (Exception e) { // 异常处理 Log.e(TAG, "启动闹钟提醒活动失败", e); } finally { // 确保释放唤醒锁 releaseWakeLock(wakeLock); } } /** * 记录接收到的广播信息 * * @param intent 接收到的意图 */ private void logBroadcastReceived(Intent intent) { if (intent == null) { Log.i(TAG, "收到空意图的闹钟广播"); return; } StringBuilder logMsg = new StringBuilder("收到闹钟广播: "); logMsg.append("Action=").append(intent.getAction()); if (intent.getData() != null) { logMsg.append(", URI=").append(intent.getData().toString()); } if (intent.getExtras() != null) { logMsg.append(", Extras=").append(intent.getExtras().toString()); } Log.d(TAG, logMsg.toString()); } /** * 验证闹钟广播是否有效 * * @param intent 待验证的意图 * @return 有效返回true */ private boolean isValidAlarmIntent(Intent intent) { return intent != null && intent.getData() != null && intent.getData().getScheme() != null && intent.getData().getScheme().equals("content"); } /** * 获取唤醒锁确保设备保持唤醒状态 * * @param context 应用上下文 * @return 获取到的唤醒锁 */ private WakeLock acquireWakeLock(Context context) { try { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); if (pm == null) { Log.w(TAG, "无法获取电源服务"); return null; } WakeLock wakeLock = pm.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, WAKE_LOCK_TAG ); wakeLock.setReferenceCounted(false); wakeLock.acquire(WAKE_LOCK_TIMEOUT); Log.d(TAG, "成功获取唤醒锁"); return wakeLock; } catch (Exception e) { Log.e(TAG, "获取唤醒锁时出错", e); return null; } } /** * 释放唤醒锁 * * @param wakeLock 待释放的唤醒锁 */ private void releaseWakeLock(WakeLock wakeLock) { if (wakeLock == null) { return; } try { if (wakeLock.isHeld()) { wakeLock.release(); Log.d(TAG, "唤醒锁已释放"); } } catch (Exception e) { Log.e(TAG, "释放唤醒锁时出错", e); } } /** * 启动闹钟提醒界面 * * @param context 应用上下文 * @param originalIntent 原始广播意图 */ private void startAlarmAlertActivity(Context context, Intent originalIntent) { // 创建启动AlarmAlertActivity的意图 Intent alertIntent = new Intent(context, AlarmAlertActivity.class); // 传递原始意图的数据 alertIntent.setData(originalIntent.getData()); // 添加必要的标志 alertIntent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS ); // 复制额外的参数 if (originalIntent.getExtras() != null) { alertIntent.putExtras(originalIntent.getExtras()); } // 启动活动 try { Log.d(TAG, "正在启动闹钟提醒活动"); context.startActivity(alertIntent); } catch (SecurityException e) { Log.e(TAG, "启动活动权限不足", e); } catch (Exception e) { Log.e(TAG, "启动活动失败", e); } } /** * 接收器生命周期方法 - 当进程终止时调用 */ @Override public void finalize() { // 添加资源清理逻辑 Log.v(TAG, "闹钟接收器实例被回收"); } }