You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
6.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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, "闹钟接收器实例被回收");
}
}