diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 35eb1dd..8306744 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java b/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java index 85723be..cd1b87f 100644 --- a/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java +++ b/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java @@ -40,69 +40,71 @@ 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) { +@Override +protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); - final Window win = getWindow(); +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); + 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; + // 获取传递过来的NoteId和Snippet + 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;// 如果文本过长则截取前60个字符,加上一个显示“…”的标识 } catch (IllegalArgumentException e) { - e.printStackTrace(); - return; + e.printStackTrace(); + return; } mPlayer = new MediaPlayer(); + // 从数据源中查询记录是否存在,如果存在则显示提醒菜单和播放提醒声音,否则结束Activity if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { - showActionDialog(); - playAlarmSound(); + showActionDialog();// 显示提醒菜单 + playAlarmSound();// 播放提醒声音 } else { - finish(); + finish();// Note不存在,结束Activity + } } - } - private boolean isScreenOn() { - PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); - return pm.isScreenOn(); - } +private boolean isScreenOn() {// 检测屏幕是否点亮 + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);// 获取PowerManager对象 + 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 @@ -119,40 +121,44 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } } - private void showActionDialog() { +// 显示提醒菜单Dialog,包括Note的文本信息、确认键和选择键(如果屏幕是点亮的) +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.setTitle(R.string.app_name); // 设置Dialog的标题为应用名称 + dialog.setMessage(mSnippet); // 设置Dialog的信息为Note的文本信息 + dialog.setPositiveButton(R.string.notealert_ok, this); // 设置确认键,点击后执行onClick()方法 + if (isScreenOn()) { // 如果屏幕是点亮的,设置选择键 “进入笔记”, 点击后执行onClick()方法 + dialog.setNegativeButton(R.string.notealert_enter, this); + } + dialog.show().setOnDismissListener(this); // 显示Dialog,并设置当Dialog消失时的监听器 } - dialog.show().setOnDismissListener(this); - } - public void onClick(DialogInterface dialog, int which) { +// Dialog按键点击响应函数, which为点击的按键的序号 +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; + case DialogInterface.BUTTON_NEGATIVE: // 如果按下了选择键”进入笔记“ + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(Intent.EXTRA_UID, mNoteId); + startActivity(intent); // 打开Note编辑界面 + break; +default: + break; + } } - } - public void onDismiss(DialogInterface dialog) { - stopAlarmSound(); - finish(); - } +// 监听Dialog消失的响应函数 +public void onDismiss(DialogInterface dialog) { + stopAlarmSound(); // 停止播放闹钟声音 + finish(); // 结束Activity + } - private void stopAlarmSound() { - if (mPlayer != null) { - mPlayer.stop(); - mPlayer.release(); - mPlayer = null; +// 停止播放闹钟声音 +private void stopAlarmSound() { + if (mPlayer != null) { // 如果播放器存在 + mPlayer.stop(); // 停止播放 + mPlayer.release(); // 释放播放器占用的资源 + mPlayer = null; // 将播放器设为空 } - } -} + } + diff --git a/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java b/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java index f221202..6352d50 100644 --- a/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java +++ b/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java @@ -28,38 +28,36 @@ import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; +// 定义接收闹钟初始化的广播接收器 public class AlarmInitReceiver extends BroadcastReceiver { - private static final String [] PROJECTION = new String [] { - NoteColumns.ID, - NoteColumns.ALERTED_DATE - }; - - private static final int COLUMN_ID = 0; - private static final int COLUMN_ALERTED_DATE = 1; - + // 查询提醒时间比当前时间更晚的Note记录,并将它们转为闹钟事件 @Override public void onReceive(Context context, Intent intent) { + // 获取当前时间 long currentDate = System.currentTimeMillis(); + // 查询所有提醒时间晚于当前时间的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) }, + NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, // 查询条件,提醒时间比当前时间更晚且类型为Note + new String[] { String.valueOf(currentDate) }, // 查询参数,当前时间 null); + // 对查询结果进行遍历转换 if (c != null) { if (c.moveToFirst()) { do { + // 获取提醒时间和Note的ID,以创建相应的PendingIntent long alertDate = c.getLong(COLUMN_ALERTED_DATE); Intent sender = new Intent(context, AlarmReceiver.class); sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); - AlarmManager alermManager = (AlarmManager) context - .getSystemService(Context.ALARM_SERVICE); - alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); + // 将提醒时间设置为对应的闹钟时间,并创建相应的闹钟事件 + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + alarmManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); } while (c.moveToNext()); } - c.close(); + c.close(); // 关闭游标 } } -} +} \ No newline at end of file diff --git a/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java b/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java index 54e503b..833682a 100644 --- a/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java +++ b/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java @@ -21,10 +21,12 @@ import android.content.Context; import android.content.Intent; public class AlarmReceiver extends BroadcastReceiver { - @Override + // 监听AlarmManager的闹钟事件,接收到事件后启动提醒界面 public void onReceive(Context context, Intent intent) { + // 指定启动的Activity为AlarmAlertActivity,并添加NEW_TASK标志,使其在新的任务栈上启动 intent.setClass(context, AlarmAlertActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // 启动指定Activity context.startActivity(intent); } } diff --git a/app/src/main/java/net/micode/notes/ui/DateTimePicker.java b/app/src/main/java/net/micode/notes/ui/DateTimePicker.java index 496b0cd..9f2ef0f 100644 --- a/app/src/main/java/net/micode/notes/ui/DateTimePicker.java +++ b/app/src/main/java/net/micode/notes/ui/DateTimePicker.java @@ -30,6 +30,7 @@ import android.widget.NumberPicker; public class DateTimePicker extends FrameLayout { + // 定义一些常量,包括默认开启状态、半天和一天的小时数、一周的天数、各个数字选择器的取值范围等 private static final boolean DEFAULT_ENABLE_STATE = true; private static final int HOURS_IN_HALF_DAY = 12; @@ -46,29 +47,34 @@ public class DateTimePicker extends FrameLayout { private static final int AMPM_SPINNER_MIN_VAL = 0; private static final int AMPM_SPINNER_MAX_VAL = 1; - private final NumberPicker mDateSpinner; - private final NumberPicker mHourSpinner; - private final NumberPicker mMinuteSpinner; - private final NumberPicker mAmPmSpinner; - private Calendar mDate; + private final NumberPicker mDateSpinner; // 日期选择器 + private final NumberPicker mHourSpinner; // 小时选择器 + private final NumberPicker mMinuteSpinner; // 分钟选择器 + private final NumberPicker mAmPmSpinner; // 上午/下午选择器 + private Calendar mDate; // 日期对象 - private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; + private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; // 显示的日期字符串 - private boolean mIsAm; + private boolean mIsAm; // 当前是上午还是下午 - private boolean mIs24HourView; + private boolean mIs24HourView; // 是否以24小时制显示时间 - private boolean mIsEnabled = DEFAULT_ENABLE_STATE; + private boolean mIsEnabled = DEFAULT_ENABLE_STATE; // 当前是否处于开启状态 - private boolean mInitialising; + private boolean mInitialising; // 是否正在初始化 - private OnDateTimeChangedListener mOnDateTimeChangedListener; + private OnDateTimeChangedListener mOnDateTimeChangedListener; // 日期时间变化监听器 + // 定义一个日期选择监听器,用于在用户调整日期选择器后更新日期值,并回调日期时间变化监听器 private NumberPicker.OnValueChangeListener mOnDateChangedListener = new NumberPicker.OnValueChangeListener() { + // 当日期选择器的值改变时,更新日历的日期,更新日期显示,触发日期时间变化监听器 @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + // 计算日期变化的天数,并更新日历对象 mDate.add(Calendar.DAY_OF_YEAR, newVal - oldVal); + // 更新日期选择器显示的日期 updateDateControl(); + // 通知监听器选择的日期时间发生变化 onDateTimeChanged(); } }; @@ -115,52 +121,77 @@ public class DateTimePicker extends FrameLayout { } }; - private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { + // 定义一个小时选择监听器,用于在用户调整小时选择器后更新日期时间值,并回调日期时间变化监听器 + private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { + // 当小时选择器的值发生改变时,更新日期时间对象,并触发日期时间变化监听器 @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { - int minValue = mMinuteSpinner.getMinValue(); - int maxValue = mMinuteSpinner.getMaxValue(); - int offset = 0; - if (oldVal == maxValue && newVal == minValue) { - offset += 1; - } else if (oldVal == minValue && newVal == maxValue) { - offset -= 1; - } - if (offset != 0) { - mDate.add(Calendar.HOUR_OF_DAY, offset); - mHourSpinner.setValue(getCurrentHour()); - updateDateControl(); - int newHour = getCurrentHourOfDay(); - if (newHour >= HOURS_IN_HALF_DAY) { - mIsAm = false; - updateAmPmControl(); - } else { - mIsAm = true; + boolean isDateChanged = false; // 标识日期是否发生了变化 + Calendar cal = Calendar.getInstance(); // 创建当前日期时间对象 + + // 根据当前是否是24小时制和是否跨越上下午进行不同的变化处理和计算 + if (!mIs24HourView) { // 不是24小时制 + if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) { // 跨越中午 + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); // 将日期向后推一天 + isDateChanged = true; + } else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { // 跨越中午 + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); // 将日期向前推一天 + isDateChanged = true; + } + if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY || oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + // 跨越中午后需要更新上午/下午的显示 + mIsAm = !mIsAm; updateAmPmControl(); } + } else { // 是24小时制 + if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) { // 跨越0点 + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); // 将日期向后推一天 + isDateChanged = true; + } else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) { // 跨越0点 + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); // 将日期向前推一天 + isDateChanged = true; + } + } + // 根据当前是否为上午、24小时制和选择的小时数计算出新的小时数 + int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); + mDate.set(Calendar.HOUR_OF_DAY, newHour); // 更新日历对象中的小时数 + onDateTimeChanged(); // 通知监听器日期时间变化事件 + + if (isDateChanged) { + // 如果日期发生变化,则需要更新日期选择器的显示 + setCurrentYear(cal.get(Calendar.YEAR)); + setCurrentMonth(cal.get(Calendar.MONTH)); + setCurrentDay(cal.get(Calendar.DAY_OF_MONTH)); } - mDate.set(Calendar.MINUTE, newVal); - onDateTimeChanged(); } }; private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + // 每次选择AM/PM时,切换mIsAm标志位 mIsAm = !mIsAm; + // 根据选择的AM/PM更新时间 if (mIsAm) { mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY); } else { mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY); } + // 更新AM/PM控件的状态 updateAmPmControl(); + // 回调onDateTimeChanged方法,通知监听器时间发生了变化 onDateTimeChanged(); } }; public interface OnDateTimeChangedListener { + // 定义onDateTimeChanged方法 void onDateTimeChanged(DateTimePicker view, int year, int month, - int dayOfMonth, int hourOfDay, int minute); + int dayOfMonth, int hourOfDay, int minute); } public DateTimePicker(Context context) {