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.
git/java/net/micode/notes/ui/AlarmAlertActivity.java

270 lines
11 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.
*/
// AlarmAlertActivity.java - 闹钟提醒Activity
// 主要功能:显示便签闹钟提醒,在指定时间弹出提醒对话框并播放提示音
package net.micode.notes.ui;
// ======================= 导入区域 =======================
// Android基础类
import android.app.Activity; // Activity基类
import android.app.AlertDialog; // 警告对话框
import android.content.Context; // 上下文
import android.content.DialogInterface; // 对话框接口
import android.content.DialogInterface.OnClickListener; // 对话框点击监听
import android.content.DialogInterface.OnDismissListener; // 对话框关闭监听
import android.content.Intent; // Intent用于跳转
import android.media.AudioManager; // 音频管理
import android.media.MediaPlayer; // 媒体播放器
import android.media.RingtoneManager; // 铃声管理器
import android.net.Uri; // URI
import android.os.Bundle; // Bundle用于保存状态
import android.os.PowerManager; // 电源管理
import android.provider.Settings; // 系统设置
import android.view.Window; // 窗口
import android.view.WindowManager; // 窗口管理器
// 应用内部资源
import net.micode.notes.R; // 资源文件R类
import net.micode.notes.data.Notes; // Notes主类
import net.micode.notes.tool.DataUtils; // 数据工具类
// Java IO
import java.io.IOException; // IO异常
// ======================= 闹钟提醒Activity =======================
/**
* AlarmAlertActivity - 闹钟提醒Activity
* 全屏对话框形式显示,即使在锁屏状态下也会弹出
* 实现功能:显示便签内容、播放提示音、提供操作按钮
* 实现接口OnClickListener对话框按钮点击OnDismissListener对话框关闭
*/
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
// 成员变量
private long mNoteId; // 便签ID从Intent中获取
private String mSnippet; // 便签摘要,用于对话框显示
private static final int SNIPPET_PREW_MAX_LEN = 60; // 摘要预览最大长度
MediaPlayer mPlayer; // 媒体播放器,用于播放提示音
// ======================= 生命周期方法 =======================
/**
* onCreate - Activity创建时的初始化方法
* 主要任务:
* 1. 设置窗口属性(全屏、锁屏显示)
* 2. 获取便签ID和内容
* 3. 检查便签是否存在
* 4. 显示提醒对话框
* 5. 播放提示音
* @param savedInstanceState 保存的状态此处为null因是新建Activity
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1. 设置窗口属性
// 请求无标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 获取窗口对象
final Window win = getWindow();
// 添加标志:在锁屏状态下显示
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
// 如果屏幕是关闭状态,添加更多标志
if (!isScreenOn()) {
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON // 保持屏幕常亮
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON // 点亮屏幕
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON // 允许锁屏
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); // 布局装饰
}
// 2. 获取Intent数据
Intent intent = getIntent();
try {
// 从Intent的URI中解析便签ID
// URI格式示例content://micode_notes/note/123
// getPathSegments()返回["note", "123"]取索引1得到"123"
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
// 通过工具类获取便签摘要
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);
// 3. 处理摘要显示长度
// 如果摘要过长截取前60个字符并添加省略号
mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0,
SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info)
: mSnippet;
} catch (IllegalArgumentException e) {
// URI解析或ID转换异常
e.printStackTrace();
return; // 异常时直接返回,不继续执行
}
// 4. 初始化媒体播放器
mPlayer = new MediaPlayer();
// 5. 检查便签是否可见(存在且不在回收站)
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
// 便签存在,显示对话框
showActionDialog();
// 播放提示音
playAlarmSound();
} else {
// 便签不存在可能已被删除直接结束Activity
finish();
}
}
/**
* 检查屏幕是否亮屏
* @return true: 屏幕已亮; false: 屏幕关闭
*/
private boolean isScreenOn() {
// 获取电源管理器服务
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
// 判断屏幕是否亮屏(已废弃,但兼容旧版本)
return pm.isScreenOn();
}
// ======================= 提示音播放 =======================
/**
* 播放闹钟提示音
* 使用系统默认的闹钟铃声
*/
private void playAlarmSound() {
// 1. 获取系统默认闹钟铃声URI
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM);
// 2. 获取静音模式设置
// 检查哪些音频流受静音模式影响
int silentModeStreams = Settings.System.getInt(getContentResolver(),
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
// 3. 设置音频流类型
// 判断闹钟音频流是否受静音模式影响
if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) {
// 受静音影响,使用系统设置的类型
mPlayer.setAudioStreamType(silentModeStreams);
} else {
// 不受静音影响,使用闹钟音频流
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
}
// 4. 设置数据源并播放
try {
mPlayer.setDataSource(this, url); // 设置铃声URI
mPlayer.prepare(); // 准备播放
mPlayer.setLooping(true); // 循环播放
mPlayer.start(); // 开始播放
} catch (IllegalArgumentException e) {
// URI格式错误
e.printStackTrace();
} catch (SecurityException e) {
// 权限不足
e.printStackTrace();
} catch (IllegalStateException e) {
// 播放器状态错误
e.printStackTrace();
} catch (IOException e) {
// IO错误文件读取失败
e.printStackTrace();
}
}
// ======================= 提醒对话框 =======================
/**
* 显示操作对话框
* 对话框内容:应用名称 + 便签摘要 + 操作按钮
*/
private void showActionDialog() {
// 1. 创建对话框构建器
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
// 2. 设置对话框内容
dialog.setTitle(R.string.app_name); // 应用名称作为标题
dialog.setMessage(mSnippet); // 便签摘要作为内容
// 3. 设置按钮
// 确定按钮 - 关闭提醒
dialog.setPositiveButton(R.string.notealert_ok, this);
// 如果屏幕已亮,显示"进入"按钮(跳转到便签编辑)
if (isScreenOn()) {
dialog.setNegativeButton(R.string.notealert_enter, this);
}
// 4. 显示对话框并设置关闭监听
dialog.show().setOnDismissListener(this);
}
// ======================= 对话框事件处理 =======================
/**
* 对话框按钮点击回调
* 实现OnClickListener接口
* @param dialog 被点击的对话框
* @param which 被点击的按钮标识
* BUTTON_POSITIVE: 确定按钮
* BUTTON_NEGATIVE: 进入按钮(仅在屏幕亮时显示)
* BUTTON_NEUTRAL: 中立按钮(未使用)
*/
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_NEGATIVE:
// "进入"按钮:跳转到便签编辑界面
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_VIEW); // 查看动作
intent.putExtra(Intent.EXTRA_UID, mNoteId); // 传递便签ID
startActivity(intent);
break;
default:
// 其他按钮(确定按钮)不执行额外操作
// 对话框关闭后会触发onDismiss自动结束Activity
break;
}
}
/**
* 对话框关闭回调
* 实现OnDismissListener接口
* 无论点击哪个按钮,对话框关闭时都会执行
* @param dialog 被关闭的对话框
*/
public void onDismiss(DialogInterface dialog) {
// 停止播放提示音
stopAlarmSound();
// 结束Activity
finish();
}
// ======================= 资源清理 =======================
/**
* 停止播放提示音
* 释放MediaPlayer资源
*/
private void stopAlarmSound() {
if (mPlayer != null) {
mPlayer.stop(); // 停止播放
mPlayer.release(); // 释放资源
mPlayer = null; // 置空引用帮助GC
}
}
}