diff --git a/java/net/micode/notes/tool/BackupUtils.java b/java/net/micode/notes/tool/BackupUtils.java index 79ed1c7..dbb04c1 100644 --- a/java/net/micode/notes/tool/BackupUtils.java +++ b/java/net/micode/notes/tool/BackupUtils.java @@ -39,10 +39,15 @@ import java.io.PrintStream; public class BackupUtils { private static final String TAG = "BackupUtils"; // Singleton stuff - private static BackupUtils sInstance; + private static BackupUtils sInstance;//类里面为什么可以定义自身类的对象? public static synchronized BackupUtils getInstance(Context context) { + //ynchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A) + //运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。 + //它包括两种用法:synchronized 方法和 synchronized 块。 + if (sInstance == null) { + //如果当前备份不存在,则新声明一个 sInstance = new BackupUtils(context); } return sInstance; @@ -65,10 +70,12 @@ public class BackupUtils { private TextExport mTextExport; + //初始化函数 private BackupUtils(Context context) { mTextExport = new TextExport(context); } + //外部存储功能是否可用 private static boolean externalStorageAvailable() { return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); } @@ -146,7 +153,7 @@ public class BackupUtils { folderId }, null); - if (notesCursor != null) { + if (notesCursor != null) {//利用光标来扫描内容,区别为callnote和note两种,靠ps.printline输出 if (notesCursor.moveToFirst()) { do { // Print note's last modified date @@ -218,7 +225,7 @@ public class BackupUtils { /** * Note will be exported as text which is user readable */ - public int exportToText() { + public int exportToText() {//总函数,调用上面的exportFolder和exportNote if (!externalStorageAvailable()) { Log.d(TAG, "Media was not mounted"); return STATE_SD_CARD_UNMOUONTED; diff --git a/java/net/micode/notes/tool/DataUtils.java b/java/net/micode/notes/tool/DataUtils.java index 2a14982..c184244 100644 --- a/java/net/micode/notes/tool/DataUtils.java +++ b/java/net/micode/notes/tool/DataUtils.java @@ -52,13 +52,13 @@ public class DataUtils { if(id == Notes.ID_ROOT_FOLDER) { Log.e(TAG, "Don't delete system folder root"); continue; - } + }//如果发现是根文件夹,则不删除 ContentProviderOperation.Builder builder = ContentProviderOperation .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); operationList.add(builder.build()); } try { - ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); //数据库事务,数据库事务是由一组数据库操作序列组成,事务作为一个整体被执行 if (results == null || results.length == 0 || results[0] == null) { Log.d(TAG, "delete notes failed, ids:" + ids.toString()); return false; diff --git a/java/net/micode/notes/ui/AlarmAlertActivity.java b/java/net/micode/notes/ui/AlarmAlertActivity.java index 5bf372d..85723be 100644 --- a/java/net/micode/notes/ui/AlarmAlertActivity.java +++ b/java/net/micode/notes/ui/AlarmAlertActivity.java @@ -1,3 +1,19 @@ +/* + * 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; @@ -23,81 +39,58 @@ 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 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); - //Bundle类型的数据与Map类型的数据相似,都是以key-value的形式存储数据的 - //onsaveInstanceState方法是用来保存Activity的状态的 - //能从onCreate的参数savedInsanceState中获得状态数据 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); - //根据ID从数据库中获取标签的内容; - //getContentResolver()是实现数据共享,实例存储。 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; } - /* - try - { - // 代码区 - } - catch(Exception e) - { - // 异常处理 - } - 代码区如果有错误,就会返回所写异常的处理。*/ + 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); - //调用系统的铃声管理URI,得到闹钟提示音 + int silentModeStreams = Settings.System.getInt(getContentResolver(), Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); @@ -108,19 +101,12 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD } try { mPlayer.setDataSource(this, url); - //方法:setDataSource(Context context, Uri uri) - //解释:无返回值,设置多媒体数据来源【根据 Uri】 mPlayer.prepare(); - //准备同步 mPlayer.setLooping(true); - //设置是否循环播放 mPlayer.start(); - //开始播放 } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); - //e.printStackTrace()函数功能是抛出异常, 还将显示出更深的调用信息 - //System.out.println(e),这个方法打印出异常,并且输出在哪里出现的异常 } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -135,58 +121,38 @@ 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就是新建了一个AlertDialog 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); } 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为key;mNoteId为键 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; } } -} \ No newline at end of file +} diff --git a/java/net/micode/notes/ui/AlarmInitReceiver.java b/java/net/micode/notes/ui/AlarmInitReceiver.java index f1c1c37..f221202 100644 --- a/java/net/micode/notes/ui/AlarmInitReceiver.java +++ b/java/net/micode/notes/ui/AlarmInitReceiver.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package net.micode.notes.ui; import android.app.AlarmManager; @@ -30,25 +31,21 @@ import net.micode.notes.data.Notes.NoteColumns; public class AlarmInitReceiver extends BroadcastReceiver { private static final String [] PROJECTION = new String [] { - NoteColumns.ID, - NoteColumns.ALERTED_DATE + NoteColumns.ID, + NoteColumns.ALERTED_DATE }; - //对数据库的操作,调用标签ID和闹钟时间 + private static final int COLUMN_ID = 0; private static final int COLUMN_ALERTED_DATE = 1; @Override public void onReceive(Context context, Intent intent) { long currentDate = System.currentTimeMillis(); - //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) }, - //将long变量currentDate转化为字符串 null); - //Cursor在这里的作用是通过查找数据库中的标签内容,找到和当前系统时间相等的标签 if (c != null) { if (c.moveToFirst()) { @@ -64,8 +61,5 @@ public class AlarmInitReceiver extends BroadcastReceiver { } c.close(); } - //然而通过网上查找资料发现,对于闹钟机制的启动,通常需要上面的几个步骤 - //如新建Intent、PendingIntent以及AlarmManager等 - //这里就是根据数据库里的闹钟时间创建一个闹钟机制 } -} \ No newline at end of file +} diff --git a/java/net/micode/notes/ui/AlarmReceiver.java b/java/net/micode/notes/ui/AlarmReceiver.java index c98495d..54e503b 100644 --- a/java/net/micode/notes/ui/AlarmReceiver.java +++ b/java/net/micode/notes/ui/AlarmReceiver.java @@ -24,13 +24,7 @@ public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { intent.setClass(context, AlarmAlertActivity.class); - //启动AlarmAlertActivity intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - //activity要存在于activity的栈中,而非activity的途径启动activity时必然不存在一个activity的栈 - //所以要新起一个栈装入启动的activity context.startActivity(intent); } } -//这是实现alarm这个功能最接近用户层的包,基于上面的两个包, -//作用还需要深究但是对于setClass和addFlags的 - diff --git a/java/net/micode/notes/ui/DateTimePicker.java b/java/net/micode/notes/ui/DateTimePicker.java index 7cda91e..496b0cd 100644 --- a/java/net/micode/notes/ui/DateTimePicker.java +++ b/java/net/micode/notes/ui/DateTimePicker.java @@ -29,8 +29,7 @@ import android.widget.FrameLayout; import android.widget.NumberPicker; public class DateTimePicker extends FrameLayout { - //FrameLayout是布局模板之一 - //所有的子元素全部在屏幕的右上方 + private static final boolean DEFAULT_ENABLE_STATE = true; private static final int HOURS_IN_HALF_DAY = 12; @@ -46,15 +45,13 @@ public class DateTimePicker extends FrameLayout { private static final int MINUT_SPINNER_MAX_VAL = 59; 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; - //NumberPicker是数字选择器 - //这里定义的四个变量全部是在设置闹钟时需要选择的变量(如日期、时、分、上午或者下午) private Calendar mDate; - //定义了Calendar类型的变量mDate,用于操作时间 + private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; private boolean mIsAm; @@ -74,49 +71,41 @@ public class DateTimePicker extends FrameLayout { updateDateControl(); onDateTimeChanged(); } - };//OnValueChangeListener,这是时间改变监听器,这里主要是对日期的监听 - //将现在日期的值传递给mDate;updateDateControl是同步操作 + }; private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { - //这里是对 小时(Hour) 的监听 @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { boolean isDateChanged = false; Calendar cal = Calendar.getInstance(); - //声明一个Calendar的变量cal,便于后续的操作 if (!mIs24HourView) { 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; - //这里是对于12小时制时,晚上11点和12点交替时对日期的更改 } 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; } - //这里是对于12小时制时,凌晨11点和12点交替时对日期的更改 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(); - }//这里是对于12小时制时,中午11点和12点交替时对AM和PM的更改 + } } else { if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) { cal.setTimeInMillis(mDate.getTimeInMillis()); cal.add(Calendar.DAY_OF_YEAR, 1); isDateChanged = true; - //这里是对于24小时制时,晚上11点和12点交替时对日期的更改 } else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) { cal.setTimeInMillis(mDate.getTimeInMillis()); cal.add(Calendar.DAY_OF_YEAR, -1); isDateChanged = true; } - } //这里是对于12小时制时,凌晨11点和12点交替时对日期的更改 + } int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); - //通过数字选择器对newHour的赋值 mDate.set(Calendar.HOUR_OF_DAY, newHour); - //通过set函数将新的Hour值传给mDate onDateTimeChanged(); if (isDateChanged) { setCurrentYear(cal.get(Calendar.YEAR)); @@ -128,19 +117,15 @@ public class DateTimePicker extends FrameLayout { private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { @Override - //这里是对 分钟(Minute)改变的监听 public void onValueChange(NumberPicker picker, int oldVal, int newVal) { int minValue = mMinuteSpinner.getMinValue(); int maxValue = mMinuteSpinner.getMaxValue(); int offset = 0; - //设置offset,作为小时改变的一个记录数据 if (oldVal == maxValue && newVal == minValue) { offset += 1; } else if (oldVal == minValue && newVal == maxValue) { offset -= 1; } - //如果原值为59,新值为0,则offset加1 - //如果原值为0,新值为59,则offset减1 if (offset != 0) { mDate.add(Calendar.HOUR_OF_DAY, offset); mHourSpinner.setValue(getCurrentHour()); @@ -160,7 +145,6 @@ public class DateTimePicker extends FrameLayout { }; private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { - //对AM和PM的监听 @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { mIsAm = !mIsAm; @@ -176,27 +160,24 @@ public class DateTimePicker extends FrameLayout { public interface OnDateTimeChangedListener { void onDateTimeChanged(DateTimePicker view, int year, int month, - int dayOfMonth, int hourOfDay, int minute); + int dayOfMonth, int hourOfDay, int minute); } public DateTimePicker(Context context) { this(context, System.currentTimeMillis()); - }//通过对数据库的访问,获取当前的系统时间 + } public DateTimePicker(Context context, long date) { this(context, date, DateFormat.is24HourFormat(context)); - }//上面函数的得到的是一个天文数字(1970至今的秒数),需要DateFormat将其变得有意义 + } public DateTimePicker(Context context, long date, boolean is24HourView) { super(context); - //获取系统时间 mDate = Calendar.getInstance(); mInitialising = true; mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY; inflate(context, R.layout.datetime_picker, this); - //如果当前Activity里用到别的layout,比如对话框layout - //还要设置这个layout上的其他组件的内容,就必须用inflate()方法先将对话框的layout找出来 - //然后再用findViewById()找到它上面的其它组件 + mDateSpinner = (NumberPicker) findViewById(R.id.date); mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); @@ -204,7 +185,7 @@ public class DateTimePicker extends FrameLayout { mHourSpinner = (NumberPicker) findViewById(R.id.hour); mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); - mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); + mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL); mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL); mMinuteSpinner.setOnLongPressUpdateInterval(100); @@ -245,9 +226,7 @@ public class DateTimePicker extends FrameLayout { mAmPmSpinner.setEnabled(enabled); mIsEnabled = enabled; } - //存在疑问!!!!!!!!!!!!!setEnabled的作用 - //下面的代码通过原程序的注释已经比较清晰,另外可以通过函数名来判断 - //下面的各函数主要是对上面代码引用到的各函数功能的实现 + @Override public boolean isEnabled() { return mIsEnabled; @@ -260,7 +239,7 @@ public class DateTimePicker extends FrameLayout { */ public long getCurrentDateInTimeMillis() { return mDate.getTimeInMillis(); - }//实现函数——得到当前的秒数 + } /** * Set the current date @@ -272,7 +251,7 @@ public class DateTimePicker extends FrameLayout { cal.setTimeInMillis(date); setCurrentDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); - }//实现函数功能——设置当前的时间,参数是date + } /** * Set the current date @@ -284,20 +263,19 @@ public class DateTimePicker extends FrameLayout { * @param minute The current minute */ public void setCurrentDate(int year, int month, - int dayOfMonth, int hourOfDay, int minute) { + int dayOfMonth, int hourOfDay, int minute) { setCurrentYear(year); setCurrentMonth(month); setCurrentDay(dayOfMonth); setCurrentHour(hourOfDay); setCurrentMinute(minute); - }//实现函数功能——设置当前的时间,参数是各详细的变量 + } /** * Get current year * * @return The current year */ - //下面是得到year、month、day等值 public int getCurrentYear() { return mDate.get(Calendar.YEAR); } @@ -468,7 +446,7 @@ public class DateTimePicker extends FrameLayout { mDateSpinner.setDisplayedValues(mDateDisplayValues); mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); mDateSpinner.invalidate(); - }// 对于星期几的算法 + } private void updateAmPmControl() { if (mIs24HourView) { @@ -477,7 +455,7 @@ public class DateTimePicker extends FrameLayout { int index = mIsAm ? Calendar.AM : Calendar.PM; mAmPmSpinner.setValue(index); mAmPmSpinner.setVisibility(View.VISIBLE); - }// 对于上下午操作的算法 + } } private void updateHourControl() { @@ -487,7 +465,7 @@ public class DateTimePicker extends FrameLayout { } else { mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); - }// 对与小时的算法 + } } /** @@ -504,4 +482,4 @@ public class DateTimePicker extends FrameLayout { getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); } } -} \ No newline at end of file +}