|
|
/*
|
|
|
* 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.
|
|
|
*/
|
|
|
|
|
|
// 包声明,表明该类属于net.micode.notes.ui包,通常用于存放与用户界面相关的类
|
|
|
package net.micode.notes.ui;
|
|
|
|
|
|
import android.app.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;
|
|
|
import android.media.AudioManager;
|
|
|
import android.media.MediaPlayer;
|
|
|
import android.media.RingtoneManager;
|
|
|
import android.net.Uri;
|
|
|
import android.os.Bundle;
|
|
|
import android.os.PowerManager;
|
|
|
import android.provider.Settings;
|
|
|
import android.view.Window;
|
|
|
import android.view.WindowManager;
|
|
|
|
|
|
import net.micode.notes.R;
|
|
|
import net.micode.notes.data.Notes;
|
|
|
import net.micode.notes.tool.DataUtils;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
// AlarmAlertActivity类继承自Activity类,意味着它是一个安卓中的Activity,用于展示用户界面。
|
|
|
// 同时实现了OnClickListener和OnDismissListener接口,用于处理对话框的点击和关闭事件
|
|
|
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
|
|
|
|
|
|
// 用于存储与提醒相关联的笔记的ID,可能后续用于查询、操作该笔记的相关信息
|
|
|
private long mNoteId;
|
|
|
// 用于存储笔记的摘要信息,将展示在提醒界面等地方给用户查看
|
|
|
private String mSnippet;
|
|
|
// 定义摘要信息的最大长度为60个字符,超过这个长度会进行截断处理
|
|
|
private static final int SNIPPET_PREW_MAX_LEN = 60;
|
|
|
// MediaPlayer对象,用于播放提醒的声音,比如闹钟铃声等
|
|
|
MediaPlayer mPlayer;
|
|
|
|
|
|
// 重写Activity的onCreate方法,该方法在Activity被创建时调用,用于进行初始化等相关操作
|
|
|
@Override
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
super.onCreate(savedInstanceState);
|
|
|
// 请求去除Activity的标题栏,使界面更加简洁,仅在支持该特性的安卓版本和设备上生效
|
|
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
|
|
|
|
|
// 获取当前Activity的窗口对象,后续用于设置窗口的各种属性
|
|
|
final Window win = getWindow();
|
|
|
// 设置窗口属性,使窗口在屏幕锁定时也能够显示出来,方便用户看到提醒信息
|
|
|
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
|
|
|
|
|
|
// 调用isScreenOn方法判断屏幕是否处于开启状态,如果屏幕未开启
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
// 获取启动该Activity的Intent对象,Intent中可能携带了与提醒相关的数据,比如笔记的相关信息等
|
|
|
Intent intent = getIntent();
|
|
|
|
|
|
try {
|
|
|
// 从Intent携带的数据中解析出笔记的ID,具体是从Intent的数据Uri的路径段中获取第二个元素(索引为1)并转换为长整型
|
|
|
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
|
|
|
// 通过DataUtils工具类的方法,根据笔记ID从内容提供器中获取笔记的摘要信息
|
|
|
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);
|
|
|
// 如果获取到的摘要信息长度大于设定的最大长度(SNIPPET_PREW_MAX_LEN)
|
|
|
mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN? mSnippet.substring(0,
|
|
|
SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info)
|
|
|
: mSnippet;
|
|
|
// 则进行截断处理,截取前60个字符,并添加一个特定的提示字符串(从资源文件中获取),否则保持原摘要信息不变
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
// 如果在解析笔记ID或者获取摘要信息过程中出现参数异常(比如格式不正确等原因),打印异常堆栈信息,并直接返回,不再执行后续操作
|
|
|
e.printStackTrace();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 创建一个MediaPlayer实例,用于后续播放提醒声音
|
|
|
mPlayer = new MediaPlayer();
|
|
|
// 通过DataUtils工具类判断该笔记在笔记数据库中是否可见(可能涉及是否被删除、是否处于有效状态等条件判断),
|
|
|
// 传入笔记ID以及笔记类型(这里是普通笔记类型Notes.TYPE_NOTE)进行判断
|
|
|
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
|
|
|
// 如果笔记可见,即满足有效条件,调用showActionDialog方法显示操作对话框,供用户进行相应操作
|
|
|
showActionDialog();
|
|
|
// 调用playAlarmSound方法播放提醒声音
|
|
|
playAlarmSound();
|
|
|
} else {
|
|
|
// 如果笔记不可见,直接结束当前Activity,意味着不需要展示提醒相关的界面了
|
|
|
finish();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 私有方法,用于判断屏幕是否处于开启状态
|
|
|
private boolean isScreenOn() {
|
|
|
// 获取系统的电源管理服务对象,用于查询屏幕的电源状态等信息
|
|
|
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
|
|
// 调用电源管理服务对象的isScreenOn方法,返回屏幕是否开启的布尔值结果
|
|
|
return pm.isScreenOn();
|
|
|
}
|
|
|
|
|
|
// 私有方法,用于播放提醒声音,比如播放闹钟铃声等
|
|
|
private void playAlarmSound() {
|
|
|
// 通过RingtoneManager获取系统默认的闹钟铃声的Uri,用于指定MediaPlayer要播放的音频资源
|
|
|
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM);
|
|
|
|
|
|
// 从系统设置中获取静音模式影响的音频流相关设置值,用于判断在静音模式下闹钟声音的播放情况
|
|
|
int silentModeStreams = Settings.System.getInt(getContentResolver(),
|
|
|
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
|
|
|
|
|
|
// 判断静音模式设置中是否影响闹钟音频流,如果影响(对应位的值不为0)
|
|
|
if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM))!= 0) {
|
|
|
// 设置MediaPlayer的音频流类型为获取到的静音模式设置值,按照系统静音模式的相关配置来播放声音
|
|
|
mPlayer.setAudioStreamType(silentModeStreams);
|
|
|
} else {
|
|
|
// 如果静音模式不影响闹钟音频流,设置为正常的闹钟音频流类型,确保闹钟声音正常播放
|
|
|
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
// 设置MediaPlayer的数据源为获取到的铃声Uri,指定要播放的音频文件等资源
|
|
|
mPlayer.setDataSource(this, url);
|
|
|
// 准备MediaPlayer,使其进入可播放状态,这个过程可能涉及加载音频资源、初始化播放相关参数等操作
|
|
|
mPlayer.prepare();
|
|
|
// 设置MediaPlayer为循环播放模式,使提醒声音能够持续播放,直到用户手动停止或者其他相关逻辑结束播放
|
|
|
mPlayer.setLooping(true);
|
|
|
// 启动MediaPlayer,开始播放提醒声音
|
|
|
mPlayer.start();
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
// 如果在设置数据源等过程中出现参数异常(比如参数不合法等原因),打印异常堆栈信息
|
|
|
e.printStackTrace();
|
|
|
} catch (SecurityException e) {
|
|
|
// 如果出现安全相关异常(比如没有权限访问音频资源等原因),打印异常堆栈信息
|
|
|
e.printStackTrace();
|
|
|
} catch (IllegalStateException e) {
|
|
|
// 如果MediaPlayer的状态出现异常(比如在不恰当的状态下执行了某些操作等原因),打印异常堆栈信息
|
|
|
e.printStackTrace();
|
|
|
} catch (IOException e) {
|
|
|
// 如果在读取数据源等IO操作过程中出现异常(比如音频文件损坏、无法读取等原因),打印异常堆栈信息
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 私有方法,用于创建并显示操作对话框,给用户提供相应的操作选项,比如确认、进入编辑等操作
|
|
|
private void showActionDialog() {
|
|
|
// 创建一个AlertDialog的构建器对象,用于方便地构建AlertDialog对话框
|
|
|
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
|
|
|
// 设置对话框的标题,这里使用了字符串资源中的应用名称(R.string.app_name对应的字符串)作为标题
|
|
|
dialog.setTitle(R.string.app_name);
|
|
|
// 设置对话框的消息内容,展示之前获取到的笔记摘要信息,让用户了解是哪个笔记的提醒
|
|
|
dialog.setMessage(mSnippet);
|
|
|
// 设置对话框的确定按钮(通常是一个积极的操作按钮)文本以及点击监听器,点击监听器使用当前类实现的OnClickListener接口,
|
|
|
// 意味着点击该按钮会触发当前类中对应的onClick方法
|
|
|
dialog.setPositiveButton(R.string.notealert_ok, this);
|
|
|
// 如果屏幕处于开启状态,设置对话框的另一个按钮(可能是进入编辑等操作按钮)文本以及点击监听器,同样使用当前类实现的OnClickListener接口
|
|
|
if (isScreenOn()) {
|
|
|
dialog.setNegativeButton(R.string.notealert_enter, this);
|
|
|
}
|
|
|
// 构建并显示对话框,同时设置对话框的关闭监听器,使用当前类实现的OnDismissListener接口,
|
|
|
// 意味着对话框关闭时会触发当前类中对应的onDismiss方法
|
|
|
dialog.show().setOnDismissListener(this);
|
|
|
}
|
|
|
|
|
|
// 实现OnClickListener接口的方法,用于处理对话框按钮的点击事件,根据点击的按钮不同执行相应的逻辑
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
switch (which) {
|
|
|
// 如果点击的是对话框中的否定按钮(具体含义根据设置的文本而定,这里可能是进入编辑按钮等情况)
|
|
|
case DialogInterface.BUTTON_NEGATIVE:
|
|
|
// 创建一个Intent,用于启动NoteEditActivity,可能是进入对应的笔记编辑界面,方便用户对笔记进行编辑等操作
|
|
|
Intent intent = new Intent(this, NoteEditActivity.class);
|
|
|
// 设置Intent的动作,这里设置为查看(ACTION_VIEW)动作,表明是查看相关的操作意图
|
|
|
intent.setAction(Intent.ACTION_VIEW);
|
|
|
// 通过Intent的额外数据传递机制,将笔记的ID传递给目标Activity(NoteEditActivity),以便目标Activity能获取并处理对应的笔记
|
|
|
intent.putExtra(Intent.EXTRA_UID, mNoteId);
|
|
|
// 启动目标Activity,跳转到对应的笔记编辑界面
|
|
|
startActivity(intent);
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 实现OnDismissListener接口的方法,当对话框关闭时会被调用,用于执行对话框关闭后的相关操作
|
|
|
public void onDismiss(DialogInterface dialog) {
|
|
|
// 调用stopAlarmSound方法停止播放提醒声音,并释放相关的资源,如MediaPlayer占用的内存等
|
|
|
stopAlarmSound();
|
|
|
// 结束当前Activity,关闭提醒相关的界面,完成整个提醒流程
|
|
|
finish();
|
|
|
}
|
|
|
|
|
|
// 私有方法,用于停止播放提醒声音,并释放MediaPlayer资源,将其置为null避免后续出现问题
|
|
|
private void stopAlarmSound() {
|
|
|
if (mPlayer!= null) {
|
|
|
// 停止MediaPlayer的播放,如果正在播放声音则立即停止
|
|
|
mPlayer.stop();
|
|
|
// 释放MediaPlayer占用的资源,使其回到初始未使用状态
|
|
|
mPlayer.release();
|
|
|
// 将mPlayer对象置为null,防止后续误操作该对象,同时也符合资源释放后的正确使用习惯
|
|
|
mPlayer = null;
|
|
|
}
|
|
|
}
|
|
|
} |