From 48e03e4dafe10d6555f29b8e7800bb328297b64d Mon Sep 17 00:00:00 2001 From: xxxx Date: Sat, 21 Dec 2024 18:28:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AlarmAlertActivity.java | 313 ++++++++++++++++++++++++++++++++++++++++ AlarmInitReceiver.java | 131 +++++++++++++++++ AlarmReceiver.java | 65 +++++++++ 3 files changed, 509 insertions(+) create mode 100644 AlarmAlertActivity.java create mode 100644 AlarmInitReceiver.java create mode 100644 AlarmReceiver.java diff --git a/AlarmAlertActivity.java b/AlarmAlertActivity.java new file mode 100644 index 0000000..b91155c --- /dev/null +++ b/AlarmAlertActivity.java @@ -0,0 +1,313 @@ +/* + * 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. + */ + +// 导入所需的Android和Java类 + +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; // 笔记ID + + private String mSnippet; // 笔记摘要 + + private static final int SNIPPET_PREW_MAX_LEN = 60; // 摘要最大长度 + + MediaPlayer mPlayer; // 媒体播放器,用于播放闹钟声音 + + + + // onCreate方法,Activity创建时调用 + + @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(); // 获取启动此Activity的Intent + + + + try { + + // 从Intent中提取笔记ID + + 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(); // 如果笔记不存在,则结束Activity + + } + + } + + + + // 检查屏幕是否点亮 + + 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 + + + + // 获取静音模式下受影响的音频流类型 + + 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 | SecurityException | IllegalStateException | IOException e) { + + 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); // 创建跳转到NoteEditActivity的Intent + + intent.setAction(Intent.ACTION_VIEW); // 设置Intent动作为查看 + + intent.putExtra(Intent.EXTRA_UID, mNoteId); // 将笔记ID作为额外数据添加到Intent中 + + startActivity(intent); // 启动NoteEditActivity + + break; + + default: + + break; + + } + + } + + + + // 对话框关闭时调用 + + public void onDismiss(DialogInterface dialog) { + + stopAlarmSound(); // 停止播放闹钟声音 + + finish(); // 结束Activity + + } + + + + // 停止播放闹钟声音 + + private void stopAlarmSound() { + + if (mPlayer != null) { + + mPlayer.stop(); // 停止媒体播放器 + + mPlayer.release(); // 释放媒体播放器资源 + + mPlayer = null; // 将媒体播放器引用置为空 + + } + + } + +} \ No newline at end of file diff --git a/AlarmInitReceiver.java b/AlarmInitReceiver.java new file mode 100644 index 0000000..4852329 --- /dev/null +++ b/AlarmInitReceiver.java @@ -0,0 +1,131 @@ +/* + * 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. + */ + +// 导入所需的Android和应用程序特定的包 + +package net.micode.notes.ui; + + + +import android.app.AlarmManager; // 导入AlarmManager类,用于设置闹钟 + +import android.app.PendingIntent; // 导入PendingIntent类,用于表示一个将要执行的操作 + +import android.content.BroadcastReceiver; // 导入BroadcastReceiver类,用于接收广播消息 + +import android.content.ContentUris; // 导入ContentUris类,用于生成内容URI + +import android.content.Context; // 导入Context类,表示应用程序环境的全局信息 + +import android.content.Intent; // 导入Intent类,用于不同组件之间的通信 + +import android.database.Cursor; // 导入Cursor类,用于遍历查询结果 + + + +import net.micode.notes.data.Notes; // 导入Notes类,包含NoteProvider的相关常量 + +import net.micode.notes.data.Notes.NoteColumns; // 导入NoteColumns接口,包含Note表的列名 + + + +// 定义一个继承自BroadcastReceiver的类,用于初始化闹钟 + +public class AlarmInitReceiver extends BroadcastReceiver { + + + + // 定义要从Note表中查询的列 + + private static final String [] PROJECTION = new String [] { + + NoteColumns.ID, // Note的ID + + NoteColumns.ALERTED_DATE // Note的提醒日期 + + }; + + + + // 定义查询结果集中列的索引 + + private static final int COLUMN_ID = 0; // ID列的索引 + + private static final int COLUMN_ALERTED_DATE = 1; // 提醒日期列的索引 + + + + // 当接收到广播时调用的方法 + + @Override + + public void onReceive(Context context, Intent intent) { + + long currentDate = System.currentTimeMillis(); // 获取当前时间(毫秒) + + // 从Note表中查询提醒日期大于当前时间且类型为Note的记录 + + Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI, + + PROJECTION, + + NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, + + new String[] { String.valueOf(currentDate) }, // 替换查询语句中的?为当前时间的字符串表示 + + null); // 不对结果进行排序 + + + + if (c != null) { // 如果查询结果不为空 + + if (c.moveToFirst()) { // 移动到查询结果的第一条记录 + + do { + + long alertDate = c.getLong(COLUMN_ALERTED_DATE); // 获取当前记录的提醒日期 + + Intent sender = new Intent(context, AlarmReceiver.class); // 创建一个Intent,指向AlarmReceiver + + // 设置Intent的数据为Note的URI,并附加Note的ID + + sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); + + // 创建一个PendingIntent,表示在指定时间执行的操作 + + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); + + // 获取AlarmManager实例,用于设置闹钟 + + AlarmManager alermManager = (AlarmManager) context + + .getSystemService(Context.ALARM_SERVICE); + + // 设置一个闹钟,在指定的提醒日期(alertDate)触发AlarmReceiver + + alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); + + } while (c.moveToNext()); // 移动到下一条记录,直到遍历完所有结果 + + } + + c.close(); // 关闭Cursor,释放资源 + + } + + } + +} \ No newline at end of file diff --git a/AlarmReceiver.java b/AlarmReceiver.java new file mode 100644 index 0000000..bbe2eac --- /dev/null +++ b/AlarmReceiver.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +// 导入必要的Android框架类 + +package net.micode.notes.ui; // 指定这个类所在的包名 + + + +import android.content.BroadcastReceiver; // 导入BroadcastReceiver类,用于接收广播 + +import android.content.Context; // 导入Context类,代表应用的当前状态,包括资源和类以及调用应用级操作 + +import android.content.Intent; // 导入Intent类,用于不同组件之间的通信 + + + +// 定义一个名为AlarmReceiver的类,它继承自BroadcastReceiver + +public class AlarmReceiver extends BroadcastReceiver { + + + + // 重写onReceive方法,这是BroadcastReceiver的核心方法,用于接收广播 + + @Override + + public void onReceive(Context context, Intent intent) { + + // 设置Intent的目标Activity为AlarmAlertActivity,这意味着当广播被接收时,将启动这个Activity + + intent.setClass(context, AlarmAlertActivity.class); + + + + // 添加一个标志,指定这个Activity应该在一个新的任务中启动 + + // 这对于从非Activity的上下文中启动Activity(如BroadcastReceiver)是必要的 + + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + + + // 使用上下文(context)启动Intent指定的Activity + + // 这将导致AlarmAlertActivity被创建并显示在屏幕上 + + context.startActivity(intent); + + } + +} \ No newline at end of file