精读标注

pull/1/head
lyy 1 year ago
parent b38189d2e9
commit 04d774fb4f

Binary file not shown.

@ -62,7 +62,7 @@ public class Note {//单个便签项
Log.e(TAG, "Get note id error :" + e.toString());
noteId = 0;
}//验证noteID是否正确
/**
/*
* try-catch
* uri.getPathSegments()uriURI(/)
* get(1)0
@ -122,7 +122,7 @@ public class Note {//单个便签项
return true;
}//没修改不需要同步
/**
/*
* In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and
* {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update thenote data info
* LOCAL_MODIFIEDMODIFIED_DATE使

@ -213,7 +213,6 @@ public class WorkingNote {//当前活动便签项
/**
* Update widget content if there exist any widget of this note
*
*/
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE

@ -41,79 +41,127 @@ import java.io.IOException;
public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener {//闹铃提醒界面
private long mNoteId;
private String mSnippet;
private long mNoteId;//文本在数据库存储中的ID号
private String mSnippet;//闹钟提示时出现的文本片段
private static final int SNIPPET_PREW_MAX_LEN = 60;
MediaPlayer mPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
//onCreate 方法是 Activity 生命周期中的一个重要方法,当 Activity 第一次被创建时调用。
//Bundle类型的数据与Map类型的数据相似都是以key-value的形式存储数据的
// Bundle 类型的参数 savedInstanceState是用来保存之前该 Activity 的状态,如果 Activity 之前被销毁(例如由于屏幕旋转)并且现在重新创建,那么 savedInstanceState 将包含之前保存的状态数据。
super.onCreate(savedInstanceState);
//能从父类Activity的onCreate方法的参数savedInsanceState中获得状态数据
requestWindowFeature(Window.FEATURE_NO_TITLE);
//移除标题栏
//在Android应用中创建一个新的Activity时默认情况下该Activity会有一个标题栏它通常显示应用的名字和Activity的标题
//如果不想显示这个标题栏,需要在调用 setContentView() 方法之前,首先调用 requestWindowFeature() 方法。这是因为一旦你设置了内容视图,窗口的一些特性(包括标题栏)就已经被确定了,此时再更改它们将不会有任何效果。
final Window win = getWindow();
//getWindow(): 这是一个常用于Android的Activity类中的方法。它返回与当前Activity关联的Window对象。Window对象代表了Activity的视图层次结构的顶层容器它控制着如何显示这个视图。
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
//addFlags(...): 这是Window类的一个方法用于给窗口添加特定的标志。这些标志会影响窗口的显示和行为。
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();
//Intent 是一个消息传递对象。当你从另一个 Activity 启动一个新的 Activity 时,你通常会创建一个 Intent 对象来指定你想要启动的目标 Activity 以及可能传递给它的一些数据
//getIntent() 方法允许你访问启动当前 Activity 的 Intent从而可以从中提取传递过来的数据或执行其他与 Intent 相关的操作。
try {
mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1));
/*
*ActivityActivity使IntentsetData()Activity使getData()
*getPathSegments()UriUriList<String>
*get(1)List<String>1Java0get(1)
*Long.valueOf()LongLong
*/
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;
//如果mSnippet的长度超过SNIPPET_PREW_MAX_LEN则只保留其前SNIPPET_PREW_MAX_LEN个字符并在其后附加一个从资源文件中获取的字符串。
//如果mSnippet的长度没有超过SNIPPET_PREW_MAX_LEN则mSnippet的值不变。
} catch (IllegalArgumentException e) {
e.printStackTrace();
return;
}
}//当IllegalArgumentException异常被抛出时捕获它并打印出关于该异常的详细信息
//IllegalArgumentException 是一个用于指示方法调用者传递了不合法或不适当参数的异常
mPlayer = new MediaPlayer();
//MediaPlayer是Android中用于播放音频文件的类。
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
showActionDialog();
//弹出对话框
playAlarmSound();
//闹钟提示音激发
} else {
finish();
//完成闹钟动作
}
}
private boolean isScreenOn() {
//判断屏幕是否锁屏,调用系统函数判断,最后返回值是布尔类型
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
//PowerManager: 这是一个Android的系统级服务允许应用程序控制设备的电源状态例如使设备进入睡眠状态或唤醒设备
//getSystemService(): 这是一个Context类的方法用于获取系统级别的服务。在Android中许多核心功能如闹钟、通知、电源管理等都是通过这种方式提供的。
//Context.POWER_SERVICE: 这是一个常量,表示电源管理服务的名称
return pm.isScreenOn();
}
private void playAlarmSound() {
////闹钟提示音激发
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM);
//调用系统的铃声管理URI得到闹钟提示音
//URL是Internet上用来描述信息资源的字符串主要用在各种WWW客户程序和服务器程序上。采用URL可以用一种统一的格式来描述各种信息资源包括文件、服务器的地址和目录等。URL的格式由三部分组成第一部分是协议第二部分是存有该资源的主机IP地址有时也包括端口号第三部分是主机资源的具体地址如目录和文件名等。第一部分和第二部分之间用"://"符号隔开,第二部分和第三部分用"/"符号隔开。
int silentModeStreams = Settings.System.getInt(getContentResolver(),
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
//从Android系统设置中获取“静音模式”会影响哪些声音流的设置
if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) {
//如果静音并且静音影响闹钟
mPlayer.setAudioStreamType(silentModeStreams);
//将mPlayer这个MediaPlayer对象的音频流类型设置为静音
} else {
mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
//将mPlayer这个MediaPlayer对象的音频流类型设置为闹钟
}
try {
mPlayer.setDataSource(this, url);
//设置媒体播放的数据源
mPlayer.prepare();
//加载媒体资源当你有一个媒体文件的路径或URI时你可以使用 setDataSource() 方法来设置这个资源。之后,调用 prepare() 方法会加载这个资源到 MediaPlayer 对象中。
//同步prepare() 方法是同步的,这意味着它会阻塞当前线程直到媒体资源准备完毕。
mPlayer.setLooping(true);
//设置是否循环播放
mPlayer.start();
//开始播放
} catch (IllegalArgumentException e) {
//当向方法传递了一个不合法或不适当的参数时,就会抛出 IllegalArgumentException
// TODO Auto-generated catch block
e.printStackTrace();
//这个方法的功能是打印异常的堆栈跟踪信息。当异常发生时,这个方法会输出异常的详细信息,包括异常的类型、异常发生的位置(类名、方法名、行号)以及异常发生时的调用栈信息。这对于调试和定位问题非常有帮助
} catch (SecurityException e) {
//种异常通常与Java的安全管理器有关当代码试图执行某些受保护的操作如访问文件、网络等而未被授权时会抛出这种异常。
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
//当一个对象处于某种状态,而此状态下该对象不应该被调用某些方法时,如果这些方法被调用了,那么就会抛出 IllegalStateException 异常。
//这种异常通常是由于编程错误或设计错误引起的,例如在多线程环境中,一个线程试图修改一个正在被另一个线程使用的对象。
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
//当Java程序无法正常读取或写入数据流时就会抛出IOException。IOException是一个广泛的异常类型它涵盖了各种文件和网络操作中可能出现的错误情况。例如当试图打开不存在的文件或目录或者无法访问文件或目录时会发生IOException。IOException类提供了一些方法来获取有关错误的详细信息例如getMessage()方法返回错误消息的详细描述getCause()方法返回导致IOException的根本原因。
// TODO Auto-generated catch block
e.printStackTrace();
}
@ -121,37 +169,57 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
private void showActionDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
//AlertDialog的构造方法全部是Protected的所以不能直接通过new一个AlertDialog来创建出一个AlertDialog。要创建一个AlertDialog就要用到AlertDialog.Builder中的create()方法
dialog.setTitle(R.string.app_name);
//为对话框设置标题
dialog.setMessage(mSnippet);
//为对话框设置内容
dialog.setPositiveButton(R.string.notealert_ok, this);
//给对话框添加"Yes"按钮
if (isScreenOn()) {
dialog.setNegativeButton(R.string.notealert_enter, this);
}
}//对话框添加"No"按钮
dialog.show().setOnDismissListener(this);
//show() 是 Dialog 类的一个方法,用于显示对话框
//setOnDismissListener 是 Dialog 类的一个方法,用于设置对话框关闭时的监听器。
//this 通常指代当前的Activity或Fragment意味着当对话框关闭时会回调当前Activity或Fragment中实现的 onDismiss 方法。
}
public void onClick(DialogInterface dialog, int which) {
switch (which) {
//用which来选择click后下一步的操作
case DialogInterface.BUTTON_NEGATIVE:
//这是取消操作
Intent intent = new Intent(this, NoteEditActivity.class);
//实现两个类间的数据传输
intent.setAction(Intent.ACTION_VIEW);
//设置动作属性
intent.putExtra(Intent.EXTRA_UID, mNoteId);
//实现key-value对
//EXTRA_UID为keymNoteId为键
startActivity(intent);
//开始动作
break;
default:
//这是确定操作
break;
}
}
public void onDismiss(DialogInterface dialog) {
//忽略
stopAlarmSound();
//停止闹钟声音
finish();
//完成该动作
}
private void stopAlarmSound() {
if (mPlayer != null) {
mPlayer.stop();
//停止播放
mPlayer.release();
//释放MediaPlayer对象
mPlayer = null;
}
}

@ -34,6 +34,7 @@ public class AlarmInitReceiver extends BroadcastReceiver {//闹铃提醒启动
NoteColumns.ID,
NoteColumns.ALERTED_DATE
};
//对数据库的操作调用标签ID和闹钟时间
private static final int COLUMN_ID = 0;
private static final int COLUMN_ALERTED_DATE = 1;
@ -41,25 +42,35 @@ public class AlarmInitReceiver extends BroadcastReceiver {//闹铃提醒启动
@Override
public void onReceive(Context context, Intent intent) {
long currentDate = System.currentTimeMillis();
Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
//System.currentTimeMillis()产生一个当前的毫秒
//这个毫秒其实就是自1970年1月1日0时起的毫秒数
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);
//将long变量currentDate转化为字符串
//Cursor在这里的作用是通过查找数据库中的标签内容找到和当前系统时间相等的标签
if (c != null) {
if (c.moveToFirst()) {
//moveToFirst()方法尝试将Cursor的定位移动到第一条记录。如果Cursor是空的即没有记录则此方法返回false。如果moveToFirst()返回true说明Cursor至少有一条记录那么将执行括号内的代码。
do {
long alertDate = c.getLong(COLUMN_ALERTED_DATE);
//从当前Cursor的记录中获取名为COLUMN_ALERTED_DATE的列的值并将其存储为long类型的alertDate。这通常是提醒的日期和时间。
Intent sender = new Intent(context, AlarmReceiver.class);
//创建一个新的Intent对象该对象用于启动名为AlarmReceiver的BroadcastReceiver。
sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID)));
//设置Intent的数据。这通常用于标识与特定闹钟提醒相关联的笔记或记录
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0);
AlarmManager alermManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
//创建一个PendingIntent对象。这是一个可以被多次使用例如用于多次触发闹钟的Intent
AlarmManager alermManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
//获取AlarmManager服务的实例该服务用于设置、修改或删除闹钟提醒。
alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent);
} while (c.moveToNext());
//使用AlarmManager的set方法设置一个闹钟提醒。AlarmManager.RTC_WAKEUP表示闹钟应该在系统时间到达alertDate时唤醒设备。pendingIntent是当闹钟触发时要执行的Intent
} while (c.moveToNext());//将Cursor的定位移动到下一条记录。如果Cursor还有下一条记录则循环继续
}
c.close();
c.close();//关闭Cursor
}
//这段代码的主要目的是从某个数据库中读取一系列记录的提醒日期并为每个记录设置一个闹钟提醒。当这些日期到达时AlarmReceiver将被触发。
}
}

Loading…
Cancel
Save