gaoliuyang_br
13365576176 2 years ago
parent f45011f7ac
commit 3b39ffddeb

@ -0,0 +1 @@
Subproject commit 4f9b53791b00b089343a4919af9ad7ac765b751f

@ -20,7 +20,7 @@
android:versionCode="1"
android:versionName="0.1" >
<uses-sdk android:minSdkVersion="14" />
<uses-sdk android:minSdkVersion="17" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
@ -36,12 +36,12 @@
android:icon="@drawable/icon_app"
android:label="@string/app_name" >
<activity
android:name=".ui.NotesListActivity"
android:name=".ui.LoginView"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:uiOptions="splitActionBarWhenNarrow"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan" >
<intent-filter>
@ -50,6 +50,36 @@
</intent-filter>
</activity>
<activity
android:name=".ui.LoginActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan" >
</activity>
<activity
android:name=".ui.ChangeLoginPasswordActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan" >
</activity>
<activity
android:name=".ui.NotesListActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:uiOptions="splitActionBarWhenNarrow"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan" >
</activity>
<activity
android:name=".ui.NoteEditActivity"
android:configChanges="keyboardHidden|orientation|screenSize"

@ -26,7 +26,7 @@ import android.util.Log;
import java.util.HashMap;
public class Contact {
private static HashMap<String, String> sContactCache;
private static HashMap<String, String> sContactCache;//联系人缓存
private static final String TAG = "Contact";
private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER
@ -34,7 +34,7 @@ public class Contact {
+ " AND " + Data.RAW_CONTACT_ID + " IN "
+ "(SELECT raw_contact_id "
+ " FROM phone_lookup"
+ " WHERE min_match = '+')";
+ " WHERE min_match = '+')";//规定SQL查询语句
public static String getContact(Context context, String phoneNumber) {
if(sContactCache == null) {
@ -52,8 +52,8 @@ public class Contact {
new String [] { Phone.DISPLAY_NAME },
selection,
new String[] { phoneNumber },
null);
null);//进行缓存查询。如果缓存没有填充SQL查询语言
//进行查询并返回结果
if (cursor != null && cursor.moveToFirst()) {
try {
String name = cursor.getString(0);

@ -32,7 +32,7 @@ public class MetaData extends Task {
public void setMeta(String gid, JSONObject metaInfo) {
try {
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);//将gid放进去
} catch (JSONException e) {
Log.e(TAG, "failed to put related gid");
}
@ -55,7 +55,7 @@ public class MetaData extends Task {
if (getNotes() != null) {
try {
JSONObject metaInfo = new JSONObject(getNotes().trim());
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);//从metaInfo中获取该字段的值。metaInfo应该是一个类似于数据集合的东西
} catch (JSONException e) {
Log.w(TAG, "failed to get related gid");
mRelatedGid = null;

@ -19,8 +19,9 @@ package net.micode.notes.gtask.data;
import android.database.Cursor;
import org.json.JSONObject;
//本地及云端数据更新、同步
public abstract class Node {
//下述常量用于表示对本地及云端数据的操作号
public static final int SYNC_ACTION_NONE = 0;
public static final int SYNC_ACTION_ADD_REMOTE = 1;
@ -43,7 +44,7 @@ public abstract class Node {
private String mName;
private long mLastModified;
private long mLastModified;//最后一次修改时间
private boolean mDeleted;
@ -54,7 +55,7 @@ public abstract class Node {
mDeleted = false;
}
public abstract JSONObject getCreateAction(int actionId);
public abstract JSONObject getCreateAction(int actionId);//actionId 可能是用于标识不同类型的创建操作的参数
public abstract JSONObject getUpdateAction(int actionId);
@ -64,7 +65,7 @@ public abstract class Node {
public abstract JSONObject getLocalJSONFromContent();
public abstract int getSyncAction(Cursor c);
public abstract int getSyncAction(Cursor c);//获取同步操作
public void setGid(String gid) {
this.mGid = gid;

@ -34,11 +34,11 @@ import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException;
import org.json.JSONObject;
//小米便签底层数据库相关操作
public class SqlData {
private static final String TAG = SqlData.class.getSimpleName();
private static final int INVALID_ID = -99999;
private static final int INVALID_ID = -99999;//无效ID
public static final String[] PROJECTION_DATA = new String[] {
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
@ -57,7 +57,7 @@ public class SqlData {
private ContentResolver mContentResolver;
private boolean mIsCreate;
private boolean mIsCreate;//用于表示sqldata初始化的两种方式
private long mDataId;
@ -71,6 +71,7 @@ public class SqlData {
private ContentValues mDiffDataValues;
//第一种初始化形式
public SqlData(Context context) {
mContentResolver = context.getContentResolver();
mIsCreate = true;
@ -96,7 +97,7 @@ public class SqlData {
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
//设置共享数据
public void setContent(JSONObject js) throws JSONException {
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
if (mIsCreate || mDataId != dataId) {
@ -125,7 +126,7 @@ public class SqlData {
String dataContentData3 = js.has(DataColumns.DATA3) ? js.getString(DataColumns.DATA3) : "";
if (mIsCreate || !mDataContentData3.equals(dataContentData3)) {
mDiffDataValues.put(DataColumns.DATA3, dataContentData3);
mDiffDataValues.put(DataColumns.DATA3, dataContentData3);//键值对
}
mDataContentData3 = dataContentData3;
}
@ -143,29 +144,34 @@ public class SqlData {
js.put(DataColumns.DATA3, mDataContentData3);
return js;
}
//将当前所做修改保存至数据库
//下面创建及更新两种不同操作有由IsCreate控制也对应了sqlData初始化的两种方式创建新的从cursor更新
//创建新数据笔记并将其同步至数据库
//感觉在这里mDiffdataValues代表需要新写的键值对(记录已发生更改的属性?),通常与数据库交互,保存数据变化,就是用户新编辑的。
// ContentResolver 是用于访问应用程序的数据存储区域的关键类之一。与应用程序的数据提供者(如数据库、内容提供器等)进行交互
public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) {
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
mDiffDataValues.remove(DataColumns.ID);
}
}//如果ID无效以及mDiffdataValues包含这个ID键值对移除这个键值对
mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);//把mDiffdataValues插到这个URI的位置
try {
mDataId = Long.valueOf(uri.getPathSegments().get(1));
mDataId = Long.valueOf(uri.getPathSegments().get(1));//再把这个uri对应的数据的ID取出来。如果提取失败说明创建失败
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
} else {
if (mDiffDataValues.size() > 0) {
//笔记更新
if (mDiffDataValues.size() > 0) { //说明有需要更新的
int result = 0;
if (!validateVersion) {
if (!validateVersion) { //如果版本不需要更新则直接对指定URI进行更新
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else {
} else { //版本与指定内容一起更新
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
" ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE

@ -37,12 +37,13 @@ import org.json.JSONObject;
import java.util.ArrayList;
//底层数据库操作是SqlData的父集。相对而言是真正意义上的数据
public class SqlNote {
private static final String TAG = SqlNote.class.getSimpleName();
private static final int INVALID_ID = -99999;
//PROJECTION_NOTE 里面包括了许多列的名字,在后面数据库查询中用到
public static final String[] PROJECTION_NOTE = new String[] {
NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE,
@ -51,7 +52,7 @@ public class SqlNote {
NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID,
NoteColumns.VERSION
};
//下面是17个列的编号
public static final int ID_COLUMN = 0;
public static final int ALERTED_DATE_COLUMN = 1;
@ -120,18 +121,19 @@ public class SqlNote {
private ContentValues mDiffNoteValues;
private ArrayList<SqlData> mDataList;
private ArrayList<SqlData> mDataList;//ArrayList是动态数组用于储存类型为SqlData的数据。
//SqlNote一种构造方式。这里为新建一个
public SqlNote(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = true;
mId = INVALID_ID;
mAlertDate = 0;
mBgColorId = ResourceParser.getDefaultBgId(context);
mCreatedDate = System.currentTimeMillis();
mBgColorId = ResourceParser.getDefaultBgId(context);//获取颜色、图片等元素ID用以渲染界面
mCreatedDate = System.currentTimeMillis();//当前系统时间
mHasAttachment = 0;
mModifiedDate = System.currentTimeMillis();
mModifiedDate = System.currentTimeMillis();//最后一次数据更新时间
mParentId = 0;
mSnippet = "";
mType = Notes.TYPE_NOTE;
@ -142,7 +144,7 @@ public class SqlNote {
mDiffNoteValues = new ContentValues();
mDataList = new ArrayList<SqlData>();
}
//初始化方式。通过cursor c初始化
public SqlNote(Context context, Cursor c) {
mContext = context;
mContentResolver = context.getContentResolver();
@ -150,31 +152,34 @@ public class SqlNote {
loadFromCursor(c);
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
loadDataContent();
loadDataContent();//数据加载等操作
mDiffNoteValues = new ContentValues();
}
//第三种初始化方式只不过这次也不是新建的。通过id初始化
public SqlNote(Context context, long id) {
mContext = context;
mContentResolver = context.getContentResolver();
//ContentResolver 是用于访问应用程序的数据存储区域的关键类之一。与应用程序的数据提供者(如数据库、内容提供器等)进行交互
mIsCreate = false;
loadFromCursor(id);
loadFromCursor(id);//将cursor数据下载到SqlNote
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
loadDataContent();
mDiffNoteValues = new ContentValues();
mDiffNoteValues = new ContentValues();//创建一个空的 ContentValues 对象,用于存储键值对数据,通常用于与数据库进行交互或保存数据的变化。
}
//从数据库中查询笔记数据,将结果加载到对象中(cursor c)
private void loadFromCursor(long id) {
Cursor c = null;
try {
//query查询函数。
//下面函数先匹配给的id与需要查询的id是否相同然后查询PROJECTION_NOTE里列的数据将其赋给c
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[] {
String.valueOf(id)
}, null);
if (c != null) {
c.moveToNext();
c.moveToNext();//移动游标读取数据
loadFromCursor(c);
} else {
Log.w(TAG, "loadFromCursor: cursor = null");
@ -199,7 +204,7 @@ public class SqlNote {
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
mVersion = c.getLong(VERSION_COLUMN);
}
//查询笔记数据内容
private void loadDataContent() {
Cursor c = null;
mDataList.clear();
@ -228,6 +233,7 @@ public class SqlNote {
public boolean setContent(JSONObject js) {
try {
//根据不同的便签类型操作。
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
Log.w(TAG, "cannot set system folder");
@ -253,7 +259,9 @@ public class SqlNote {
mDiffNoteValues.put(NoteColumns.ID, id);
}
mId = id;
//下面的操作是根据获得的新数据更新一些变量值。
// 其中m开的头的变量eg mBgColorId 表示当前的属性值)下面的代码就是根据新数据来更新这些值
//更新笔记提醒时间属性
long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note
.getLong(NoteColumns.ALERTED_DATE) : 0;
if (mIsCreate || mAlertDate != alertDate) {
@ -262,7 +270,7 @@ public class SqlNote {
mAlertDate = alertDate;
int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note
.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);
.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);//后面这个指获取默认的背景信息
if (mIsCreate || mBgColorId != bgColorId) {
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
}
@ -330,12 +338,13 @@ public class SqlNote {
mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);
}
mOriginParent = originParent;
//从mDataList中寻找与dataArray中ID相同的元素将其放入sqldata中
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
SqlData sqlData = null;
if (data.has(DataColumns.ID)) {
long dataId = data.getLong(DataColumns.ID);
//这个for循环为增强型即每次遍历mDataList中的一个数组并将这个数组赋给temp
for (SqlData temp : mDataList) {
if (dataId == temp.getId()) {
sqlData = temp;
@ -358,7 +367,7 @@ public class SqlNote {
}
return true;
}
//将笔记的属性及数据以json形式返回以便后续使用
public JSONObject getContent() {
try {
JSONObject js = new JSONObject();
@ -367,7 +376,7 @@ public class SqlNote {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
//下面是获得单个(或多个)便签对象的数据
JSONObject note = new JSONObject();
if (mType == Notes.TYPE_NOTE) {
note.put(NoteColumns.ID, mId);
@ -392,7 +401,7 @@ public class SqlNote {
}
}
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) { //这是获得文件夹的数据
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.SNIPPET, mSnippet);
@ -440,7 +449,9 @@ public class SqlNote {
return mType == Notes.TYPE_NOTE;
}
//数据提交或更新(将当前更改保存到数据库)
public void commit(boolean validateVersion) {
//创建新笔记
if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
mDiffNoteValues.remove(NoteColumns.ID);
@ -462,7 +473,7 @@ public class SqlNote {
sqlData.commit(mId, false, -1);
}
}
} else {
} else { //更新现有笔记
if (mId <= 0 && mId != Notes.ID_ROOT_FOLDER && mId != Notes.ID_CALL_RECORD_FOLDER) {
Log.e(TAG, "No such note");
throw new IllegalStateException("Try to update note with invalid id");
@ -486,7 +497,7 @@ public class SqlNote {
Log.w(TAG, "there is no update. maybe user updates note when syncing");
}
}
//提交关联数据
if (mType == Notes.TYPE_NOTE) {
for (SqlData sqlData : mDataList) {
sqlData.commit(mId, validateVersion, mVersion);
@ -495,9 +506,10 @@ public class SqlNote {
}
// refresh local info
loadFromCursor(mId);
//刷新本地信息
loadFromCursor(mId);//加载数据
if (mType == Notes.TYPE_NOTE)
loadDataContent();
loadDataContent();//加载数据内容
mDiffNoteValues.clear();
mIsCreate = false;

@ -49,8 +49,8 @@ public class Task extends Node {
super();
mCompleted = false;
mNotes = null;
mPriorSibling = null;
mParent = null;
mPriorSibling = null;//TaskList中当前task的前一个task
mParent = null;//当前task所在点List
mMetaInfo = null;
}
@ -66,8 +66,8 @@ public class Task extends Node {
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// index
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));//当前task在其父级task的索引
//构建一个包含任务的名称、创建者ID和实体类型信息的 JSON 对象entity
// entity_delta
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
@ -123,7 +123,7 @@ public class Task extends Node {
if (getNotes() != null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
}
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());//实体的删除状态
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) {
@ -135,6 +135,7 @@ public class Task extends Node {
return js;
}
//remote指云端数据库反正不是本地
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
@ -192,6 +193,7 @@ public class Task extends Node {
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
//如果这个data的mime_type与NOTE常量相同则将this所指代的对象的名字设为内容CONTENT)
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
setName(data.getString(DataColumns.CONTENT));
break;
@ -225,7 +227,7 @@ public class Task extends Node {
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
return js;
} else {
// synced task
// synced task 同步任务
JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
@ -247,17 +249,18 @@ public class Task extends Node {
}
}
//将metaData对象中的笔记信息假设是一个JSON字符串解析为一个JSON对象并将其赋值给mMetaInfo
public void setMetaInfo(MetaData metaData) {
if (metaData != null && metaData.getNotes() != null) {
try {
mMetaInfo = new JSONObject(metaData.getNotes());
mMetaInfo = new JSONObject(metaData.getNotes());//用getNodes中的信息初始化mMetaInfo
} catch (JSONException e) {
Log.w(TAG, e.toString());
mMetaInfo = null;
}
}
}
//数据库与本地数据同步
public int getSyncAction(Cursor c) {
try {
JSONObject noteInfo = null;
@ -312,7 +315,7 @@ public class Task extends Node {
}
public boolean isWorthSaving() {
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)//trim作用为去掉空格
|| (getNotes() != null && getNotes().trim().length() > 0);
}

@ -216,6 +216,8 @@ public class TaskList extends Node {
return SYNC_ACTION_ERROR;
}
//任务队列大小
public int getChildTaskCount() {
return mChildren.size();
}
@ -226,6 +228,7 @@ public class TaskList extends Node {
ret = mChildren.add(task);
if (ret) {
// need to set prior sibling and parent
//如果子任务链表为空则前一个兄弟任务为null如果不为空则将前一个子任务设置为当前任务末端。
task.setPriorSibling(mChildren.isEmpty() ? null : mChildren
.get(mChildren.size() - 1));
task.setParent(this);
@ -234,6 +237,7 @@ public class TaskList extends Node {
return ret;
}
//在某个位置插入一个子任务
public boolean addChildTask(Task task, int index) {
if (index < 0 || index > mChildren.size()) {
Log.e(TAG, "add child task: invalid index");
@ -281,6 +285,8 @@ public class TaskList extends Node {
return ret;
}
//移动某子任务到index位置
public boolean moveChildTask(Task task, int index) {
if (index < 0 || index >= mChildren.size()) {
@ -321,6 +327,7 @@ public class TaskList extends Node {
return mChildren.get(index);
}
//和308行函数的区别在于308行新建一个Task返回下面的直接把原本的Task返回
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))

@ -57,6 +57,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
mTaskManager.cancelSync();
}
//通知异步任务更新进度信息。
public void publishProgess(String message) {
publishProgress(new String[] {
message
@ -64,10 +65,15 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
}
private void showNotification(int tickerId, String content) {
//创建一个Notification对象并设置其图标、文本和时间戳等属性。其中R.drawable.notification表示通知的图标
// mContext.getString(tickerId)表示通知的文本System.currentTimeMillis()表示通知的时间戳。
Notification notification = new Notification(R.drawable.notification, mContext
.getString(tickerId), System.currentTimeMillis());
//将通知设置为默认显示灯光效果。
notification.defaults = Notification.DEFAULT_LIGHTS;
//将通知设置为默认显示灯光效果。
notification.flags = Notification.FLAG_AUTO_CANCEL;
PendingIntent pendingIntent;
if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
@ -77,17 +83,21 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0);
}
notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
pendingIntent);
//设置通知的最新事件信息包括应用程序名称、通知内容和要启动的pendingIntent。
//notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
// pendingIntent);
//显示通知并指定通知的标识符为GTASK_SYNC_NOTIFICATION_ID。
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
}
//更新进度信息,并执行后台的同步任务
@Override
protected Integer doInBackground(Void... unused) {
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
.getSyncAccountName(mContext)));
return mTaskManager.sync(mContext, this);
}
//后台任务执行过程中更新进度信息,并通过通知和广播将进度信息传递给其他组件
@Override
protected void onProgressUpdate(String... progress) {
@ -96,7 +106,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
((GTaskSyncService) mContext).sendBroadcast(progress[0]);
}
}
//异步任务执行完成后,根据任务执行的结果执行不同的操作,并通过通知和回调将结果传递给其他组件.
@Override
protected void onPostExecute(Integer result) {
if (result == GTaskManager.STATE_SUCCESS) {
@ -111,13 +121,15 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
showNotification(R.string.ticker_cancel, mContext
.getString(R.string.error_sync_cancelled));
}
//新开线程回调监听器
if (mOnCompleteListener != null) {
new Thread(new Runnable() {
public void run() {
//线程创建后执行以下操作
mOnCompleteListener.onComplete();
}
}).start();
}).start();//启动线程
}
}
}

@ -110,9 +110,9 @@ public class GTaskClient {
}
public boolean login(Activity activity) {
// we suppose that the cookie would expire after 5 minutes
// we suppose that the cookie would expire(失效) after 5 minutes
// then we need to re-login
final long interval = 1000 * 60 * 5;
final long interval = 1000 * 60 * 5;//5min的ms
if (mLastLoginTime + interval < System.currentTimeMillis()) {
mLoggedin = false;
}
@ -130,13 +130,14 @@ public class GTaskClient {
}
mLastLoginTime = System.currentTimeMillis();
String authToken = loginGoogleAccount(activity, false);
String authToken = loginGoogleAccount(activity, false);//谷歌账号登陆
if (authToken == null) {
Log.e(TAG, "login google account failed");
return false;
}
// login with custom domain if necessary
// login with custom domain if necessary 反正也是管登陆的.
//toLowerCase 字符串转成小写
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase()
.endsWith("googlemail.com"))) {
StringBuilder url = new StringBuilder(GTASK_URL).append("a/");
@ -176,6 +177,7 @@ public class GTaskClient {
String accountName = NotesPreferenceActivity.getSyncAccountName(activity);
Account account = null;
//遍历所有账户列表,看有没有和所给的一样的
for (Account a : accounts) {
if (a.name.equals(accountName)) {
account = a;
@ -189,7 +191,12 @@ public class GTaskClient {
return null;
}
// get the token now
//下面是获得目标账户认证令牌。
//调用accountManager.getAuthToken函数异步获取认证令牌返回的是一个AccountManagerFuture<Bundle>对象。
// 然后调用getResult方法尝试获取包含认证令牌的Bundle对象。如果成功获得该Bundle就从中提取出认证令牌并赋值给authToken。
// 如果invalidateToken标志为true那么就使当前的认证令牌失效并且再次调用loginGoogleAccount方法获取新的认证令牌。
// 如果在这个过程中捕获到任何异常就打印错误日志并将authToken设置为null。
// get the token now token有认证的意思
AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account,
"goanna_mobile", null, activity, null, null);
try {
@ -207,6 +214,7 @@ public class GTaskClient {
return authToken;
}
//如果刚开始没登录成功GTask那么我再取一次授权令牌再试一次如果还没成功则登陆gtask失败
private boolean tryToLoginGtask(Activity activity, String authToken) {
if (!loginGtask(authToken)) {
// maybe the auth token is out of date, now let's invalidate the
@ -225,10 +233,13 @@ public class GTaskClient {
return true;
}
//使用给出的authToken进行登录操作并获取客户端版本信息
private boolean loginGtask(String authToken) {
int timeoutConnection = 10000;
int timeoutSocket = 15000;
HttpParams httpParameters = new BasicHttpParams();
//下面是鼓捣http连接的。HttpClient是Apache HttpClient库提供的一个类用于设立HTTP连接发送HTTP请求并处理HTTP响应。
HttpParams httpParameters = new BasicHttpParams();//param参数
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
mHttpClient = new DefaultHttpClient(httpParameters);
@ -239,7 +250,7 @@ public class GTaskClient {
// login gtask
try {
String loginUrl = mGetUrl + "?auth=" + authToken;
HttpGet httpGet = new HttpGet(loginUrl);
HttpGet httpGet = new HttpGet(loginUrl);//用于发送 HTTP GET 请求到服务器并获取响应
HttpResponse response = null;
response = mHttpClient.execute(httpGet);
@ -255,7 +266,7 @@ public class GTaskClient {
Log.w(TAG, "it seems that there is no auth cookie");
}
// get the client version
// get the client version 这在切割js代码把字符串提出来
String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup(";
String jsEnd = ")}</script>";
@ -284,6 +295,7 @@ public class GTaskClient {
return mActionId++;
}
//请求头信息
private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
@ -291,21 +303,24 @@ public class GTaskClient {
return httpPost;
}
//获取HTTP响应的内容内容编码方式—
private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null;
if (entity.getContentEncoding() != null) {
contentEncoding = entity.getContentEncoding().getValue();
Log.d(TAG, "encoding: " + contentEncoding);
}
//根据响应的内容编码方式对输入流进行处理
InputStream input = entity.getContent();
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {//是否经过gzip文件压缩
input = new GZIPInputStream(entity.getContent());
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {
Inflater inflater = new Inflater(true);
input = new InflaterInputStream(entity.getContent(), inflater);
}
//将输入流转换为字符串
try {
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
@ -323,6 +338,7 @@ public class GTaskClient {
}
}
//服务器发送JSON格式的数据并返回服务器响应的JSON格式数据
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) {
Log.e(TAG, "please login first");
@ -331,6 +347,7 @@ public class GTaskClient {
HttpPost httpPost = createHttpPost();
try {
//将json转为字符串往列表里放
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>();
list.add(new BasicNameValuePair("r", js.toString()));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
@ -360,6 +377,8 @@ public class GTaskClient {
}
}
//创建新任务的方法它构建了一个包含任务操作和客户端版本号的JSON对象并将其作为POST请求发送给服务器。
// 然后从服务器响应中解析出新创建任务的ID并将其设置给task对象
public void createTask(Task task) throws NetworkFailureException {
commitUpdate();
try {
@ -412,6 +431,8 @@ public class GTaskClient {
}
}
//提交任务更新的方法
//mUpdateArray是否为null。如果是表示没有需要提交的更新直接退出方法
public void commitUpdate() throws NetworkFailureException {
if (mUpdateArray != null) {
try {
@ -447,6 +468,7 @@ public class GTaskClient {
}
}
//移动任务
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
commitUpdate();

@ -168,6 +168,8 @@ public class GTaskManager {
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;
}
//init初始化。先初始化metalist再 搞tasklist在搞具体的task
private void initGTaskList() throws NetworkFailureException {
if (mCancelled)
return;
@ -247,6 +249,8 @@ public class GTaskManager {
}
}
//从本地的备忘录应用中查询未被删除的备忘录条目并与Google Tasks服务同步。
private void syncContent() throws NetworkFailureException {
int syncType;
Cursor c = null;
@ -288,6 +292,7 @@ public class GTaskManager {
// sync folder first
syncFolder();
//从本地的备忘录应用中查询已存在的备忘录条目并与Google Tasks服务同步
// for note existing in database
try {
@ -326,7 +331,7 @@ public class GTaskManager {
}
}
// go through remaining items
// go through remaining items 同步在Google Tasks服务中存在、但在本地备忘录应用中不存在的备忘录条目
Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, Node> entry = iter.next();
@ -336,7 +341,9 @@ public class GTaskManager {
// mCancelled can be set by another thread, so we neet to check one by
// one
// clear local delete table
// clear local delete table在同步完成后对于本地备忘录应用中已删除的备忘录条目进行批量删除操作
// 并刷新本地备忘录应用与Google Tasks服务之间的同步ID。
// batch 批量
if (!mCancelled) {
if (!DataUtils.batchDeleteNotes(mContentResolver, mLocalDeleteIdMap)) {
throw new ActionFailureException("failed to batch-delete local deleted notes");
@ -362,6 +369,7 @@ public class GTaskManager {
}
// for root folder
//Google Tasks服务中的备忘录条目是否需要更新名称并决定调用何种类型的同步操作
try {
c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI,
Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null);
@ -374,6 +382,7 @@ public class GTaskManager {
mGidToNid.put(gid, (long) Notes.ID_ROOT_FOLDER);
mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid);
// for system folder, only update remote name if necessary
//下面是Googletask服务备忘录与本地 的是否有?或不存在。有就是更新,没有就是增加
if (!node.getName().equals(
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT))
doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);
@ -391,6 +400,8 @@ public class GTaskManager {
}
// for call-note folder
//查询特定系统文件夹ID为Notes.ID_CALL_RECORD_FOLDER表示通话记录文件夹对应的备忘录条目
// 并根据查询结果执行相应的同步操作
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)",
new String[] {
@ -424,7 +435,8 @@ public class GTaskManager {
}
}
// for local existing folders
// for local existing folders 查询本地备忘录应用中所有非"垃圾箱"文件夹类型的备忘录条目,
// 并根据查询结果执行相应的同步操作
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,
"(type=? AND parent_id<>?)", new String[] {
@ -440,6 +452,8 @@ public class GTaskManager {
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);
syncType = node.getSyncAction(c);
} else {
//当node为null且GTASK_ID列为空时说明该备忘录条目是本地新增的需要将其添加到远程服务器进行同步。
//当node为null且GTASK_ID列不为空时说明该备忘录条目是远程删除的需要将其从本地进行同步删除。
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {
// local add
syncType = Node.SYNC_ACTION_ADD_REMOTE;
@ -645,6 +659,7 @@ public class GTaskManager {
// add meta
updateRemoteMeta(task.getGid(), sqlNote);
} else {
//查找是否已经存在一个与给定的文件夹名称匹配的远程任务列表
TaskList tasklist = null;
// we need to skip folder if it has already existed
@ -670,6 +685,7 @@ public class GTaskManager {
break;
}
}
//所以,上面的操作是找到了匹配的远程任务列表,下面是没找到,我们创个新的
// no match we can add now
if (tasklist == null) {
@ -746,6 +762,8 @@ public class GTaskManager {
}
}
//确保本地笔记和GTask上的笔记同步并更新本地笔记的同步ID
private void refreshLocalSyncId() throws NetworkFailureException {
if (mCancelled) {
return;

@ -69,8 +69,10 @@ public class GTaskSyncService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle bundle = intent.getExtras();
Bundle bundle = intent.getExtras();//获取附加数据
if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {
//从Bundle中获取与指定键对应的整数值(ACTION_STRING_NAME)。如果指定键存在且对应的值为整数类型,则返回该整数值;
// 否则返回默认的整数值ACTION_INVALID。
switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) {
case ACTION_START_SYNC:
startSync();
@ -87,6 +89,7 @@ public class GTaskSyncService extends Service {
}
@Override
//内存不足时取消同步任务
public void onLowMemory() {
if (mSyncTask != null) {
mSyncTask.cancelSync();
@ -105,13 +108,17 @@ public class GTaskSyncService extends Service {
sendBroadcast(intent);
}
//在指定的Activity中开启同步任务通过调用GTaskSyncService服务来执行同步操作。
public static void startSync(Activity activity) {
GTaskManager.getInstance().setActivityContext(activity);
Intent intent = new Intent(activity, GTaskSyncService.class);
//增加键值对
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC);
activity.startService(intent);
}
//取消同步操作
public static void cancelSync(Context context) {
Intent intent = new Intent(context, GTaskSyncService.class);
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC);

@ -41,6 +41,8 @@ public class Note {
/**
* Create a new note id for adding a new note to databases
*/
//在数据库中创建一条新的笔记记录并返回新创建的笔记的ID
public static synchronized long getNewNoteId(Context context, long folderId) {
// Create a new note in the database
ContentValues values = new ContentValues();
@ -49,11 +51,14 @@ public class Note {
values.put(NoteColumns.MODIFIED_DATE, createdTime);
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
//这个新笔记的父节点就是文件夹ID。
values.put(NoteColumns.PARENT_ID, folderId);
//将values对象插入到数据库中并返回插入的记录的URI
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
long noteId = 0;
try {
//解析返回的uri得到新笔记ID值
noteId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString());
@ -114,6 +119,7 @@ public class Note {
* {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the
* note data info
*/
//估计是看update的过程有没有出现错误。如果有就报错了
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
@ -178,6 +184,7 @@ public class Note {
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
//该方法用于将笔记数据推送到内容解析器Content Resolver中。
Uri pushIntoContentResolver(Context context, long noteId) {
/**
* Check for safety
@ -186,11 +193,12 @@ public class Note {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();//操作列表
ContentProviderOperation.Builder builder = null;
//是否有文本数据需要更新
if(mTextDataValues.size() > 0) {
mTextDataValues.put(DataColumns.NOTE_ID, noteId);
//mTextDataId=0表示需要新插入文本数据
if (mTextDataId == 0) {
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
@ -205,6 +213,7 @@ public class Note {
} else {
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId));
//设置需要更新的字段及值
builder.withValues(mTextDataValues);
operationList.add(builder.build());
}
@ -235,6 +244,7 @@ public class Note {
if (operationList.size() > 0) {
try {
//将操作列表operationList应用到内容解析器
ContentProviderResult[] results = context.getContentResolver().applyBatch(
Notes.AUTHORITY, operationList);
return (results == null || results.length == 0 || results[0] == null) ? null

@ -101,6 +101,9 @@ public class WorkingNote {
private static final int NOTE_MODIFIED_DATE_COLUMN = 5;
//创建新的笔记
// New note construct
private WorkingNote(Context context, long folderId) {
mContext = context;
@ -114,6 +117,7 @@ public class WorkingNote {
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
}
//构建已存在的笔记
// Existing note construct
private WorkingNote(Context context, long noteId, long folderId) {
mContext = context;
@ -124,6 +128,8 @@ public class WorkingNote {
loadNote();
}
//加载笔记数据
private void loadNote() {
Cursor cursor = mContext.getContentResolver().query(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null,
@ -146,6 +152,7 @@ public class WorkingNote {
loadNoteData();
}
//加载笔记具体数据
private void loadNoteData() {
Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
DataColumns.NOTE_ID + "=?", new String[] {
@ -174,6 +181,7 @@ public class WorkingNote {
}
}
//创建新的空白笔记
public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
int widgetType, int defaultBgColorId) {
WorkingNote note = new WorkingNote(context, folderId);
@ -183,6 +191,8 @@ public class WorkingNote {
return note;
}
//加载工作笔记
public static WorkingNote load(Context context, long id) {
return new WorkingNote(context, id, 0);
}
@ -228,7 +238,7 @@ public class WorkingNote {
public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) {
mNoteSettingStatusListener = l;
}
//设置提醒日期
public void setAlertDate(long date, boolean set) {
if (date != mAlertDate) {
mAlertDate = date;
@ -288,6 +298,9 @@ public class WorkingNote {
}
}
//将一条电话通话记录转换为一个笔记
//电话通话记录转换为笔记的功能将电话号码、通话日期和父文件夹ID存储到笔记对象中
// 以便后续可以在应用程序中显示和管理这些通话记录笔记
public void convertToCallNote(String phoneNumber, long callDate) {
mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate));
mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber);
@ -310,6 +323,7 @@ public class WorkingNote {
return mModifiedDate;
}
//res事件
public int getBgColorResId() {
return NoteBgResources.getNoteBgResource(mBgColorId);
}
@ -341,7 +355,7 @@ public class WorkingNote {
public int getWidgetType() {
return mWidgetType;
}
//下面这个类是一个侦听器,用于检测用户是否发生改变背景颜色、设置时钟等操作
public interface NoteSettingChangedListener {
/**
* Called when the background color of current note has just changed

@ -30,6 +30,8 @@ public class ResourceParser {
public static final int GREEN = 3;
public static final int RED = 4;
public static final int DUCK = 5;
public static final int BG_DEFAULT_COLOR = YELLOW;
public static final int TEXT_SMALL = 0;
@ -45,7 +47,10 @@ public class ResourceParser {
R.drawable.edit_blue,
R.drawable.edit_white,
R.drawable.edit_green,
R.drawable.edit_red
R.drawable.edit_red,
R.drawable.note_bg_photo_wangyi
};
private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] {
@ -53,7 +58,9 @@ public class ResourceParser {
R.drawable.edit_title_blue,
R.drawable.edit_title_white,
R.drawable.edit_title_green,
R.drawable.edit_title_red
R.drawable.edit_title_red,
R.drawable.note_bg_photo_wangyi
};
public static int getNoteBgResource(int id) {
@ -80,7 +87,8 @@ public class ResourceParser {
R.drawable.list_blue_up,
R.drawable.list_white_up,
R.drawable.list_green_up,
R.drawable.list_red_up
R.drawable.list_red_up,
R.drawable.note_bg_photo_wangyi
};
private final static int [] BG_NORMAL_RESOURCES = new int [] {
@ -88,7 +96,8 @@ public class ResourceParser {
R.drawable.list_blue_middle,
R.drawable.list_white_middle,
R.drawable.list_green_middle,
R.drawable.list_red_middle
R.drawable.list_red_middle,
R.drawable.note_bg_photo_wangyi
};
private final static int [] BG_LAST_RESOURCES = new int [] {
@ -97,6 +106,7 @@ public class ResourceParser {
R.drawable.list_white_down,
R.drawable.list_green_down,
R.drawable.list_red_down,
R.drawable.note_bg_photo_wangyi
};
private final static int [] BG_SINGLE_RESOURCES = new int [] {
@ -104,7 +114,8 @@ public class ResourceParser {
R.drawable.list_blue_single,
R.drawable.list_white_single,
R.drawable.list_green_single,
R.drawable.list_red_single
R.drawable.list_red_single,
R.drawable.note_bg_photo_wangyi
};
public static int getNoteBgFirstRes(int id) {

@ -0,0 +1,127 @@
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Paint;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class ChangeLoginPasswordActivity extends Activity {
EditText OldPassword;
EditText NewPassword;
EditText ReWritePassword;
Button Acknowledged;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.change_login_password_activity);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
OldPassword=(EditText) findViewById(R.id.old_password);
NewPassword=(EditText) findViewById(R.id.new_password);
ReWritePassword=(EditText) findViewById(R.id.ack_password);
Acknowledged=(Button)findViewById(R.id.Bt_Acknowledged);
Acknowledged.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String old_password = OldPassword.getText().toString();
String new_password = NewPassword.getText().toString();
String ack_password = ReWritePassword.getText().toString();
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
String login_password=pref.getString("password","");
if(old_password.equals("")==true || new_password.equals("")==true || ack_password.equals("")==true) {
Toast.makeText(ChangeLoginPasswordActivity.this, "密码不能为空", Toast.LENGTH_SHORT).show();
}else if (new_password.equals(ack_password) == false) {
Toast.makeText(ChangeLoginPasswordActivity.this, "新建密码与重复密码不匹配,请重新输入密码", Toast.LENGTH_SHORT).show();
ReWritePassword.setText("");
}else if(old_password.equals(login_password) == false){
Toast.makeText(ChangeLoginPasswordActivity.this, "原有密码错误,请重新输入密码", Toast.LENGTH_SHORT).show();
OldPassword.setText("");
}
else if (new_password.equals(ack_password) == true && old_password.equals(login_password) == true){
SharedPreferences.Editor editor=getSharedPreferences("user management", MODE_PRIVATE).edit();
editor.putString("password",new_password);
editor.apply();
Toast.makeText(ChangeLoginPasswordActivity.this, "修改密码成功", Toast.LENGTH_SHORT).show();
Intent intent=new Intent(ChangeLoginPasswordActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
}
});
}
@Override
public void onBackPressed() {
Intent intent=new Intent(ChangeLoginPasswordActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
}

@ -0,0 +1,163 @@
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LoginActivity extends Activity{
private EditText accountEdit;
private EditText passwordEdit;
private Button login;
private Button cancel;
private Button change;
private long last_login_time = 0 ;
public static final long MAX_LOGIN_TIME = 9999999;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
boolean user_boolean = pref.getBoolean("user",false);//获取用户是否设置了密码
if(!user_boolean) //User_boolean = false时没有设置密码直接跳转到便签主界面
{
SharedPreferences.Editor editor=getSharedPreferences("user management", MODE_PRIVATE).edit();
editor.putString("password","123456");
editor.putBoolean("user",true);
editor.apply();
}
SharedPreferences login_time_get = getSharedPreferences("login time",MODE_PRIVATE);
boolean is_first_login = login_time_get.getBoolean("is_first_login",false);
setContentView(R.layout.login_activity);
accountEdit = (EditText) findViewById(R.id.account);
passwordEdit = (EditText) findViewById(R.id.password);
login = (Button) findViewById(R.id.login);
cancel = (Button) findViewById(R.id.cancel);
change = (Button) findViewById(R.id.change_password);
long current_time = System.currentTimeMillis();
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(LoginActivity.this, R.string.app_already_quit, Toast.LENGTH_LONG).show();
finish();
}
});
Long current_login_time = login_time_get.getLong("current login time",0);
if((is_first_login)&&(current_time - current_login_time <= MAX_LOGIN_TIME)){
SharedPreferences.Editor editor=getSharedPreferences("login time", MODE_PRIVATE).edit();
editor.putLong("current login time",System.currentTimeMillis());
editor.apply();
Intent intent = new Intent(LoginActivity.this,NotesListActivity.class);
startActivity(intent);
finish();
}
else{
if(!is_first_login){
SharedPreferences.Editor editor=getSharedPreferences("login time", MODE_PRIVATE).edit();
editor.putLong("current login time",System.currentTimeMillis());
editor.putBoolean("is_first_login",true);
editor.apply();
}
login.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
String share_password=pref.getString("password","");
if(account.equals("hei") && password.equals(share_password)){
ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this);
progressDialog.setTitle(R.string.Loading);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(true);
progressDialog.show();;
Intent intent = new Intent(LoginActivity.this,NotesListActivity.class);
startActivity(intent);
finish();
}else {
Toast.makeText(LoginActivity.this, R.string.invalid,Toast.LENGTH_SHORT).show();
}
}
});
change.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new Intent(LoginActivity.this,ChangeLoginPasswordActivity.class);
startActivity(intent);
finish();
}
});
}
}
}

@ -0,0 +1,76 @@
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LoginView extends Activity
{
Handler mHandler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_view);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(LoginView.this, LoginActivity.class);
startActivity(intent);
finish();
}
},2000);
}
}

@ -84,6 +84,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public ImageView ibSetBgColor;
}
//静态Map。用于设置背景选择器点击相关按钮选选择相关颜色。这是选择便签颜色的选择器
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
@ -91,6 +92,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
sBgSelectorBtnsMap.put(R.id.iv_ph_duck, ResourceParser.DUCK);
}
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
@ -100,8 +103,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
}
sBgSelectorSelectionMap.put(ResourceParser.DUCK, R.id.iv_ph_duck_select);
}//
//选择便签字体大小的界选择器的吧
private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
static {
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
@ -149,6 +154,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private String mUserQuery;
private Pattern mPattern;
//创建Activity启动其生命周期
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -165,6 +171,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* Current activity may be killed when the memory is low. Once it is killed, for another time
* user load this activity, we should restore the former state
*/
//Activity状态恢复函数。当Activity因内存不足被杀死后再次加载该活动
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
@ -179,6 +186,19 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
//下面是具体执行intent的函数。这个函数会判断接收的intent是干啥的从而执行相关的操作。比如我们的intent是新建便签。定义的CreateNewNote函数
//只是为我们设置好了intent而intent的具体执行还要在initActivityState里。
//对于创建便签他会看是普通的文字便签还是通讯记录对于文字便签新建便签的操作是调用了workingNote.createEmptyNote函数。而这个该函数
//又会调用Note.Note函数。故猜测Note是对应的便签的操作包里面定义了对一个便签的所有操作比如创建等workingNote是Note的一个子集即当前正在被操作的note。
// Notes定义了
//文件夹和便签的顶层即具体样式信息与数据等信息。DataColumn是便签具体的和数据直接相关的NoteColumn是定义了便签或文件夹的其他信息
// 比如用了什么小组件创建时间样式背景颜色等信息。而NoteitemData是一个便签或文件夹的具体实例其中包括了DataColumn及NoteColum等其他信息。
//故对于一个便签来说NoteItemData是他的数据及自身信息实例Note是其操作定义。
//初始化Activity状态函数形参为intent根据传入的intent执行相关活动。
//该函数通过if-else判断intent.getAction()是哪种活动,从而执行相应函数。
//通过intent.getExtra来获取活动执行对象的附加信息。
private boolean initActivityState(Intent intent) {
/**
* If the user specified the {@link Intent#ACTION_VIEW} but not provided with id,
@ -262,12 +282,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return true;
}
//回调函数使得Activity与用户互动。这里不断初始化便签界面
@Override
protected void onResume() {
super.onResume();
initNoteScreen();
}
//初始化便签界面
private void initNoteScreen() {
mNoteEditor.setTextAppearance(this, TextAppearanceResources
.getTexAppearanceResource(mFontSizeId));
@ -295,6 +317,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
showAlertHeader();
}
//闹钟提醒功能实现。
private void showAlertHeader() {
if (mWorkingNote.hasClockAlert()) {
long time = System.currentTimeMillis();
@ -430,13 +453,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
if (id == R.id.btn_set_bg_color) {
mNoteBgColorSelector.setVisibility(View.VISIBLE);
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
- View.VISIBLE);
View.VISIBLE);
} else if (sBgSelectorBtnsMap.containsKey(id)) {
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
mNoteBgColorSelector.setVisibility(View.GONE);
} else if (sFontSizeBtnsMap.containsKey(id)) {
}
else if (sFontSizeBtnsMap.containsKey(id)) {
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
mFontSizeId = sFontSizeBtnsMap.get(id);
mSharedPrefs.edit().putInt(PREFERENCE_FONT_SIZE, mFontSizeId).commit();

@ -78,6 +78,11 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
/**
* NotesListActivty便
*
* main ActivityintentNoteEditActivity
*/
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
@ -113,6 +118,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private TextView mTitleBar;
private long mCurrentFolderId;
private ContentResolver mContentResolver;
@ -135,6 +141,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private final static int REQUEST_CODE_OPEN_NODE = 102;
private final static int REQUEST_CODE_NEW_NODE = 103;
//创建Activity启动其生命周期。完成设置界面样式、初始化资源、且在用户第一次使用App时进行介绍
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -147,6 +154,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
setAppInfoFromRawRes();
}
//intent返回数据接收函数。形参为请求码、结果码、其他intent返回的数据。主要与NoteEditActivity交互。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK
@ -157,6 +165,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
//第一次使用App时调用显示introduction。
private void setAppInfoFromRawRes() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
@ -202,13 +211,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
//onCreate调用后回调此Activity对用户可见。
@Override
protected void onStart() {
super.onStart();
startAsyncNotesListQuery();
}
//初始化资源
private void initResources() {
mContentResolver = this.getContentResolver();
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
@ -231,11 +241,16 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mModeCallBack = new ModeCallback();
}
/**
* ActionMode使便ActionMode
* 便便ActionBar
*/
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
private DropdownMenu mDropDownMenu;
private ActionMode mActionMode;
private MenuItem mMoveMenu;
//ActionMode创建函数形参为创建的ActionMode及需要通过该ActionMode显示的Menu对象
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
getMenuInflater().inflate(R.menu.note_list_options, menu);
menu.findItem(R.id.delete).setOnMenuItemClickListener(this);
@ -269,6 +284,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
//用于进行多选(全选)时菜单栏界面的更新
private void updateMenu() {
int selectedCount = mNotesListAdapter.getSelectedCount();
// Update dropdown menu
@ -286,32 +302,39 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
//重新刷新菜单栏时调用.
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
//菜单栏点击动作按钮时调用形参为ActionMode、点击的菜单项.
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
return false;
}
//销毁或退出ActionMode时调用。
public void onDestroyActionMode(ActionMode mode) {
mNotesListAdapter.setChoiceMode(false);
mNotesListView.setLongClickable(true);
mAddNewNote.setVisibility(View.VISIBLE);
}
//结束ActionMode时调用
public void finishActionMode() {
mActionMode.finish();
}
//检查当前菜单选择情况(针对多选)并进行菜单更新。
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
boolean checked) {
mNotesListAdapter.setCheckedItem(position, checked);
updateMenu();
}
//菜单项点击时调用。
public boolean onMenuItemClick(MenuItem item) {
if (mNotesListAdapter.getSelectedCount() == 0) {
Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none),
@ -330,7 +353,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
batchDelete();
batchDelete();//批处理删除
}
});
builder.setNegativeButton(android.R.string.cancel, null);
@ -344,61 +367,58 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
/**
* 便
*/
private class NewNoteOnTouchListener implements OnTouchListener {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
Display display = getWindowManager().getDefaultDisplay();
int screenHeight = display.getHeight();
int newNoteViewHeight = mAddNewNote.getHeight();
int start = screenHeight - newNoteViewHeight;
int eventY = start + (int) event.getY();
/**
* Minus TitleBar's height
*/
if (mState == ListEditState.SUB_FOLDER) {
eventY -= mTitleBar.getHeight();
start -= mTitleBar.getHeight();
}
/**
* HACKME:When click the transparent part of "New Note" button, dispatch
* the event to the list view behind this button. The transparent part of
* "New Note" button could be expressed by formula y=-0.12x+94Unit:pixel
* and the line top of the button. The coordinate based on left of the "New
* Note" button. The 94 represents maximum height of the transparent part.
* Notice that, if the background of the button changes, the formula should
* also change. This is very bad, just for the UI designer's strong requirement.
*/
if (event.getY() < (event.getX() * (-0.12) + 94)) {
View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
- mNotesListView.getFooterViewsCount());
if (view != null && view.getBottom() > start
&& (view.getTop() < (start + 94))) {
mOriginY = (int) event.getY();
mDispatchY = eventY;
event.setLocation(event.getX(), mDispatchY);
mDispatch = true;
return mNotesListView.dispatchTouchEvent(event);
}
}
break;
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
Display display = getWindowManager().getDefaultDisplay();
int screenHeight = display.getHeight();
int newNoteViewHeight = mAddNewNote.getHeight();
int start = screenHeight - newNoteViewHeight;
int eventY = start + (int) event.getY();
/**
* Minus TitleBar's height
*/
if (mState == ListEditState.SUB_FOLDER) {
eventY -= mTitleBar.getHeight();
start -= mTitleBar.getHeight();
}
case MotionEvent.ACTION_MOVE: {
if (mDispatch) {
mDispatchY += (int) event.getY() - mOriginY;
/**
* HACKME:When click the transparent part of "New Note" button, dispatch
* the event to the list view behind this button. The transparent part of
* "New Note" button could be expressed by formula y=-0.12x+94Unit:pixel
* and the line top of the button. The coordinate based on left of the "New
* Note" button. The 94 represents maximum height of the transparent part.
* Notice that, if the background of the button changes, the formula should
* also change. This is very bad, just for the UI designer's strong requirement.
*/
if (event.getY() < (event.getX() * (-0.12) + 94)) {
View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
- mNotesListView.getFooterViewsCount());
if (view != null && view.getBottom() > start
&& (view.getTop() < (start + 94))) {
mOriginY = (int) event.getY();
mDispatchY = eventY;
event.setLocation(event.getX(), mDispatchY);
mDispatch = true;
return mNotesListView.dispatchTouchEvent(event);
}
break;
}
default: {
if (mDispatch) {
event.setLocation(event.getX(), mDispatchY);
mDispatch = false;
return mNotesListView.dispatchTouchEvent(event);
}
break;
} else if (action == MotionEvent.ACTION_MOVE) {
if (mDispatch) {
mDispatchY += (int) event.getY() - mOriginY;
event.setLocation(event.getX(), mDispatchY);
return mNotesListView.dispatchTouchEvent(event);
}
} else {
if (mDispatch) {
event.setLocation(event.getX(), mDispatchY);
mDispatch = false;
return mNotesListView.dispatchTouchEvent(event);
}
}
return false;
@ -406,6 +426,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
/*
便便
*/
private void startAsyncNotesListQuery() {
String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
: NORMAL_SELECTION;
@ -415,11 +440,16 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
/**
*
* (startAsyncNoteListQuery)便
*/
private final class BackgroundQueryHandler extends AsyncQueryHandler {
public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
}
//下面就是查询结束后对返回数据的处理,完成界面更新。
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch (token) {
@ -439,6 +469,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
//通过游标显示文件夹列表菜单,功能为移动便签至某个文件夹
private void showFolderListMenu(Cursor cursor) {
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(R.string.menu_title_select_folder);
@ -460,6 +492,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
builder.show();
}
//创建新便签。主要是创建intent并启动。
private void createNewNote() {
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
@ -467,6 +500,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
}
//批处理删除。用于多个标签删除时.
private void batchDelete() {
new AsyncTask<Void, Void, HashSet<AppWidgetAttribute>>() {
protected HashSet<AppWidgetAttribute> doInBackground(Void... unused) {
@ -504,6 +539,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}.execute();
}
//文件夹删除功能。形参为文件夹ID号
private void deleteFolder(long folderId) {
if (folderId == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Wrong folder id, should not happen " + folderId);
@ -531,6 +567,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
//打开便签功能。形参为NoteItemData其为文件夹或便签的实例。
private void openNode(NoteItemData data) {
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_VIEW);
@ -538,6 +575,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE);
}
//打开文件夹功能
private void openFolder(NoteItemData data) {
mCurrentFolderId = data.getId();
startAsyncNotesListQuery();
@ -555,24 +593,28 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mTitleBar.setVisibility(View.VISIBLE);
}
//视图点击事件。实现创建便签。
public void onClick(View v) {
if (v.getId() == R.id.btn_new_note) {
createNewNote();
}
}
//显示软键盘
private void showSoftInput() {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
}
//不显示软键盘
private void hideSoftInput(View view) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
//文件夹新建、查看及重命名功能。
private void showCreateOrModifyFolderDialog(final boolean create) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null);
@ -657,7 +699,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
});
}
//用于处理子Acitivity返回父Activity。相当于对按下“返回箭头”的处理。即返回NotesListActivity活动。
@Override
public void onBackPressed() {
switch (mState) {
@ -682,6 +724,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
//更新小组件。
private void updateWidget(int appWidgetId, int appWidgetType) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
if (appWidgetType == Notes.TYPE_WIDGET_2X) {
@ -701,7 +744,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
setResult(RESULT_OK, intent);
}
//查看、删除、修改文件夹名称的浮动菜单栏ContextMenu创建
private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() {
//创建ContextMenu形参为创建的菜单、长按事件绑定的视图、视图元素信息
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
if (mFocusNoteDataItem != null) {
menu.setHeaderTitle(mFocusNoteDataItem.getSnippet());
@ -712,6 +757,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
};
//下面都是对浮动菜单栏的一些函数
//浮动菜单栏关闭
@Override
public void onContextMenuClosed(Menu menu) {
if (mNotesListView != null) {
@ -719,6 +766,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
super.onContextMenuClosed(menu);
}
//浮动菜单栏点击按钮后事件处理。
@Override
public boolean onContextItemSelected(MenuItem item) {
@ -754,6 +802,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
//下面是OptionsMenu菜单创建的有关函数。
//OptionsMenu创建
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
@ -772,6 +822,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
//OptionsMenu点击按钮事件处理
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
@ -799,12 +850,16 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
//搜索栏功能实现(就是最上面那个搜索便签得的)
//内部调用了搜索的ui组件
@Override
public boolean onSearchRequested() {
startSearch(null, false, null /* appData */, false);
return true;
}
//下面使用了异步线程类AsynTask。可在类中可以直接进行UI操作并将后台计算的结果及时的交给UI线程进行UI界面显示。
//将便签内容输出为文本
private void exportNoteToText() {
final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this);
new AsyncTask<Void, Void, Integer>() {
@ -851,14 +906,19 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}
//用于跳转到保存的设置界面。这个maybe在isSyncMode==0时调用。作用在没进行过保存设置时。
private void startPreferenceActivity() {
Activity from = getParent() != null ? getParent() : this;
Intent intent = new Intent(from, NotesPreferenceActivity.class);
from.startActivityIfNeeded(intent, -1);
}
/**
*
*/
private class OnListItemClickListener implements OnItemClickListener {
//点击事件处理。将点击事件其与视图绑定。
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (view instanceof NotesListItem) {
NoteItemData item = ((NotesListItem) view).getItemData();
@ -898,6 +958,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
private void startQueryDestinationFolders() {
String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?";
selection = (mState == ListEditState.NOTE_LIST) ? selection:
@ -916,6 +977,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
NoteColumns.MODIFIED_DATE + " DESC");
}
//处理长按事件。
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (view instanceof NotesListItem) {
mFocusNoteDataItem = ((NotesListItem) view).getItemData();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="输入原有密码:"/>
<EditText
android:id="@+id/old_password"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="输入新建密码:"/>
<EditText
android:id="@+id/new_password"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="再次输入密码:"/>
<EditText
android:id="@+id/ack_password"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:password="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<Button
android:id="@+id/Bt_Acknowledged"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确认"/>
</LinearLayout>
</LinearLayout>

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.LoginActivity"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="center">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="@string/prompt_account" />
<EditText
android:id="@+id/account"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="center">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/prompt_password"
android:textSize="18sp" />
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:inputType="textPassword" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="center">
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/prompt_login" />
<Button
android:id="@+id/cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/cancel" />
<Button
android:id="@+id/change_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='修改密码'/>
</LinearLayout>
</LinearLayout>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/login_view_photo_2">
<TextView
android:id="@+id/login_view_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:keepScreenOn="true"
android:text="快放假了家人们"
android:textSize="50sp"
android:textStyle="bold"
android:textColor="#1CAC78"
/>
</LinearLayout>

@ -127,7 +127,7 @@
android:id="@+id/note_bg_color_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/note_edit_color_selector_panel"
android:background="@drawable/note_edit_color_selector_panel_test"
android:layout_marginTop="30dip"
android:layout_marginRight="8dip"
android:layout_gravity="top|right"
@ -235,6 +235,26 @@
android:visibility="gone"
android:src="@drawable/selected" />
</FrameLayout>
<FrameLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/iv_ph_duck"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/iv_ph_duck_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:focusable="false"
android:visibility="gone"
android:src="@drawable/selected" />
</FrameLayout>
</LinearLayout>
<LinearLayout

@ -119,6 +119,7 @@
<string name="search">便签</string>
<string name="datetime_dialog_ok">设置</string>
<string name="datetime_dialog_cancel">取消</string>
<plurals name="search_results_title">
<item quantity="other"><xliff:g id="NUMBER">%1$s</xliff:g> 条符合“<xliff:g id="SEARCH">%2$s</xliff:g>”的搜索结果</item>
</plurals>

@ -120,6 +120,7 @@
<string name="search">便籤</string>
<string name="datetime_dialog_ok">設置</string>
<string name="datetime_dialog_cancel">取消</string>
<plurals name="search_results_title">
<item quantity="other"><xliff:g id="NUMBER">%1$s</xliff:g> 條符合”<xliff:g id="SEARCH">%2$s</xliff:g>“的搜尋結果</item>
</plurals>

@ -132,4 +132,15 @@
<item quantity="other"><xliff:g id="number" example="15">%1$s</xliff:g> results for \"<xliff:g id="search" example="???">%2$s</xliff:g>\"</item>
</plurals>
<string name="login_view_text">玛卡巴卡斗志昂扬</string>
<string name="activity_login_view">LoginView</string>
<string name="prompt_account">用户名:</string>
<string name="prompt_password">密码:</string>
<string name="prompt_login">登录</string>
<string name="cancel">取消</string>
<string name="app_already_quit">程序已退出</string>
<string name="Loading">正在登录,你给我等着</string>
<string name="invalid">有人抢银行啦</string>
</resources>

@ -63,7 +63,7 @@
</style>
<style name="NoteActionBarStyle" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
<item name="android:displayOptions" />
<item name="android:visibility">gone</item>
<!--<item name="android:displayOptions"/>-->
<item name="android:visibility">visible</item>
</style>
</resources>
Loading…
Cancel
Save