forked from ppm9irgyz/MINotes
Compare commits
62 Commits
Binary file not shown.
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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.gtask.remote;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* 便签与Google任务同步服务类.
|
||||
*/
|
||||
public class GTaskSyncService extends Service {
|
||||
/**
|
||||
* 广播动作字符串名称.
|
||||
*/
|
||||
public final static String ACTION_STRING_NAME = "sync_action_type";
|
||||
|
||||
/**
|
||||
* 开始同步动作.
|
||||
*/
|
||||
public final static int ACTION_START_SYNC = 0;
|
||||
|
||||
/**
|
||||
* 取消同步动作.
|
||||
*/
|
||||
public final static int ACTION_CANCEL_SYNC = 1;
|
||||
|
||||
/**
|
||||
* 无效动作.
|
||||
*/
|
||||
public final static int ACTION_INVALID = 2;
|
||||
|
||||
/**
|
||||
* Google任务服务广播名称.
|
||||
*/
|
||||
public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service";
|
||||
|
||||
/**
|
||||
* 广播是否正在同步的键.
|
||||
*/
|
||||
public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing";
|
||||
|
||||
/**
|
||||
* 广播同步进度消息的键.
|
||||
*/
|
||||
public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg";
|
||||
|
||||
/**
|
||||
* 同步任务对象.
|
||||
*/
|
||||
private static GTaskASyncTask mSyncTask = null;
|
||||
|
||||
/**
|
||||
* 同步进度字符串.
|
||||
*/
|
||||
private static String mSyncProgress = "";
|
||||
|
||||
/**
|
||||
* 开始同步任务.
|
||||
*/
|
||||
private void startSync() {
|
||||
if (mSyncTask == null) {
|
||||
mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() {
|
||||
public void onComplete() {
|
||||
mSyncTask = null;
|
||||
sendBroadcast("");
|
||||
stopSelf();
|
||||
}
|
||||
});
|
||||
sendBroadcast("");
|
||||
mSyncTask.execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消同步任务.
|
||||
*/
|
||||
private void cancelSync() {
|
||||
if (mSyncTask != null) {
|
||||
mSyncTask.cancelSync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建服务时调用.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
mSyncTask = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动命令时调用.
|
||||
*
|
||||
* @param intent 意图
|
||||
* @param flags 标志
|
||||
* @param startId 启动ID
|
||||
* @return 启动结果
|
||||
*/
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Bundle bundle = intent.getExtras();
|
||||
if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {
|
||||
switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) {
|
||||
case ACTION_START_SYNC:
|
||||
startSync();
|
||||
break;
|
||||
case ACTION_CANCEL_SYNC:
|
||||
cancelSync();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return START_STICKY;
|
||||
}
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 内存不足时调用.
|
||||
*/
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
if (mSyncTask != null) {
|
||||
mSyncTask.cancelSync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定服务时调用.
|
||||
*
|
||||
* @param intent 意图
|
||||
* @return 绑定对象
|
||||
*/
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送广播.
|
||||
*
|
||||
* @param msg 消息
|
||||
*/
|
||||
public void sendBroadcast(String msg) {
|
||||
mSyncProgress = msg;
|
||||
Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME);
|
||||
intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null);
|
||||
intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始同步.
|
||||
*
|
||||
* @param activity 活动
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消同步.
|
||||
*
|
||||
* @param context 上下文
|
||||
*/
|
||||
public static void cancelSync(Context context) {
|
||||
Intent intent = new Intent(context, GTaskSyncService.class);
|
||||
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否正在同步.
|
||||
*
|
||||
* @return 是否正在同步
|
||||
*/
|
||||
public static boolean isSyncing() {
|
||||
return mSyncTask != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取同步进度字符串.
|
||||
*
|
||||
* @return 同步进度字符串
|
||||
*/
|
||||
public static String getProgressString() {
|
||||
return mSyncProgress;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,349 @@
|
||||
/*
|
||||
* 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.tool;
|
||||
|
||||
// 导入相关类
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.Environment;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.Log;
|
||||
|
||||
import net.micode.notes.R;
|
||||
import net.micode.notes.data.Notes;
|
||||
import net.micode.notes.data.Notes.DataColumns;
|
||||
import net.micode.notes.data.Notes.DataConstants;
|
||||
import net.micode.notes.data.Notes.NoteColumns;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
// 声明一个名为 BackupUtils 的公共类
|
||||
public class BackupUtils {
|
||||
// 定义一个日志标签常量
|
||||
private static final String TAG = "BackupUtils";
|
||||
// 单例模式相关变量
|
||||
private static BackupUtils sInstance;
|
||||
|
||||
// 提供获取 BackupUtils 实例的静态方法
|
||||
public static synchronized BackupUtils getInstance(Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new BackupUtils(context);
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
// 定义一些常量,表示备份或恢复的状态
|
||||
public static final int STATE_SD_CARD_UNMOUONTED = 0;
|
||||
public static final int STATE_BACKUP_FILE_NOT_EXIST = 1;
|
||||
public static final int STATE_DATA_DESTROIED = 2;
|
||||
public static final int STATE_SYSTEM_ERROR = 3;
|
||||
public static final int STATE_SUCCESS = 4;
|
||||
|
||||
// 声明一个 TextExport 类型的私有变量
|
||||
private TextExport mTextExport;
|
||||
|
||||
// 构造方法,传入 Context 对象
|
||||
private BackupUtils(Context context) {
|
||||
mTextExport = new TextExport(context);
|
||||
}
|
||||
|
||||
// 判断外部存储是否可用的静态方法
|
||||
private static boolean externalStorageAvailable() {
|
||||
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
|
||||
}
|
||||
|
||||
// 导出数据到文本文件的方法
|
||||
public int exportToText() {
|
||||
return mTextExport.exportToText();
|
||||
}
|
||||
|
||||
// 获取导出文本文件名的方法
|
||||
public String getExportedTextFileName() {
|
||||
return mTextExport.mFileName;
|
||||
}
|
||||
|
||||
// 获取导出文本文件目录的方法
|
||||
public String getExportedTextFileDir() {
|
||||
return mTextExport.mFileDirectory;
|
||||
}
|
||||
|
||||
// 声明一个名为 TextExport 的私有静态内部类
|
||||
private static class TextExport {
|
||||
// 定义查询笔记和数据的投影数组
|
||||
private static final String[] NOTE_PROJECTION = {
|
||||
NoteColumns.ID,
|
||||
NoteColumns.MODIFIED_DATE,
|
||||
NoteColumns.SNIPPET,
|
||||
NoteColumns.TYPE
|
||||
};
|
||||
|
||||
private static final int NOTE_COLUMN_ID = 0;
|
||||
private static final int NOTE_COLUMN_MODIFIED_DATE = 1;
|
||||
private static final int NOTE_COLUMN_SNIPPET = 2;
|
||||
|
||||
private static final String[] DATA_PROJECTION = {
|
||||
DataColumns.CONTENT,
|
||||
DataColumns.MIME_TYPE,
|
||||
DataColumns.DATA1,
|
||||
DataColumns.DATA2,
|
||||
DataColumns.DATA3,
|
||||
DataColumns.DATA4,
|
||||
};
|
||||
|
||||
private static final int DATA_COLUMN_CONTENT = 0;
|
||||
private static final int DATA_COLUMN_MIME_TYPE = 1;
|
||||
private static final int DATA_COLUMN_CALL_DATE = 2;
|
||||
private static final int DATA_COLUMN_PHONE_NUMBER = 4;
|
||||
|
||||
// 定义文本格式数组
|
||||
private final String [] TEXT_FORMAT;
|
||||
private static final int FORMAT_FOLDER_NAME = 0;
|
||||
private static final int FORMAT_NOTE_DATE = 1;
|
||||
private static final int FORMAT_NOTE_CONTENT = 2;
|
||||
|
||||
// 声明 Context 对象和文件名、目录变量
|
||||
private Context mContext;
|
||||
private String mFileName;
|
||||
private String mFileDirectory;
|
||||
|
||||
// 构造方法,传入 Context 对象
|
||||
public TextExport(Context context) {
|
||||
TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note);
|
||||
mContext = context;
|
||||
mFileName = "";
|
||||
mFileDirectory = "";
|
||||
}
|
||||
|
||||
// 根据 id 获取文本格式的方法
|
||||
private String getFormat(int id) {
|
||||
return TEXT_FORMAT[id];
|
||||
}
|
||||
|
||||
// 导出指定文件夹到文本的方法
|
||||
private void exportFolderToText(String folderId, PrintStream ps) {
|
||||
// 查询属于该文件夹的笔记
|
||||
Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI,
|
||||
NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] {
|
||||
folderId
|
||||
}, null);
|
||||
|
||||
if (notesCursor != null) {
|
||||
if (notesCursor.moveToFirst()) {
|
||||
do {
|
||||
// 打印笔记的最后修改日期
|
||||
ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format(
|
||||
mContext.getString(R.string.format_datetime_mdhm),
|
||||
notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE))));
|
||||
// 查询属于该笔记的数据
|
||||
String noteId = notesCursor.getString(NOTE_COLUMN_ID);
|
||||
exportNoteToText(noteId, ps);
|
||||
} while (notesCursor.moveToNext());
|
||||
}
|
||||
notesCursor.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 将指定 id 的笔记导出到打印流中
|
||||
*/
|
||||
private void exportNoteToText(String noteId, PrintStream ps) {
|
||||
// 查询属于该笔记的数据
|
||||
Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI,
|
||||
DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] {
|
||||
noteId
|
||||
}, null);
|
||||
|
||||
if (dataCursor != null) {
|
||||
if (dataCursor.moveToFirst()) {
|
||||
do {
|
||||
// 获取数据的 MIME 类型
|
||||
String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE);
|
||||
if (DataConstants.CALL_NOTE.equals(mimeType)) {
|
||||
// 打印电话号码
|
||||
String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER);
|
||||
long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE);
|
||||
String location = dataCursor.getString(DATA_COLUMN_CONTENT);
|
||||
|
||||
if (!TextUtils.isEmpty(phoneNumber)) {
|
||||
ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT),
|
||||
phoneNumber));
|
||||
}
|
||||
// 打印通话日期
|
||||
ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat
|
||||
.format(mContext.getString(R.string.format_datetime_mdhm),
|
||||
callDate)));
|
||||
// 打印通话附件位置
|
||||
if (!TextUtils.isEmpty(location)) {
|
||||
ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT),
|
||||
location));
|
||||
}
|
||||
} else if (DataConstants.NOTE.equals(mimeType)) {
|
||||
// 打印笔记内容
|
||||
String content = dataCursor.getString(DATA_COLUMN_CONTENT);
|
||||
if (!TextUtils.isEmpty(content)) {
|
||||
ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT),
|
||||
content));
|
||||
}
|
||||
}
|
||||
} while (dataCursor.moveToNext());
|
||||
}
|
||||
dataCursor.close();
|
||||
}
|
||||
// 在笔记之间打印一行分隔符
|
||||
try {
|
||||
ps.write(new byte[] {
|
||||
Character.LINE_SEPARATOR, Character.LETTER_NUMBER
|
||||
});
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 笔记将被导出为用户可读的文本
|
||||
*/
|
||||
public int exportToText() {
|
||||
// 判断外部存储是否可用
|
||||
if (!externalStorageAvailable()) {
|
||||
Log.d(TAG, "Media was not mounted");
|
||||
return STATE_SD_CARD_UNMOUONTED;
|
||||
}
|
||||
|
||||
// 获取导出到文本的打印流
|
||||
PrintStream ps = getExportToTextPrintStream();
|
||||
if (ps == null) {
|
||||
Log.e(TAG, "get print stream error");
|
||||
return STATE_SYSTEM_ERROR;
|
||||
}
|
||||
// 首先导出文件夹及其笔记
|
||||
Cursor folderCursor = mContext.getContentResolver().query(
|
||||
Notes.CONTENT_NOTE_URI,
|
||||
NOTE_PROJECTION,
|
||||
"(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND "
|
||||
+ NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR "
|
||||
+ NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, null, null);
|
||||
|
||||
if (folderCursor != null) {
|
||||
if (folderCursor.moveToFirst()) {
|
||||
do {
|
||||
// 打印文件夹的名称
|
||||
String folderName = "";
|
||||
if(folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) {
|
||||
folderName = mContext.getString(R.string.call_record_folder_name);
|
||||
} else {
|
||||
folderName = folderCursor.getString(NOTE_COLUMN_SNIPPET);
|
||||
}
|
||||
if (!TextUtils.isEmpty(folderName)) {
|
||||
ps.println(String.format(getFormat(FORMAT_FOLDER_NAME), folderName));
|
||||
}
|
||||
String folderId = folderCursor.getString(NOTE_COLUMN_ID);
|
||||
exportFolderToText(folderId, ps);
|
||||
} while (folderCursor.moveToNext());
|
||||
}
|
||||
folderCursor.close();
|
||||
}
|
||||
|
||||
// 导出根文件夹中的笔记
|
||||
Cursor noteCursor = mContext.getContentResolver().query(
|
||||
Notes.CONTENT_NOTE_URI,
|
||||
NOTE_PROJECTION,
|
||||
NoteColumns.TYPE + "=" + +Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID
|
||||
+ "=0", null, null);
|
||||
|
||||
if (noteCursor != null) {
|
||||
if (noteCursor.moveToFirst()) {
|
||||
do {
|
||||
ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format(
|
||||
mContext.getString(R.string.format_datetime_mdhm),
|
||||
noteCursor.getLong(NOTE_COLUMN_MODIFIED_DATE))));
|
||||
// 查询属于该笔记的数据
|
||||
String noteId = noteCursor.getString(NOTE_COLUMN_ID);
|
||||
exportNoteToText(noteId, ps);
|
||||
} while (noteCursor.moveToNext());
|
||||
}
|
||||
noteCursor.close();
|
||||
}
|
||||
ps.close();
|
||||
|
||||
return STATE_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指向 {@generateExportedTextFile} 文件的打印流
|
||||
*/
|
||||
private PrintStream getExportToTextPrintStream() {
|
||||
// 在 SD 卡上生成文件
|
||||
File file = generateFileMountedOnSDcard(mContext, R.string.file_path,
|
||||
R.string.file_name_txt_format);
|
||||
if (file == null) {
|
||||
Log.e(TAG, "create file to exported failed");
|
||||
return null;
|
||||
}
|
||||
mFileName = file.getName();
|
||||
mFileDirectory = mContext.getString(R.string.file_path);
|
||||
PrintStream ps = null;
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
ps = new PrintStream(fos);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return ps;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成用于存储导入数据的文本文件
|
||||
*/
|
||||
private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) {
|
||||
// 构建文件路径
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(Environment.getExternalStorageDirectory());
|
||||
sb.append(context.getString(filePathResId));
|
||||
File filedir = new File(sb.toString());
|
||||
sb.append(context.getString(
|
||||
fileNameFormatResId,
|
||||
DateFormat.format(context.getString(R.string.format_date_ymd),
|
||||
System.currentTimeMillis())));
|
||||
File file = new File(sb.toString());
|
||||
|
||||
try {
|
||||
// 创建文件夹和文件
|
||||
if (!filedir.exists()) {
|
||||
filedir.mkdir();
|
||||
}
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
return file;
|
||||
} catch (SecurityException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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.tool;
|
||||
|
||||
// 声明一个名为 GTaskStringUtils 的公共类
|
||||
public class GTaskStringUtils {
|
||||
|
||||
// 定义 JSON 中动作 ID 的键
|
||||
public final static String GTASK_JSON_ACTION_ID = "action_id";
|
||||
|
||||
// 定义 JSON 中动作列表的键
|
||||
public final static String GTASK_JSON_ACTION_LIST = "action_list";
|
||||
|
||||
// 定义 JSON 中动作类型的键
|
||||
public final static String GTASK_JSON_ACTION_TYPE = "action_type";
|
||||
|
||||
// 定义 JSON 中创建动作类型的值
|
||||
public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create";
|
||||
|
||||
// 定义 JSON 中获取全部动作类型的值
|
||||
public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all";
|
||||
|
||||
// 定义 JSON 中移动动作类型的值
|
||||
public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move";
|
||||
|
||||
// 定义 JSON 中更新动作类型的值
|
||||
public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update";
|
||||
|
||||
// 定义 JSON 中创建者 ID 的键
|
||||
public final static String GTASK_JSON_CREATOR_ID = "creator_id";
|
||||
|
||||
// 定义 JSON 中子实体的键
|
||||
public final static String GTASK_JSON_CHILD_ENTITY = "child_entity";
|
||||
|
||||
// 定义 JSON 中客户端版本的键
|
||||
public final static String GTASK_JSON_CLIENT_VERSION = "client_version";
|
||||
|
||||
// 定义 JSON 中完成状态的键
|
||||
public final static String GTASK_JSON_COMPLETED = "completed";
|
||||
|
||||
// 定义 JSON 中当前列表 ID 的键
|
||||
public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id";
|
||||
|
||||
// 定义 JSON 中默认列表 ID 的键
|
||||
public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id";
|
||||
|
||||
// 定义 JSON 中删除状态的键
|
||||
public final static String GTASK_JSON_DELETED = "deleted";
|
||||
|
||||
// 定义 JSON 中目标列表的键
|
||||
public final static String GTASK_JSON_DEST_LIST = "dest_list";
|
||||
|
||||
// 定义 JSON 中目标父实体的键
|
||||
public final static String GTASK_JSON_DEST_PARENT = "dest_parent";
|
||||
|
||||
// 定义 JSON 中目标父实体类型的键
|
||||
public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type";
|
||||
|
||||
// 定义 JSON 中实体差异的键
|
||||
public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta";
|
||||
|
||||
// 定义 JSON 中实体类型的键
|
||||
public final static String GTASK_JSON_ENTITY_TYPE = "entity_type";
|
||||
|
||||
// 定义 JSON 中获取删除状态的键
|
||||
public final static String GTASK_JSON_GET_DELETED = "get_deleted";
|
||||
|
||||
// 定义 JSON 中 ID 的键
|
||||
public final static String GTASK_JSON_ID = "id";
|
||||
|
||||
// 定义 JSON 中索引的键
|
||||
public final static String GTASK_JSON_INDEX = "index";
|
||||
|
||||
// 定义 JSON 中最后修改时间的键
|
||||
public final static String GTASK_JSON_LAST_MODIFIED = "last_modified";
|
||||
|
||||
// 定义 JSON 中最新同步点的键
|
||||
public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point";
|
||||
|
||||
// 定义 JSON 中列表 ID 的键
|
||||
public final static String GTASK_JSON_LIST_ID = "list_id";
|
||||
|
||||
// 定义 JSON 中列表的键
|
||||
public final static String GTASK_JSON_LISTS = "lists";
|
||||
|
||||
// 定义 JSON 中名称的键
|
||||
public final static String GTASK_JSON_NAME = "name";
|
||||
|
||||
// 定义 JSON 中新 ID 的键
|
||||
public final static String GTASK_JSON_NEW_ID = "new_id";
|
||||
|
||||
// 定义 JSON 中笔记的键
|
||||
public final static String GTASK_JSON_NOTES = "notes";
|
||||
|
||||
// 定义 JSON 中父 ID 的键
|
||||
public final static String GTASK_JSON_PARENT_ID = "parent_id";
|
||||
|
||||
// 定义 JSON 中前一个兄弟 ID 的键
|
||||
public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id";
|
||||
|
||||
// 定义 JSON 中结果的键
|
||||
public final static String GTASK_JSON_RESULTS = "results";
|
||||
|
||||
// 定义 JSON 中源列表的键
|
||||
public final static String GTASK_JSON_SOURCE_LIST = "source_list";
|
||||
|
||||
// 定义 JSON 中任务的键
|
||||
public final static String GTASK_JSON_TASKS = "tasks";
|
||||
|
||||
// 定义 JSON 中类型的键
|
||||
public final static String GTASK_JSON_TYPE = "type";
|
||||
|
||||
// 定义 JSON 中组类型的值
|
||||
public final static String GTASK_JSON_TYPE_GROUP = "GROUP";
|
||||
|
||||
// 定义 JSON 中任务类型的值
|
||||
public final static String GTASK_JSON_TYPE_TASK = "TASK";
|
||||
|
||||
// 定义 JSON 中用户的键
|
||||
public final static String GTASK_JSON_USER = "user";
|
||||
|
||||
// 定义 MIUI 笔记文件夹前缀
|
||||
public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]";
|
||||
|
||||
// 定义默认文件夹名称
|
||||
public final static String FOLDER_DEFAULT = "Default";
|
||||
|
||||
// 定义通话笔记文件夹名称
|
||||
public final static String FOLDER_CALL_NOTE = "Call_Note";
|
||||
|
||||
// 定义元数据文件夹名称
|
||||
public final static String FOLDER_META = "METADATA";
|
||||
|
||||
// 定义元数据头部 GTASK ID 的键
|
||||
public final static String META_HEAD_GTASK_ID = "meta_gid";
|
||||
|
||||
// 定义元数据头部笔记的键
|
||||
public final static String META_HEAD_NOTE = "meta_note";
|
||||
|
||||
// 定义元数据头部数据的键
|
||||
public final static String META_HEAD_DATA = "meta_data";
|
||||
|
||||
// 定义元数据笔记名称
|
||||
public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE";
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 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.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import net.micode.notes.data.Contact;
|
||||
import net.micode.notes.data.Notes;
|
||||
import net.micode.notes.data.Notes.NoteColumns;
|
||||
import net.micode.notes.tool.DataUtils;
|
||||
|
||||
|
||||
public class NoteItemData {
|
||||
static final String [] PROJECTION = new String [] {
|
||||
NoteColumns.ID,
|
||||
NoteColumns.ALERTED_DATE,
|
||||
NoteColumns.BG_COLOR_ID,
|
||||
NoteColumns.CREATED_DATE,
|
||||
NoteColumns.HAS_ATTACHMENT,
|
||||
NoteColumns.MODIFIED_DATE,
|
||||
NoteColumns.NOTES_COUNT,
|
||||
NoteColumns.PARENT_ID,
|
||||
NoteColumns.SNIPPET,
|
||||
NoteColumns.TYPE,
|
||||
NoteColumns.WIDGET_ID,
|
||||
NoteColumns.WIDGET_TYPE,
|
||||
};
|
||||
|
||||
private static final int ID_COLUMN = 0;
|
||||
private static final int ALERTED_DATE_COLUMN = 1;
|
||||
private static final int BG_COLOR_ID_COLUMN = 2;
|
||||
private static final int CREATED_DATE_COLUMN = 3;
|
||||
private static final int HAS_ATTACHMENT_COLUMN = 4;
|
||||
private static final int MODIFIED_DATE_COLUMN = 5;
|
||||
private static final int NOTES_COUNT_COLUMN = 6;
|
||||
private static final int PARENT_ID_COLUMN = 7;
|
||||
private static final int SNIPPET_COLUMN = 8;
|
||||
private static final int TYPE_COLUMN = 9;
|
||||
private static final int WIDGET_ID_COLUMN = 10;
|
||||
private static final int WIDGET_TYPE_COLUMN = 11;
|
||||
|
||||
private long mId;
|
||||
private long mAlertDate;
|
||||
private int mBgColorId;
|
||||
private long mCreatedDate;
|
||||
private boolean mHasAttachment;
|
||||
private long mModifiedDate;
|
||||
private int mNotesCount;
|
||||
private long mParentId;
|
||||
private String mSnippet;
|
||||
private int mType;
|
||||
private int mWidgetId;
|
||||
private int mWidgetType;
|
||||
private String mName;
|
||||
private String mPhoneNumber;
|
||||
|
||||
private boolean mIsLastItem;
|
||||
private boolean mIsFirstItem;
|
||||
private boolean mIsOnlyOneItem;
|
||||
private boolean mIsOneNoteFollowingFolder;
|
||||
private boolean mIsMultiNotesFollowingFolder;
|
||||
|
||||
public NoteItemData(Context context, Cursor cursor) {
|
||||
mId = cursor.getLong(ID_COLUMN);
|
||||
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
|
||||
mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN);
|
||||
mCreatedDate = cursor.getLong(CREATED_DATE_COLUMN);
|
||||
mHasAttachment = (cursor.getInt(HAS_ATTACHMENT_COLUMN) > 0) ? true : false;
|
||||
mModifiedDate = cursor.getLong(MODIFIED_DATE_COLUMN);
|
||||
mNotesCount = cursor.getInt(NOTES_COUNT_COLUMN);
|
||||
mParentId = cursor.getLong(PARENT_ID_COLUMN);
|
||||
mSnippet = cursor.getString(SNIPPET_COLUMN);
|
||||
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace(
|
||||
NoteEditActivity.TAG_UNCHECKED, "");
|
||||
mType = cursor.getInt(TYPE_COLUMN);
|
||||
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
|
||||
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
|
||||
|
||||
mPhoneNumber = "";
|
||||
if (mParentId == Notes.ID_CALL_RECORD_FOLDER) {
|
||||
mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId);
|
||||
if (!TextUtils.isEmpty(mPhoneNumber)) {
|
||||
mName = Contact.getContact(context, mPhoneNumber);
|
||||
if (mName == null) {
|
||||
mName = mPhoneNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mName == null) {
|
||||
mName = "";
|
||||
}
|
||||
checkPostion(cursor);
|
||||
}
|
||||
|
||||
private void checkPostion(Cursor cursor) {
|
||||
mIsLastItem = cursor.isLast() ? true : false;
|
||||
mIsFirstItem = cursor.isFirst() ? true : false;
|
||||
mIsOnlyOneItem = (cursor.getCount() == 1);
|
||||
mIsMultiNotesFollowingFolder = false;
|
||||
mIsOneNoteFollowingFolder = false;
|
||||
|
||||
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
|
||||
int position = cursor.getPosition();
|
||||
if (cursor.moveToPrevious()) {
|
||||
if (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER
|
||||
|| cursor.getInt(TYPE_COLUMN) == Notes.TYPE_SYSTEM) {
|
||||
if (cursor.getCount() > (position + 1)) {
|
||||
mIsMultiNotesFollowingFolder = true;
|
||||
} else {
|
||||
mIsOneNoteFollowingFolder = true;
|
||||
}
|
||||
}
|
||||
if (!cursor.moveToNext()) {
|
||||
throw new IllegalStateException("cursor move to previous but can't move back");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOneFollowingFolder() {
|
||||
return mIsOneNoteFollowingFolder;
|
||||
}
|
||||
|
||||
public boolean isMultiFollowingFolder() {
|
||||
return mIsMultiNotesFollowingFolder;
|
||||
}
|
||||
|
||||
public boolean isLast() {
|
||||
return mIsLastItem;
|
||||
}
|
||||
|
||||
public String getCallName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public boolean isFirst() {
|
||||
return mIsFirstItem;
|
||||
}
|
||||
|
||||
public boolean isSingle() {
|
||||
return mIsOnlyOneItem;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
public long getAlertDate() {
|
||||
return mAlertDate;
|
||||
}
|
||||
|
||||
public long getCreatedDate() {
|
||||
return mCreatedDate;
|
||||
}
|
||||
|
||||
public boolean hasAttachment() {
|
||||
return mHasAttachment;
|
||||
}
|
||||
|
||||
public long getModifiedDate() {
|
||||
return mModifiedDate;
|
||||
}
|
||||
|
||||
public int getBgColorId() {
|
||||
return mBgColorId;
|
||||
}
|
||||
|
||||
public long getParentId() {
|
||||
return mParentId;
|
||||
}
|
||||
|
||||
public int getNotesCount() {
|
||||
return mNotesCount;
|
||||
}
|
||||
|
||||
public long getFolderId () {
|
||||
return mParentId;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
public int getWidgetType() {
|
||||
return mWidgetType;
|
||||
}
|
||||
|
||||
public int getWidgetId() {
|
||||
return mWidgetId;
|
||||
}
|
||||
|
||||
public String getSnippet() {
|
||||
return mSnippet;
|
||||
}
|
||||
|
||||
public boolean hasAlert() {
|
||||
return (mAlertDate > 0);
|
||||
}
|
||||
|
||||
public boolean isCallRecord() {
|
||||
return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber));
|
||||
}
|
||||
|
||||
public static int getNoteType(Cursor cursor) {
|
||||
return cursor.getInt(TYPE_COLUMN);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.content.Context;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import net.micode.notes.R;
|
||||
import net.micode.notes.data.Notes;
|
||||
import net.micode.notes.tool.DataUtils;
|
||||
import net.micode.notes.tool.ResourceParser.NoteItemBgResources;
|
||||
|
||||
|
||||
public class NotesListItem extends LinearLayout {
|
||||
private ImageView mAlert;
|
||||
private TextView mTitle;
|
||||
private TextView mTime;
|
||||
private TextView mCallName;
|
||||
private NoteItemData mItemData;
|
||||
private CheckBox mCheckBox;
|
||||
|
||||
public NotesListItem(Context context) {
|
||||
super(context);
|
||||
inflate(context, R.layout.note_item, this);
|
||||
mAlert = (ImageView) findViewById(R.id.iv_alert_icon);
|
||||
mTitle = (TextView) findViewById(R.id.tv_title);
|
||||
mTime = (TextView) findViewById(R.id.tv_time);
|
||||
mCallName = (TextView) findViewById(R.id.tv_name);
|
||||
mCheckBox = (CheckBox) findViewById(android.R.id.checkbox);
|
||||
}
|
||||
|
||||
public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) {
|
||||
if (choiceMode && data.getType() == Notes.TYPE_NOTE) {
|
||||
mCheckBox.setVisibility(View.VISIBLE);
|
||||
mCheckBox.setChecked(checked);
|
||||
} else {
|
||||
mCheckBox.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
mItemData = data;
|
||||
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
|
||||
mCallName.setVisibility(View.GONE);
|
||||
mAlert.setVisibility(View.VISIBLE);
|
||||
mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
|
||||
mTitle.setText(context.getString(R.string.call_record_folder_name)
|
||||
+ context.getString(R.string.format_folder_files_count, data.getNotesCount()));
|
||||
mAlert.setImageResource(R.drawable.call_record);
|
||||
} else if (data.getParentId() == Notes.ID_CALL_RECORD_FOLDER) {
|
||||
mCallName.setVisibility(View.VISIBLE);
|
||||
mCallName.setText(data.getCallName());
|
||||
mTitle.setTextAppearance(context,R.style.TextAppearanceSecondaryItem);
|
||||
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
|
||||
if (data.hasAlert()) {
|
||||
mAlert.setImageResource(R.drawable.clock);
|
||||
mAlert.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mAlert.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
mCallName.setVisibility(View.GONE);
|
||||
mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
|
||||
|
||||
if (data.getType() == Notes.TYPE_FOLDER) {
|
||||
mTitle.setText(data.getSnippet()
|
||||
+ context.getString(R.string.format_folder_files_count,
|
||||
data.getNotesCount()));
|
||||
mAlert.setVisibility(View.GONE);
|
||||
} else {
|
||||
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
|
||||
if (data.hasAlert()) {
|
||||
mAlert.setImageResource(R.drawable.clock);
|
||||
mAlert.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mAlert.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate()));
|
||||
|
||||
setBackground(data);
|
||||
}
|
||||
|
||||
private void setBackground(NoteItemData data) {
|
||||
int id = data.getBgColorId();
|
||||
if (data.getType() == Notes.TYPE_NOTE) {
|
||||
if (data.isSingle() || data.isOneFollowingFolder()) {
|
||||
setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id));
|
||||
} else if (data.isLast()) {
|
||||
setBackgroundResource(NoteItemBgResources.getNoteBgLastRes(id));
|
||||
} else if (data.isFirst() || data.isMultiFollowingFolder()) {
|
||||
setBackgroundResource(NoteItemBgResources.getNoteBgFirstRes(id));
|
||||
} else {
|
||||
setBackgroundResource(NoteItemBgResources.getNoteBgNormalRes(id));
|
||||
}
|
||||
} else {
|
||||
setBackgroundResource(NoteItemBgResources.getFolderBgRes());
|
||||
}
|
||||
}
|
||||
|
||||
public NoteItemData getItemData() {
|
||||
return mItemData;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue