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.
note/AlarmAlertActivity12.java

377 lines
18 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.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;
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
private long mNoteId;
private String mSnippet;
private static final int SNIPPET_PREW_MAX_LEN = 60;
MediaPlayer mPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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);
}
Intent intent = getIntent();
try {
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);
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) {
e.printStackTrace();
return;
}
mPlayer = new MediaPlayer();
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
showActionDialog();
playAlarmSound();
} else {
finish();
}
}
private boolean isScreenOn() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
return pm.isScreenOn();
}
private void playAlarmSound() {
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM);
int silentModeStreams = Settings.System.getInt(getContentResolver(),
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) {
mPlayer.setAudioStreamType(silentModeStreams);
} else {
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
}
try {
mPlayer.setDataSource(this, url);
mPlayer.prepare();
mPlayer.setLooping(true);
mPlayer.start();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void showActionDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle(R.string.app_name);
dialog.setMessage(mSnippet);
dialog.setPositiveButton(R.string.notealert_ok, this);
if (isScreenOn()) {
dialog.setNegativeButton(R.string.notealert_enter, this);
}
dialog.show().setOnDismissListener(this);
}
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);
startActivity(intent);
break;
default:
break;
}
}
public void onDismiss(DialogInterface dialog) {
stopAlarmSound();
finish();
}
private void stopAlarmSound() {
if (mPlayer != null) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
}
}
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用于处理闹钟提醒相关的界面展示、声音播放以及用户交互操作
// 同时实现了OnClickListener和OnDismissListener接口分别处理对话框的点击事件和消失事件
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {
// 用于存储便签的唯一标识符,后续通过此标识符来获取对应的便签相关信息
private long mNoteId;
// 用于存储便签内容的片段,会按照一定规则进行截取展示
private String mSnippet;
// 定义便签内容片段展示的最大长度为60个字符
private static final int SNIPPET_PREW_MAX_LEN = 60;
// MediaPlayer对象用于播放闹钟提醒的声音
MediaPlayer mPlayer;
// onCreate方法是在Activity创建时调用的生命周期方法进行一系列初始化操作
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 请求去除Activity的标题栏使界面更加简洁专注于展示提醒相关内容
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 获取当前Activity的窗口对象后续用于设置窗口的相关属性
final Window win = getWindow();
// 添加FLAG_SHOW_WHEN_LOCKED标志使得Activity窗口在屏幕锁定时也能够显示出来方便用户看到提醒信息
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);
}
// 获取启动该Activity的Intent对象Intent中可能携带了与便签提醒相关的数据信息
Intent intent = getIntent();
try {
// 尝试从Intent携带的数据中解析出便签的唯一标识符mNoteId
// 通过获取Intent中数据的路径片段假设数据的格式符合一定规范此处取路径中的第二个片段并转换为long类型
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
// 使用DataUtils工具类的方法根据mNoteId从内容解析器中获取便签内容的片段并赋值给mSnippet
mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId);
// 如果获取到的便签内容片段长度大于预设的最大长度SNIPPET_PREW_MAX_LEN
if (mSnippet.length() > SNIPPET_PREW_MAX_LEN) {
// 则对内容进行截取取前SNIPPET_PREW_MAX_LEN个字符并拼接上特定的提示字符串从资源文件中获取
mSnippet = mSnippet.substring(0, SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info);
}
} catch (IllegalArgumentException e) {
// 如果在解析过程中出现IllegalArgumentException异常例如数据格式不正确等情况
// 打印异常的栈信息,方便调试查找问题
e.printStackTrace();
// 直接返回,不再进行后续的初始化操作
return;
}
// 创建MediaPlayer对象用于后续播放闹钟提醒的声音
mPlayer = new MediaPlayer();
// 通过DataUtils工具类判断该便签在数据库中是否可见根据便签的唯一标识符mNoteId和便签类型Notes.TYPE_NOTE来判断
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
// 如果便签可见则调用showActionDialog方法弹出操作对话框向用户展示相关信息并提供操作按钮
showActionDialog();
// 同时调用playAlarmSound方法开始播放闹钟提醒的声音
playAlarmSound();
} else {
// 如果便签不可见直接调用finish方法结束当前的Activity无需进行其他展示和操作
finish();
}
}
// isScreenOn方法用于判断屏幕当前是否处于开启状态
private boolean isScreenOn() {
// 获取系统的PowerManager服务PowerManager用于管理电源相关的操作和获取电源状态信息
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
// 调用PowerManager的isScreenOn方法来获取屏幕的开启状态返回true表示屏幕开启false表示屏幕关闭
return pm.isScreenOn();
}
// playAlarmSound方法用于播放闹钟提醒的声音
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);
// 判断获取到的设置值中是否包含闹钟音频流对应的标志位(通过位运算进行判断)
if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM))!= 0) {
// 如果包含则将MediaPlayer的音频流类型设置为获取到的这个设置值按照系统的静音相关设置来播放声音
mPlayer.setAudioStreamType(silentModeStreams);
} else {
// 如果不包含则将MediaPlayer的音频流类型设置为正常的闹钟音频流类型AudioManager.STREAM_ALARM
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
}
try {
// 使用获取到的Uri为MediaPlayer设置数据源指定要播放的音频资源
mPlayer.setDataSource(this, url);
// 调用prepare方法准备播放声音进行必要的缓冲和初始化操作
mPlayer.prepare();
// 设置MediaPlayer为循环播放模式使得闹钟声音会一直循环播放直到被停止
mPlayer.setLooping(true);
// 调用start方法开始播放声音触发闹钟提醒的音频播放功能
mPlayer.start();
} catch (IllegalArgumentException e) {
// 如果在设置数据源、准备播放等过程中出现IllegalArgumentException异常例如参数不合法等情况
// 打印异常的栈信息,方便调试查找问题
e.printStackTrace();
} catch (SecurityException e) {
// 如果出现SecurityException异常例如没有权限访问音频资源等情况
// 打印异常的栈信息,方便调试查找问题
e.printStackTrace();
} catch (IllegalStateException e) {
// 如果出现IllegalStateException异常例如MediaPlayer状态不正确等情况
// 打印异常的栈信息,方便调试查找问题
e.printStackTrace();
} catch (IOException e) {
// 如果出现IOException异常例如读取音频数据源出错等情况
// 打印异常的栈信息,方便调试查找问题
e.printStackTrace();
}
}
// showActionDialog方法用于创建并显示一个包含便签信息和操作按钮的对话框方便用户进行相关操作
private void showActionDialog() {
// 创建一个AlertDialog的构建器对象传入当前Activity的Context用于构建对话框
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
// 设置对话框的标题为应用的名称,从资源文件中获取对应的字符串作为标题内容
dialog.setTitle(R.string.app_name);
// 设置对话框的消息内容为前面获取并处理后的便签内容片段mSnippet展示给用户查看
dialog.setMessage(mSnippet);
// 设置对话框的确定按钮PositiveButton按钮文本为R.string.notealert_ok同时将当前类实现了OnClickListener接口作为点击事件的监听器传入
// 点击确定按钮后会触发onClick方法中对应的逻辑处理
dialog.setPositiveButton(R.string.notealert_ok, this);
// 根据屏幕是否开启通过isScreenOn方法判断来决定是否添加“进入”按钮NegativeButton
if (isScreenOn()) {
// 如果屏幕开启则添加“进入”按钮按钮文本为R.string.notealert_enter同样将当前类作为点击事件监听器传入
dialog.setNegativeButton(R.string.notealert_enter, this);
}
// 调用dialog.show()方法显示对话框并为对话框设置消失监听器通过setOnDismissListener方法传入实现了OnDismissListener接口的当前类
// 这样在对话框消失时会触发onDismiss方法中的逻辑处理
dialog.show().setOnDismissListener(this);
}
// 实现OnClickListener接口的点击事件处理方法根据用户点击对话框中不同按钮来执行相应的操作
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
// 如果用户点击的是NegativeButton即前面设置的“进入”按钮如果屏幕开启时显示
case DialogInterface.BUTTON_NEGATIVE:
// 创建一个Intent用于启动NoteEditActivity通常用于进入便签的编辑界面
Intent intent = new Intent(this, NoteEditActivity.class);
// 设置Intent的动作Action为Intent.ACTION_VIEW表示查看相关内容的操作
intent.setAction(Intent.ACTION_VIEW);
// 通过putExtra方法将便签的唯一标识符mNoteId作为额外数据传递给要启动的NoteEditActivity
intent.putExtra(Intent.EXTRA_UID, mNoteId);
// 调用startActivity方法启动NoteEditActivity实现界面跳转进入便签编辑界面
startActivity(intent);
break;
default:
// 如果点击的是其他按钮这里目前只有PositiveButton情况暂时不做额外处理
break;
}
}
// 实现OnDismissListener接口的对话框消失事件处理方法在对话框消失时进行相关资源清理和Activity结束操作
@Override
public void onDismiss(DialogInterface dialog) {
// 调用stopAlarmSound方法停止正在播放的闹钟声音释放相关音频资源
stopAlarmSound();
// 调用finish方法结束当前的AlarmAlertActivity关闭该提醒界面
finish();
}
// stopAlarmSound方法用于停止并释放MediaPlayer资源避免资源浪费和内存泄漏等问题
private void stopAlarmSound() {
// 判断MediaPlayer对象是否为空如果不为空说明之前已经创建并正在使用
if (mPlayer!= null) {
// 调用stop方法停止正在播放的音频立即停止声音播放
mPlayer.stop();
// 调用release方法释放MediaPlayer占用的系统资源如音频播放相关的内存等
mPlayer.release();
// 将mPlayer对象赋值为null表示资源已经释放避免后续误操作
mPlayer = null;
}
}
}