diff --git a/src/ui/AlarmAlertActivity.java b/src/ui/AlarmAlertActivity.java new file mode 100644 index 0000000..6662469 --- /dev/null +++ b/src/ui/AlarmAlertActivity.java @@ -0,0 +1,182 @@ +/* + * 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. + */ + +// 220340038 毛彦翔 2024/4/14 + +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; //便签在库中的检索ID + private String mSnippet; //便签提醒时显示的文本 + private static final int SNIPPET_PREW_MAX_LEN = 60; + MediaPlayer mPlayer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState);//通过savedInstanceState获取状态信息 + requestWindowFeature(Window.FEATURE_NO_TITLE); + //通过requestWindowFeature指定活动窗口的特性(无标题) + + final Window win = getWindow(); + /* + *获取当前活动的window对象,并赋值给名为win的final变量 + *由于final变量 在赋值后不能再改变, + *可以确保后续引用该变量时不会被意外修改 提高代码的可维护性 + */ + + win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + //使window对象win可以在锁屏后仍然显示 即可以覆盖在锁屏界面之上 + + if (!isScreenOn()) { //检查屏幕是否开启 + win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + //保持屏幕唤醒 防止自动息屏 + | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + //唤醒屏幕并显示窗口 不明白与66行保持屏幕唤醒的区别 + | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON + //允许屏幕在保持唤醒的情况下手动锁定屏幕 猜测与66行FLAG_KEEP_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); + //通过检索ID从库中获取便签内容 + 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(); //创建一个MediaPlayer对象用于播放音频 + if (DataUtils.visibleInNoteDatabase/*便签是否可见*/(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { + showActionDialog(); //笔记存在可见则显示操作对话框 + playAlarmSound(); //同时播放警示音 + } else { + finish(); //笔记不存在或不可见则调用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); + //获取当前默认铃声的uri并存储在Uri类型的变量url中 Uri是什么类型?写完再查 + int silentModeStreams = Settings.System.getInt(getContentResolver(), + Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + //从系统设置中获取当前静音模式下受铃声模式影响的流的信息,并存储在一个整数变量中 + //作用是什么?没想明白 + if ((silentModeStreams/*处于静音模式*/ & (1 << AudioManager.STREAM_ALARM)) != 0) { + mPlayer.setAudioStreamType(silentModeStreams); + /*这下看懂了 + *使用位运算判断静音模式下是否受到铃声模式影响 + *与运算结果不为0则表示静音模式下受到铃声模式影响 + *受铃声模式影响则直接调用setAudioStreamType(silentModeStreams)设置音频流类型 + */ + } else { + mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); + } //否则使用AudioManager.STREAM_ALARM作为银趴留类型 总之 确保播放的铃声会受系统静音模式控制 + try { + mPlayer.setDataSource(this, url); + mPlayer.prepare(); + mPlayer.setLooping(true); + mPlayer.start(); + //设置MediaPlayer的数据源 准备播放铃声并循环播放 不一一注释了 + } 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(); + } + //用于捕获可能抛出的异常 发生以上异常则打印异常信息并继续执行 + //看不懂上面的注释 查找后发现是IDE自动生成的catch块 + } + + private void showActionDialog() { //显示操作对话框的私有方法 + AlertDialog.Builder dialog = new AlertDialog.Builder(this); //构建对话框 在当前活动窗口中显示 + dialog.setTitle(R.string.app_name); //设置对话框标题 文本来自app_name 这是什么 + dialog.setMessage(mSnippet); //对话框的内容 mSnippet在第46行被定义 这是什么来着 + dialog.setPositiveButton(R.string.notealert_ok, this); //某个按钮?没懂 positive按钮是什么 + if (isScreenOn()) { + dialog.setNegativeButton(R.string.notealert_enter, this); //negative按钮又是什么 晕了 这俩玩意的功能写在哪了 + } + dialog.show().setOnDismissListener(this); //头好痛 要长脑子了 + } +DialogInterface.OnClickListener + public void onClick(DialogInterface dialog, int which) { //对话框被点击时调用 DialogInterface.OnClickListener接口的实现 + switch (which) { // 用Switch分值判断哪个按钮被点击了 为什么不用if-else呢 + case DialogInterface.BUTTON_NEGATIVE: //negative按钮被按了! + Intent intent = new Intent(this, NoteEditActivity.class); //新建intent对象 调用NoteEditActivity类 + intent.setAction(Intent.ACTION_VIEW); //把当前活动状态设置为action_view + intent.putExtra(Intent.EXTRA_UID, mNoteId); //加了个什么东西 键为EXTRA_UID,值为mNoteID 检索ID?是把这对键值赋给新建的便签吗 + startActivity(intent); //启动。 + break; + default: //按的不是negative按钮则停止活动 为什么startActivity按的是negative按钮不是positive按钮 + break; + } + } + + public void onDismiss(DialogInterface dialog) { + stopAlarmSound(); + finish(); + } //最简单的一集 对话框消失则调用这两个函数 停止播放警示音并关闭当前活动 + + private void stopAlarmSound() { + if (mPlayer != null) { //就爱你差对象是否为空 是为了防止空指针吗 + mPlayer.stop(); + mPlayer.release(); //释放MediaPlayer使用的系统资源 避免资源浪费 + mPlayer = null; //将mPlayer设置为空 回收内存空间防止泄露 + } + } +}