parent
fe423345eb
commit
5e7bf0e288
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/gitProject.iml" filepath="$PROJECT_DIR$/.idea/gitProject.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public class GTaskStringUtils {
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ACTION_ID = "action_id";// 行动 ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ACTION_LIST = "action_list";// 行动清单
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ACTION_TYPE = "action_type";// 行动类型
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create";// 创建行动
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all";// 获取全部行动
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move";// 移动行动
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; // 更新行动
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_CREATOR_ID = "creator_id";// 创建者 ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_CHILD_ENTITY = "child_entity";// 子实体
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_CLIENT_VERSION = "client_version";// 客户端版本
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_COMPLETED = "completed"; // 完成状态
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id";// 当前清单 ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; // 默认清单 ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_DELETED = "deleted";// 删除状态
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_DEST_LIST = "dest_list";// 目标清单
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_DEST_PARENT = "dest_parent";// 目标父元素
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; // 目标父元素类型
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta";// 实体增量
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; // 实体类型
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_GET_DELETED = "get_deleted"; // 获取删除状态
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_ID = "id";// ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_INDEX = "index";// 索引
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; // 最后修改时间
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point";// 最新同步点
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_LIST_ID = "list_id"; // 清单 ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_LISTS = "lists";// 清单列表
|
||||||
|
public final static String GTASK_JSON_NAME = "name";// 名称
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_NEW_ID = "new_id";// 新 ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_NOTES = "notes";// 备注
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_PARENT_ID = "parent_id";// 父 ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id";// 上一个同级 ID
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_RESULTS = "results";// 结果
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_SOURCE_LIST = "source_list";// 源清单
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_TASKS = "tasks";// 任务列表
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_TYPE = "type";// 类型
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_TYPE_GROUP = "GROUP";// 分组类型
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_TYPE_TASK = "TASK";// 任务类型
|
||||||
|
|
||||||
|
public final static String GTASK_JSON_USER = "user";// 用户
|
||||||
|
|
||||||
|
public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; // MIUI 笔记前缀
|
||||||
|
|
||||||
|
public final static String FOLDER_DEFAULT = "Default";// 默认文件夹
|
||||||
|
|
||||||
|
public final static String FOLDER_CALL_NOTE = "Call_Note"; // 通话笔记文件夹
|
||||||
|
|
||||||
|
public final static String FOLDER_META = "METADATA";// 元数据文件夹
|
||||||
|
|
||||||
|
public final static String META_HEAD_GTASK_ID = "meta_gid";// GTASK ID 元数据头
|
||||||
|
|
||||||
|
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";// 元数据笔记名称
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.provider.ContactsContract.CommonDataKinds.Phone;
|
||||||
|
import android.provider.ContactsContract.Data;
|
||||||
|
import android.telephony.PhoneNumberUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class Contact {
|
||||||
|
private static HashMap<String, String> sContactCache;// 用于缓存已查询过的联系人信息
|
||||||
|
private static final String TAG = "Contact";// 用于日志输出的 TAG
|
||||||
|
|
||||||
|
// 查询电话号码与联系人名字匹配的过滤条件
|
||||||
|
private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER
|
||||||
|
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"
|
||||||
|
+ " AND " + Data.RAW_CONTACT_ID + " IN "
|
||||||
|
+ "(SELECT raw_contact_id "
|
||||||
|
+ " FROM phone_lookup"
|
||||||
|
+ " WHERE min_match = '+')";
|
||||||
|
/*
|
||||||
|
* 获取电话号码对应的联系人名字
|
||||||
|
* @param context 上下文
|
||||||
|
* @param phoneNumber 电话号码
|
||||||
|
* @return 电话号码对应的联系人名字
|
||||||
|
*/
|
||||||
|
public static String getContact(Context context, String phoneNumber) {
|
||||||
|
// 如果缓存为空,创建新的缓存对象
|
||||||
|
if(sContactCache == null) {
|
||||||
|
sContactCache = new HashMap<String, String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果已经查询过该电话号码,直接返回缓存中的联系人名字
|
||||||
|
if(sContactCache.containsKey(phoneNumber)) {
|
||||||
|
return sContactCache.get(phoneNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造查询条件
|
||||||
|
String selection = CALLER_ID_SELECTION.replace("+",
|
||||||
|
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));
|
||||||
|
Cursor cursor = context.getContentResolver().query(
|
||||||
|
Data.CONTENT_URI,
|
||||||
|
new String [] { Phone.DISPLAY_NAME },
|
||||||
|
selection,
|
||||||
|
new String[] { phoneNumber },
|
||||||
|
null);
|
||||||
|
|
||||||
|
// 如果能够查询到联系人信息
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
try {
|
||||||
|
String name = cursor.getString(0);
|
||||||
|
// 将电话号码与联系人名字加入缓存中
|
||||||
|
sContactCache.put(phoneNumber, name);
|
||||||
|
return name;
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
Log.e(TAG, " Cursor get string error " + e.toString());
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
cursor.close();// 关闭查询结果游标
|
||||||
|
}
|
||||||
|
} else {// 如果未能查询到联系人信息,输出日志并返回 null
|
||||||
|
Log.d(TAG, "No contact matched with number:" + phoneNumber);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.exception;
|
||||||
|
|
||||||
|
public class ActionFailureException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 4425249765923293627L;
|
||||||
|
|
||||||
|
public ActionFailureException() {
|
||||||
|
super(); // 调用父类的构造函数
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionFailureException(String paramString) {
|
||||||
|
super(paramString); // 调用父类的构造函数,并传入异常信息
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionFailureException(String paramString, Throwable paramThrowable) {
|
||||||
|
super(paramString, paramThrowable); // 调用父类的构造函数,并传入异常信息和原始异常
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* 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.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import net.micode.notes.R;
|
||||||
|
import net.micode.notes.ui.NotesListActivity;
|
||||||
|
import net.micode.notes.ui.NotesPreferenceActivity;
|
||||||
|
|
||||||
|
|
||||||
|
public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
|
||||||
|
|
||||||
|
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
|
||||||
|
|
||||||
|
public interface OnCompleteListener {
|
||||||
|
void onComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Context mContext; // 上下文对象
|
||||||
|
|
||||||
|
private NotificationManager mNotifiManager; // 通知管理器对象
|
||||||
|
|
||||||
|
private GTaskManager mTaskManager; // GTask 管理器对象
|
||||||
|
|
||||||
|
private OnCompleteListener mOnCompleteListener; // 异步任务完成后的回调接口
|
||||||
|
|
||||||
|
public GTaskASyncTask(Context context, OnCompleteListener listener) {
|
||||||
|
mContext = context; // 初始化上下文对象
|
||||||
|
mOnCompleteListener = listener; // 初始化回调接口
|
||||||
|
mNotifiManager = (NotificationManager) mContext
|
||||||
|
.getSystemService(Context.NOTIFICATION_SERVICE); // 初始化通知管理器对象
|
||||||
|
mTaskManager = GTaskManager.getInstance(); // 获取 GTask 管理器对象的单例
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelSync() {
|
||||||
|
mTaskManager.cancelSync(); // 取消 GTask 同步
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publishProgess(String message) {
|
||||||
|
publishProgress(new String[] {
|
||||||
|
message
|
||||||
|
}); // 向主线程发布进度更新
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNotification(int tickerId, String content) {
|
||||||
|
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,
|
||||||
|
NotesPreferenceActivity.class), 0); // 点击通知后打开 NotesPreferenceActivity
|
||||||
|
|
||||||
|
} else { // 如果是同步成功的通知
|
||||||
|
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
|
||||||
|
NotesListActivity.class), 0); // 点击通知后打开 NotesListActivity
|
||||||
|
}
|
||||||
|
//notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
|
||||||
|
// pendingIntent); // 设置通知的标题、内容和点击后的操作
|
||||||
|
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); // 开始 GTask 同步,并返回同步结果
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate(String... progress) {
|
||||||
|
showNotification(R.string.ticker_syncing, progress[0]); // 显示同步进度的通知
|
||||||
|
if (mContext instanceof GTaskSyncService) {
|
||||||
|
((GTaskSyncService) mContext).sendBroadcast(progress[0]); // 向 GTaskSyncService 发送广播,以便更新 UI
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Integer result) {
|
||||||
|
if (result == GTaskManager.STATE_SUCCESS) { // 如果同步成功
|
||||||
|
showNotification(R.string.ticker_success, mContext.getString(
|
||||||
|
R.string.success_sync_account, mTaskManager.getSyncAccount())); // 显示同步成功的通知
|
||||||
|
NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis()); // 更新最后同步时间
|
||||||
|
} else if (result == GTaskManager.STATE_NETWORK_ERROR) { // 如果网络错误
|
||||||
|
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network)); // 显示同步失败的通知,提示网络错误
|
||||||
|
} else if (result == GTaskManager.STATE_INTERNAL_ERROR) { // 如果内部错误
|
||||||
|
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal)); // 显示同步失败的通知,提示内部错误
|
||||||
|
} else if (result == GTaskManager.STATE_SYNC_CANCELLED) { // 如果同步被取消
|
||||||
|
showNotification(R.string.ticker_cancel, mContext
|
||||||
|
.getString(R.string.error_sync_cancelled)); // 显示同步被取消的通知
|
||||||
|
}
|
||||||
|
if (mOnCompleteListener != null) { // 如果设置了 OnCompleteListener
|
||||||
|
new Thread(new Runnable() { // 在新线程中执行 OnCompleteListener
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
mOnCompleteListener.onComplete();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.exception;
|
||||||
|
|
||||||
|
public class NetworkFailureException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 2107610287180234136L;
|
||||||
|
|
||||||
|
public NetworkFailureException() {
|
||||||
|
super(); // 调用父类的构造函数
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkFailureException(String paramString) {
|
||||||
|
super(paramString); // 调用父类的构造函数,并传入异常信息
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkFailureException(String paramString, Throwable paramThrowable) {
|
||||||
|
super(paramString, paramThrowable); // 调用父类的构造函数,并传入异常信息和原始异常
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,505 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import android.appwidget.AppWidgetManager;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import net.micode.notes.data.Notes;
|
||||||
|
import net.micode.notes.data.Notes.DataColumns;
|
||||||
|
import net.micode.notes.data.Notes.NoteColumns;
|
||||||
|
import net.micode.notes.gtask.exception.ActionFailureException;
|
||||||
|
import net.micode.notes.tool.GTaskStringUtils;
|
||||||
|
import net.micode.notes.tool.ResourceParser;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
public class SqlNote {
|
||||||
|
private static final String TAG = SqlNote.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final int INVALID_ID = -99999;
|
||||||
|
|
||||||
|
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,
|
||||||
|
NoteColumns.NOTES_COUNT, NoteColumns.PARENT_ID, NoteColumns.SNIPPET, NoteColumns.TYPE,
|
||||||
|
NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, NoteColumns.SYNC_ID,
|
||||||
|
NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID,
|
||||||
|
NoteColumns.VERSION
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final int ID_COLUMN = 0;
|
||||||
|
|
||||||
|
public static final int ALERTED_DATE_COLUMN = 1;
|
||||||
|
|
||||||
|
public static final int BG_COLOR_ID_COLUMN = 2;
|
||||||
|
|
||||||
|
public static final int CREATED_DATE_COLUMN = 3;
|
||||||
|
|
||||||
|
public static final int HAS_ATTACHMENT_COLUMN = 4;
|
||||||
|
|
||||||
|
public static final int MODIFIED_DATE_COLUMN = 5;
|
||||||
|
|
||||||
|
public static final int NOTES_COUNT_COLUMN = 6;
|
||||||
|
|
||||||
|
public static final int PARENT_ID_COLUMN = 7;
|
||||||
|
|
||||||
|
public static final int SNIPPET_COLUMN = 8;
|
||||||
|
|
||||||
|
public static final int TYPE_COLUMN = 9;
|
||||||
|
|
||||||
|
public static final int WIDGET_ID_COLUMN = 10;
|
||||||
|
|
||||||
|
public static final int WIDGET_TYPE_COLUMN = 11;
|
||||||
|
|
||||||
|
public static final int SYNC_ID_COLUMN = 12;
|
||||||
|
|
||||||
|
public static final int LOCAL_MODIFIED_COLUMN = 13;
|
||||||
|
|
||||||
|
public static final int ORIGIN_PARENT_ID_COLUMN = 14;
|
||||||
|
|
||||||
|
public static final int GTASK_ID_COLUMN = 15;
|
||||||
|
|
||||||
|
public static final int VERSION_COLUMN = 16;
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
private ContentResolver mContentResolver;
|
||||||
|
|
||||||
|
private boolean mIsCreate;
|
||||||
|
|
||||||
|
private long mId;
|
||||||
|
|
||||||
|
private long mAlertDate;
|
||||||
|
|
||||||
|
private int mBgColorId;
|
||||||
|
|
||||||
|
private long mCreatedDate;
|
||||||
|
|
||||||
|
private int mHasAttachment;
|
||||||
|
|
||||||
|
private long mModifiedDate;
|
||||||
|
|
||||||
|
private long mParentId;
|
||||||
|
|
||||||
|
private String mSnippet;
|
||||||
|
|
||||||
|
private int mType;
|
||||||
|
|
||||||
|
private int mWidgetId;
|
||||||
|
|
||||||
|
private int mWidgetType;
|
||||||
|
|
||||||
|
private long mOriginParent;
|
||||||
|
|
||||||
|
private long mVersion;
|
||||||
|
|
||||||
|
private ContentValues mDiffNoteValues;
|
||||||
|
|
||||||
|
private ArrayList<SqlData> mDataList;
|
||||||
|
|
||||||
|
public SqlNote(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
mContentResolver = context.getContentResolver();
|
||||||
|
mIsCreate = true;
|
||||||
|
mId = INVALID_ID;
|
||||||
|
mAlertDate = 0;
|
||||||
|
mBgColorId = ResourceParser.getDefaultBgId(context);
|
||||||
|
mCreatedDate = System.currentTimeMillis();
|
||||||
|
mHasAttachment = 0;
|
||||||
|
mModifiedDate = System.currentTimeMillis();
|
||||||
|
mParentId = 0;
|
||||||
|
mSnippet = "";
|
||||||
|
mType = Notes.TYPE_NOTE;
|
||||||
|
mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
|
||||||
|
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
|
||||||
|
mOriginParent = 0;
|
||||||
|
mVersion = 0;
|
||||||
|
mDiffNoteValues = new ContentValues();
|
||||||
|
mDataList = new ArrayList<SqlData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlNote(Context context, Cursor c) {
|
||||||
|
mContext = context;
|
||||||
|
mContentResolver = context.getContentResolver();
|
||||||
|
mIsCreate = false;
|
||||||
|
loadFromCursor(c);
|
||||||
|
mDataList = new ArrayList<SqlData>();
|
||||||
|
if (mType == Notes.TYPE_NOTE)
|
||||||
|
loadDataContent();
|
||||||
|
mDiffNoteValues = new ContentValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlNote(Context context, long id) {
|
||||||
|
mContext = context;
|
||||||
|
mContentResolver = context.getContentResolver();
|
||||||
|
mIsCreate = false;
|
||||||
|
loadFromCursor(id);
|
||||||
|
mDataList = new ArrayList<SqlData>();
|
||||||
|
if (mType == Notes.TYPE_NOTE)
|
||||||
|
loadDataContent();
|
||||||
|
mDiffNoteValues = new ContentValues();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFromCursor(long id) {
|
||||||
|
Cursor c = null;
|
||||||
|
try {
|
||||||
|
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
|
||||||
|
new String[] {
|
||||||
|
String.valueOf(id)
|
||||||
|
}, null);
|
||||||
|
if (c != null) {
|
||||||
|
c.moveToNext();
|
||||||
|
loadFromCursor(c);
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "loadFromCursor: cursor = null");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (c != null)
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFromCursor(Cursor c) {
|
||||||
|
mId = c.getLong(ID_COLUMN);
|
||||||
|
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
|
||||||
|
mBgColorId = c.getInt(BG_COLOR_ID_COLUMN);
|
||||||
|
mCreatedDate = c.getLong(CREATED_DATE_COLUMN);
|
||||||
|
mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN);
|
||||||
|
mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN);
|
||||||
|
mParentId = c.getLong(PARENT_ID_COLUMN);
|
||||||
|
mSnippet = c.getString(SNIPPET_COLUMN);
|
||||||
|
mType = c.getInt(TYPE_COLUMN);
|
||||||
|
mWidgetId = c.getInt(WIDGET_ID_COLUMN);
|
||||||
|
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
|
||||||
|
mVersion = c.getLong(VERSION_COLUMN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadDataContent() {
|
||||||
|
Cursor c = null;
|
||||||
|
mDataList.clear();
|
||||||
|
try {
|
||||||
|
c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA,
|
||||||
|
"(note_id=?)", new String[] {
|
||||||
|
String.valueOf(mId)
|
||||||
|
}, null);
|
||||||
|
if (c != null) {
|
||||||
|
if (c.getCount() == 0) {
|
||||||
|
Log.w(TAG, "it seems that the note has not data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
SqlData data = new SqlData(mContext, c);
|
||||||
|
mDataList.add(data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "loadDataContent: cursor = null");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (c != null)
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
|
||||||
|
// for folder we can only update the snnipet and type
|
||||||
|
String snippet = note.has(NoteColumns.SNIPPET) ? note
|
||||||
|
.getString(NoteColumns.SNIPPET) : "";
|
||||||
|
if (mIsCreate || !mSnippet.equals(snippet)) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
|
||||||
|
}
|
||||||
|
mSnippet = snippet;
|
||||||
|
|
||||||
|
int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE)
|
||||||
|
: Notes.TYPE_NOTE;
|
||||||
|
if (mIsCreate || mType != type) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.TYPE, type);
|
||||||
|
}
|
||||||
|
mType = type;
|
||||||
|
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {
|
||||||
|
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
|
||||||
|
long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID;
|
||||||
|
if (mIsCreate || mId != id) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.ID, id);
|
||||||
|
}
|
||||||
|
mId = id;
|
||||||
|
|
||||||
|
long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note
|
||||||
|
.getLong(NoteColumns.ALERTED_DATE) : 0;
|
||||||
|
if (mIsCreate || mAlertDate != alertDate) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate);
|
||||||
|
}
|
||||||
|
mAlertDate = alertDate;
|
||||||
|
|
||||||
|
int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note
|
||||||
|
.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);
|
||||||
|
if (mIsCreate || mBgColorId != bgColorId) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
|
||||||
|
}
|
||||||
|
mBgColorId = bgColorId;
|
||||||
|
|
||||||
|
long createDate = note.has(NoteColumns.CREATED_DATE) ? note
|
||||||
|
.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();
|
||||||
|
if (mIsCreate || mCreatedDate != createDate) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate);
|
||||||
|
}
|
||||||
|
mCreatedDate = createDate;
|
||||||
|
|
||||||
|
int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note
|
||||||
|
.getInt(NoteColumns.HAS_ATTACHMENT) : 0;
|
||||||
|
if (mIsCreate || mHasAttachment != hasAttachment) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment);
|
||||||
|
}
|
||||||
|
mHasAttachment = hasAttachment;
|
||||||
|
|
||||||
|
long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note
|
||||||
|
.getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis();
|
||||||
|
if (mIsCreate || mModifiedDate != modifiedDate) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate);
|
||||||
|
}
|
||||||
|
mModifiedDate = modifiedDate;
|
||||||
|
|
||||||
|
long parentId = note.has(NoteColumns.PARENT_ID) ? note
|
||||||
|
.getLong(NoteColumns.PARENT_ID) : 0;
|
||||||
|
if (mIsCreate || mParentId != parentId) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId);
|
||||||
|
}
|
||||||
|
mParentId = parentId;
|
||||||
|
|
||||||
|
String snippet = note.has(NoteColumns.SNIPPET) ? note
|
||||||
|
.getString(NoteColumns.SNIPPET) : "";
|
||||||
|
if (mIsCreate || !mSnippet.equals(snippet)) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
|
||||||
|
}
|
||||||
|
mSnippet = snippet;
|
||||||
|
|
||||||
|
int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE)
|
||||||
|
: Notes.TYPE_NOTE;
|
||||||
|
if (mIsCreate || mType != type) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.TYPE, type);
|
||||||
|
}
|
||||||
|
mType = type;
|
||||||
|
|
||||||
|
int widgetId = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID)
|
||||||
|
: AppWidgetManager.INVALID_APPWIDGET_ID;
|
||||||
|
if (mIsCreate || mWidgetId != widgetId) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId);
|
||||||
|
}
|
||||||
|
mWidgetId = widgetId;
|
||||||
|
|
||||||
|
int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note
|
||||||
|
.getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE;
|
||||||
|
if (mIsCreate || mWidgetType != widgetType) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType);
|
||||||
|
}
|
||||||
|
mWidgetType = widgetType;
|
||||||
|
|
||||||
|
long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note
|
||||||
|
.getLong(NoteColumns.ORIGIN_PARENT_ID) : 0;
|
||||||
|
if (mIsCreate || mOriginParent != originParent) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);
|
||||||
|
}
|
||||||
|
mOriginParent = originParent;
|
||||||
|
|
||||||
|
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 (SqlData temp : mDataList) {
|
||||||
|
if (dataId == temp.getId()) {
|
||||||
|
sqlData = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sqlData == null) {
|
||||||
|
sqlData = new SqlData(mContext);
|
||||||
|
mDataList.add(sqlData);
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlData.setContent(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getContent() {
|
||||||
|
try {
|
||||||
|
JSONObject js = new JSONObject();
|
||||||
|
|
||||||
|
if (mIsCreate) {
|
||||||
|
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);
|
||||||
|
note.put(NoteColumns.ALERTED_DATE, mAlertDate);
|
||||||
|
note.put(NoteColumns.BG_COLOR_ID, mBgColorId);
|
||||||
|
note.put(NoteColumns.CREATED_DATE, mCreatedDate);
|
||||||
|
note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment);
|
||||||
|
note.put(NoteColumns.MODIFIED_DATE, mModifiedDate);
|
||||||
|
note.put(NoteColumns.PARENT_ID, mParentId);
|
||||||
|
note.put(NoteColumns.SNIPPET, mSnippet);
|
||||||
|
note.put(NoteColumns.TYPE, mType);
|
||||||
|
note.put(NoteColumns.WIDGET_ID, mWidgetId);
|
||||||
|
note.put(NoteColumns.WIDGET_TYPE, mWidgetType);
|
||||||
|
note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent);
|
||||||
|
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
|
||||||
|
|
||||||
|
JSONArray dataArray = new JSONArray();
|
||||||
|
for (SqlData sqlData : mDataList) {
|
||||||
|
JSONObject data = sqlData.getContent();
|
||||||
|
if (data != null) {
|
||||||
|
dataArray.put(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
|
||||||
|
} 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);
|
||||||
|
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
|
||||||
|
}
|
||||||
|
|
||||||
|
return js;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentId(long id) {
|
||||||
|
mParentId = id;
|
||||||
|
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGtaskId(String gid) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyncId(long syncId) {
|
||||||
|
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetLocalModified() {
|
||||||
|
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getParentId() {
|
||||||
|
return mParentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSnippet() {
|
||||||
|
return mSnippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNoteType() {
|
||||||
|
return mType == Notes.TYPE_NOTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commit(boolean validateVersion) {
|
||||||
|
if (mIsCreate) {
|
||||||
|
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
|
||||||
|
mDiffNoteValues.remove(NoteColumns.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues);
|
||||||
|
try {
|
||||||
|
mId = Long.valueOf(uri.getPathSegments().get(1));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
Log.e(TAG, "Get note id error :" + e.toString());
|
||||||
|
throw new ActionFailureException("create note failed");
|
||||||
|
}
|
||||||
|
if (mId == 0) {
|
||||||
|
throw new IllegalStateException("Create thread id failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mType == Notes.TYPE_NOTE) {
|
||||||
|
for (SqlData sqlData : mDataList) {
|
||||||
|
sqlData.commit(mId, false, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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");
|
||||||
|
}
|
||||||
|
if (mDiffNoteValues.size() > 0) {
|
||||||
|
mVersion ++;
|
||||||
|
int result = 0;
|
||||||
|
if (!validateVersion) {
|
||||||
|
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
|
||||||
|
+ NoteColumns.ID + "=?)", new String[] {
|
||||||
|
String.valueOf(mId)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
|
||||||
|
+ NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)",
|
||||||
|
new String[] {
|
||||||
|
String.valueOf(mId), String.valueOf(mVersion)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// refresh local info
|
||||||
|
loadFromCursor(mId);
|
||||||
|
if (mType == Notes.TYPE_NOTE)
|
||||||
|
loadDataContent();
|
||||||
|
|
||||||
|
mDiffNoteValues.clear();
|
||||||
|
mIsCreate = false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
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 net.micode.notes.gtask.exception.ActionFailureException;
|
||||||
|
import net.micode.notes.tool.GTaskStringUtils;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
|
||||||
|
public class Task extends Node {
|
||||||
|
private static final String TAG = Task.class.getSimpleName();
|
||||||
|
|
||||||
|
private boolean mCompleted;
|
||||||
|
|
||||||
|
private String mNotes;
|
||||||
|
|
||||||
|
private JSONObject mMetaInfo;
|
||||||
|
|
||||||
|
private Task mPriorSibling;
|
||||||
|
|
||||||
|
private TaskList mParent;
|
||||||
|
|
||||||
|
public Task() {
|
||||||
|
super();
|
||||||
|
mCompleted = false;
|
||||||
|
mNotes = null;
|
||||||
|
mPriorSibling = null;
|
||||||
|
mParent = null;
|
||||||
|
mMetaInfo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getCreateAction(int actionId) {
|
||||||
|
JSONObject js = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// action_type
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
|
||||||
|
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
|
||||||
|
|
||||||
|
// action_id
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
|
||||||
|
|
||||||
|
// index
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));
|
||||||
|
|
||||||
|
// entity_delta
|
||||||
|
JSONObject entity = new JSONObject();
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
|
||||||
|
GTaskStringUtils.GTASK_JSON_TYPE_TASK);
|
||||||
|
if (getNotes() != null) {
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
|
||||||
|
}
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
|
||||||
|
|
||||||
|
// parent_id
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());
|
||||||
|
|
||||||
|
// dest_parent_type
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE,
|
||||||
|
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
|
||||||
|
|
||||||
|
// list_id
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
|
||||||
|
|
||||||
|
// prior_sibling_id
|
||||||
|
if (mPriorSibling != null) {
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid());
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new ActionFailureException("fail to generate task-create jsonobject");
|
||||||
|
}
|
||||||
|
|
||||||
|
return js;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getUpdateAction(int actionId) {
|
||||||
|
JSONObject js = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// action_type
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
|
||||||
|
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
|
||||||
|
|
||||||
|
// action_id
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
|
||||||
|
|
||||||
|
// id
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
|
||||||
|
|
||||||
|
// entity_delta
|
||||||
|
JSONObject entity = new JSONObject();
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
|
||||||
|
if (getNotes() != null) {
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
|
||||||
|
}
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new ActionFailureException("fail to generate task-update jsonobject");
|
||||||
|
}
|
||||||
|
|
||||||
|
return js;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentByRemoteJSON(JSONObject js) {
|
||||||
|
if (js != null) {
|
||||||
|
try {
|
||||||
|
// id
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
|
||||||
|
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
// last_modified
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
|
||||||
|
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
|
||||||
|
}
|
||||||
|
|
||||||
|
// name
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
|
||||||
|
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
// notes
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) {
|
||||||
|
setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES));
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleted
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) {
|
||||||
|
setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED));
|
||||||
|
}
|
||||||
|
|
||||||
|
// completed
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) {
|
||||||
|
setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED));
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new ActionFailureException("fail to get task content from jsonobject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentByLocalJSON(JSONObject js) {
|
||||||
|
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)
|
||||||
|
|| !js.has(GTaskStringUtils.META_HEAD_DATA)) {
|
||||||
|
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
|
||||||
|
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
|
||||||
|
|
||||||
|
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {
|
||||||
|
Log.e(TAG, "invalid type");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < dataArray.length(); i++) {
|
||||||
|
JSONObject data = dataArray.getJSONObject(i);
|
||||||
|
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
|
||||||
|
setName(data.getString(DataColumns.CONTENT));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getLocalJSONFromContent() {
|
||||||
|
String name = getName();
|
||||||
|
try {
|
||||||
|
if (mMetaInfo == null) {
|
||||||
|
// new task created from web
|
||||||
|
if (name == null) {
|
||||||
|
Log.w(TAG, "the note seems to be an empty one");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject js = new JSONObject();
|
||||||
|
JSONObject note = new JSONObject();
|
||||||
|
JSONArray dataArray = new JSONArray();
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put(DataColumns.CONTENT, name);
|
||||||
|
dataArray.put(data);
|
||||||
|
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
|
||||||
|
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
|
||||||
|
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
|
||||||
|
return js;
|
||||||
|
} else {
|
||||||
|
// synced task
|
||||||
|
JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
|
||||||
|
JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
|
||||||
|
|
||||||
|
for (int i = 0; i < dataArray.length(); i++) {
|
||||||
|
JSONObject data = dataArray.getJSONObject(i);
|
||||||
|
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
|
||||||
|
data.put(DataColumns.CONTENT, getName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
|
||||||
|
return mMetaInfo;
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetaInfo(MetaData metaData) {
|
||||||
|
if (metaData != null && metaData.getNotes() != null) {
|
||||||
|
try {
|
||||||
|
mMetaInfo = new JSONObject(metaData.getNotes());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.w(TAG, e.toString());
|
||||||
|
mMetaInfo = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSyncAction(Cursor c) {
|
||||||
|
try {
|
||||||
|
JSONObject noteInfo = null;
|
||||||
|
if (mMetaInfo != null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) {
|
||||||
|
noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noteInfo == null) {
|
||||||
|
Log.w(TAG, "it seems that note meta has been deleted");
|
||||||
|
return SYNC_ACTION_UPDATE_REMOTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noteInfo.has(NoteColumns.ID)) {
|
||||||
|
Log.w(TAG, "remote note id seems to be deleted");
|
||||||
|
return SYNC_ACTION_UPDATE_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate the note id now
|
||||||
|
if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) {
|
||||||
|
Log.w(TAG, "note id doesn't match");
|
||||||
|
return SYNC_ACTION_UPDATE_LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
|
||||||
|
// there is no local update
|
||||||
|
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
|
||||||
|
// no update both side
|
||||||
|
return SYNC_ACTION_NONE;
|
||||||
|
} else {
|
||||||
|
// apply remote to local
|
||||||
|
return SYNC_ACTION_UPDATE_LOCAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// validate gtask id
|
||||||
|
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
|
||||||
|
Log.e(TAG, "gtask id doesn't match");
|
||||||
|
return SYNC_ACTION_ERROR;
|
||||||
|
}
|
||||||
|
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
|
||||||
|
// local modification only
|
||||||
|
return SYNC_ACTION_UPDATE_REMOTE;
|
||||||
|
} else {
|
||||||
|
return SYNC_ACTION_UPDATE_CONFLICT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SYNC_ACTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWorthSaving() {
|
||||||
|
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)
|
||||||
|
|| (getNotes() != null && getNotes().trim().length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompleted(boolean completed) {
|
||||||
|
this.mCompleted = completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotes(String notes) {
|
||||||
|
this.mNotes = notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriorSibling(Task priorSibling) {
|
||||||
|
this.mPriorSibling = priorSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(TaskList parent) {
|
||||||
|
this.mParent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getCompleted() {
|
||||||
|
return this.mCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotes() {
|
||||||
|
return this.mNotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task getPriorSibling() {
|
||||||
|
return this.mPriorSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskList getParent() {
|
||||||
|
return this.mParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import net.micode.notes.data.Notes;
|
||||||
|
import net.micode.notes.data.Notes.NoteColumns;
|
||||||
|
import net.micode.notes.gtask.exception.ActionFailureException;
|
||||||
|
import net.micode.notes.tool.GTaskStringUtils;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
public class TaskList extends Node {
|
||||||
|
private static final String TAG = TaskList.class.getSimpleName();
|
||||||
|
|
||||||
|
private int mIndex;
|
||||||
|
|
||||||
|
private ArrayList<Task> mChildren;
|
||||||
|
|
||||||
|
public TaskList() {
|
||||||
|
super();
|
||||||
|
mChildren = new ArrayList<Task>();
|
||||||
|
mIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getCreateAction(int actionId) {
|
||||||
|
JSONObject js = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// action_type
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
|
||||||
|
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
|
||||||
|
|
||||||
|
// action_id
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
|
||||||
|
|
||||||
|
// index
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
|
||||||
|
|
||||||
|
// entity_delta
|
||||||
|
JSONObject entity = new JSONObject();
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
|
||||||
|
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new ActionFailureException("fail to generate tasklist-create jsonobject");
|
||||||
|
}
|
||||||
|
|
||||||
|
return js;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getUpdateAction(int actionId) {
|
||||||
|
JSONObject js = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// action_type
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
|
||||||
|
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
|
||||||
|
|
||||||
|
// action_id
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
|
||||||
|
|
||||||
|
// id
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
|
||||||
|
|
||||||
|
// entity_delta
|
||||||
|
JSONObject entity = new JSONObject();
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
|
||||||
|
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
|
||||||
|
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new ActionFailureException("fail to generate tasklist-update jsonobject");
|
||||||
|
}
|
||||||
|
|
||||||
|
return js;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentByRemoteJSON(JSONObject js) {
|
||||||
|
if (js != null) {
|
||||||
|
try {
|
||||||
|
// id
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
|
||||||
|
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
// last_modified
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
|
||||||
|
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
|
||||||
|
}
|
||||||
|
|
||||||
|
// name
|
||||||
|
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
|
||||||
|
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new ActionFailureException("fail to get tasklist content from jsonobject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentByLocalJSON(JSONObject js) {
|
||||||
|
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
|
||||||
|
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
|
||||||
|
|
||||||
|
if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
|
||||||
|
String name = folder.getString(NoteColumns.SNIPPET);
|
||||||
|
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name);
|
||||||
|
} else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
|
||||||
|
if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER)
|
||||||
|
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT);
|
||||||
|
else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER)
|
||||||
|
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX
|
||||||
|
+ GTaskStringUtils.FOLDER_CALL_NOTE);
|
||||||
|
else
|
||||||
|
Log.e(TAG, "invalid system folder");
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "error type");
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getLocalJSONFromContent() {
|
||||||
|
try {
|
||||||
|
JSONObject js = new JSONObject();
|
||||||
|
JSONObject folder = new JSONObject();
|
||||||
|
|
||||||
|
String folderName = getName();
|
||||||
|
if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX))
|
||||||
|
folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(),
|
||||||
|
folderName.length());
|
||||||
|
folder.put(NoteColumns.SNIPPET, folderName);
|
||||||
|
if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT)
|
||||||
|
|| folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE))
|
||||||
|
folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
|
||||||
|
else
|
||||||
|
folder.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
|
||||||
|
|
||||||
|
js.put(GTaskStringUtils.META_HEAD_NOTE, folder);
|
||||||
|
|
||||||
|
return js;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSyncAction(Cursor c) {
|
||||||
|
try {
|
||||||
|
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
|
||||||
|
// there is no local update
|
||||||
|
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
|
||||||
|
// no update both side
|
||||||
|
return SYNC_ACTION_NONE;
|
||||||
|
} else {
|
||||||
|
// apply remote to local
|
||||||
|
return SYNC_ACTION_UPDATE_LOCAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// validate gtask id
|
||||||
|
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
|
||||||
|
Log.e(TAG, "gtask id doesn't match");
|
||||||
|
return SYNC_ACTION_ERROR;
|
||||||
|
}
|
||||||
|
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
|
||||||
|
// local modification only
|
||||||
|
return SYNC_ACTION_UPDATE_REMOTE;
|
||||||
|
} else {
|
||||||
|
// for folder conflicts, just apply local modification
|
||||||
|
return SYNC_ACTION_UPDATE_REMOTE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SYNC_ACTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChildTaskCount() {
|
||||||
|
return mChildren.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addChildTask(Task task) {
|
||||||
|
boolean ret = false;
|
||||||
|
if (task != null && !mChildren.contains(task)) {
|
||||||
|
ret = mChildren.add(task);
|
||||||
|
if (ret) {
|
||||||
|
// need to set prior sibling and parent
|
||||||
|
task.setPriorSibling(mChildren.isEmpty() ? null : mChildren
|
||||||
|
.get(mChildren.size() - 1));
|
||||||
|
task.setParent(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addChildTask(Task task, int index) {
|
||||||
|
if (index < 0 || index > mChildren.size()) {
|
||||||
|
Log.e(TAG, "add child task: invalid index");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos = mChildren.indexOf(task);
|
||||||
|
if (task != null && pos == -1) {
|
||||||
|
mChildren.add(index, task);
|
||||||
|
|
||||||
|
// update the task list
|
||||||
|
Task preTask = null;
|
||||||
|
Task afterTask = null;
|
||||||
|
if (index != 0)
|
||||||
|
preTask = mChildren.get(index - 1);
|
||||||
|
if (index != mChildren.size() - 1)
|
||||||
|
afterTask = mChildren.get(index + 1);
|
||||||
|
|
||||||
|
task.setPriorSibling(preTask);
|
||||||
|
if (afterTask != null)
|
||||||
|
afterTask.setPriorSibling(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeChildTask(Task task) {
|
||||||
|
boolean ret = false;
|
||||||
|
int index = mChildren.indexOf(task);
|
||||||
|
if (index != -1) {
|
||||||
|
ret = mChildren.remove(task);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
// reset prior sibling and parent
|
||||||
|
task.setPriorSibling(null);
|
||||||
|
task.setParent(null);
|
||||||
|
|
||||||
|
// update the task list
|
||||||
|
if (index != mChildren.size()) {
|
||||||
|
mChildren.get(index).setPriorSibling(
|
||||||
|
index == 0 ? null : mChildren.get(index - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean moveChildTask(Task task, int index) {
|
||||||
|
|
||||||
|
if (index < 0 || index >= mChildren.size()) {
|
||||||
|
Log.e(TAG, "move child task: invalid index");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos = mChildren.indexOf(task);
|
||||||
|
if (pos == -1) {
|
||||||
|
Log.e(TAG, "move child task: the task should in the list");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos == index)
|
||||||
|
return true;
|
||||||
|
return (removeChildTask(task) && addChildTask(task, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task findChildTaskByGid(String gid) {
|
||||||
|
for (int i = 0; i < mChildren.size(); i++) {
|
||||||
|
Task t = mChildren.get(i);
|
||||||
|
if (t.getGid().equals(gid)) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChildTaskIndex(Task task) {
|
||||||
|
return mChildren.indexOf(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task getChildTaskByIndex(int index) {
|
||||||
|
if (index < 0 || index >= mChildren.size()) {
|
||||||
|
Log.e(TAG, "getTaskByIndex: invalid index");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return mChildren.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task getChilTaskByGid(String gid) {
|
||||||
|
for (Task task : mChildren) {
|
||||||
|
if (task.getGid().equals(gid))
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Task> getChildTaskList() {
|
||||||
|
return this.mChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(int index) {
|
||||||
|
this.mIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return this.mIndex;
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/src.iml" filepath="$PROJECT_DIR$/.idea/src.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/src.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/src.app.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/src.app.androidTest.iml" filepath="$PROJECT_DIR$/.idea/modules/app/src.app.androidTest.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/src.app.main.iml" filepath="$PROJECT_DIR$/.idea/modules/app/src.app.main.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/src.app.unitTest.iml" filepath="$PROJECT_DIR$/.idea/modules/app/src.app.unitTest.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module external.linked.project.id=":app:androidTest" external.linked.project.path="$MODULE_DIR$/../../../app" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.type="sourceSet" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="android" name="Android">
|
||||||
|
<configuration>
|
||||||
|
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||||
|
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||||
|
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||||
|
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||||
|
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/main/res;file://$MODULE_DIR$/../../../app/src/debug/res;file://$MODULE_DIR$/../../../app/build/generated/res/rs/debug;file://$MODULE_DIR$/../../../app/build/generated/res/resValues/debug" />
|
||||||
|
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/androidTest/res;file://$MODULE_DIR$/../../../app/src/androidTestDebug/res;file://$MODULE_DIR$/../../../app/build/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/../../../app/build/generated/res/resValues/androidTest/debug" />
|
||||||
|
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
|
<output url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debug/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debugUnitTest/classes" />
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/aidl_source_output_dir/debugAndroidTest/out" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debugAndroidTest/out" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/renderscript_source_output_dir/debugAndroidTest/out" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/res/resValues/androidTest/debug" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/res/rs/androidTest/debug" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/source/buildConfig/androidTest/debug" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/src/androidTest" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/src/androidTestDebug" />
|
||||||
|
<orderEntry type="jdk" jdkName="Android API 33, extension level 3 Platform" jdkType="Android SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="module" module-name="src.app.main" scope="TEST" />
|
||||||
|
</component>
|
||||||
|
<component name="TestModuleProperties" production-module="src.app.main" />
|
||||||
|
</module>
|
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$/../../../app" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="src" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="android-gradle" name="Android-Gradle">
|
||||||
|
<configuration>
|
||||||
|
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
||||||
|
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
|
||||||
|
<option name="LAST_KNOWN_AGP_VERSION" value="7.4.2" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
<facet type="android" name="Android">
|
||||||
|
<configuration>
|
||||||
|
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||||
|
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||||
|
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||||
|
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||||
|
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/main/res;file://$MODULE_DIR$/../../../app/src/debug/res;file://$MODULE_DIR$/../../../app/build/generated/res/rs/debug;file://$MODULE_DIR$/../../../app/build/generated/res/resValues/debug" />
|
||||||
|
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/androidTest/res;file://$MODULE_DIR$/../../../app/src/androidTestDebug/res;file://$MODULE_DIR$/../../../app/build/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/../../../app/build/generated/res/resValues/androidTest/debug" />
|
||||||
|
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
|
<output url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debug/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debugUnitTest/classes" />
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../../app/.gradle" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../../app/build" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="Android API 33, extension level 3 Platform" jdkType="Android SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module external.linked.project.id=":app:main" external.linked.project.path="$MODULE_DIR$/../../../app" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.type="sourceSet" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="android" name="Android">
|
||||||
|
<configuration>
|
||||||
|
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||||
|
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||||
|
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||||
|
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||||
|
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/main/res;file://$MODULE_DIR$/../../../app/src/debug/res;file://$MODULE_DIR$/../../../app/build/generated/res/rs/debug;file://$MODULE_DIR$/../../../app/build/generated/res/resValues/debug" />
|
||||||
|
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/androidTest/res;file://$MODULE_DIR$/../../../app/src/androidTestDebug/res;file://$MODULE_DIR$/../../../app/build/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/../../../app/build/generated/res/resValues/androidTest/debug" />
|
||||||
|
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
|
<output url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debug/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debugUnitTest/classes" />
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/aidl_source_output_dir/debug/out" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debug/out">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debug/out" isTestSource="false" generated="true" />
|
||||||
|
</content>
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/renderscript_source_output_dir/debug/out" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/res/resValues/debug">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/res/resValues/debug" type="java-resource" />
|
||||||
|
</content>
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/res/rs/debug" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/source/buildConfig/debug">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||||
|
</content>
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/src/debug" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/src/main">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../../app/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../../app/src/main/res" type="java-resource" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="Android API 33, extension level 3 Platform" jdkType="Android SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module external.linked.project.id=":app:unitTest" external.linked.project.path="$MODULE_DIR$/../../../app" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.type="sourceSet" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="android" name="Android">
|
||||||
|
<configuration>
|
||||||
|
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||||
|
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||||
|
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||||
|
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||||
|
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/main/res;file://$MODULE_DIR$/../../../app/src/debug/res;file://$MODULE_DIR$/../../../app/build/generated/res/rs/debug;file://$MODULE_DIR$/../../../app/build/generated/res/resValues/debug" />
|
||||||
|
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/androidTest/res;file://$MODULE_DIR$/../../../app/src/androidTestDebug/res;file://$MODULE_DIR$/../../../app/build/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/../../../app/build/generated/res/resValues/androidTest/debug" />
|
||||||
|
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
|
<output url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debug/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debugUnitTest/classes" />
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debugUnitTest/out" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/src/test" />
|
||||||
|
<content url="file://$MODULE_DIR$/../../../app/src/testDebug" />
|
||||||
|
<orderEntry type="jdk" jdkName="Android API 33, extension level 3 Platform" jdkType="Android SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="module" module-name="src.app.main" scope="TEST" />
|
||||||
|
</component>
|
||||||
|
<component name="TestModuleProperties" production-module="src.app.main" />
|
||||||
|
</module>
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module external.linked.project.id="src" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"artifactType": {
|
||||||
|
"type": "APK",
|
||||||
|
"kind": "Directory"
|
||||||
|
},
|
||||||
|
"applicationId": "net.micode.notes",
|
||||||
|
"variantName": "debug",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "SINGLE",
|
||||||
|
"filters": [],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 1,
|
||||||
|
"versionName": "0.1",
|
||||||
|
"outputFile": "app-debug.apk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"elementType": "File"
|
||||||
|
}
|
Loading…
Reference in new issue