() {
-
- @Override
- protected Integer doInBackground(Void... unused) {
- return backup.exportToText();
- }
-
- @Override
- protected void onPostExecute(Integer result) {
- if (result == BackupUtils.STATE_SD_CARD_UNMOUONTED) {
- AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- builder.setTitle(NotesListActivity.this
- .getString(R.string.failed_sdcard_export));
- builder.setMessage(NotesListActivity.this
- .getString(R.string.error_sdcard_unmounted));
- builder.setPositiveButton(android.R.string.ok, null);
- builder.show();
- } else if (result == BackupUtils.STATE_SUCCESS) {
- AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- builder.setTitle(NotesListActivity.this
- .getString(R.string.success_sdcard_export));
- builder.setMessage(NotesListActivity.this.getString(
- R.string.format_exported_file_location, backup
- .getExportedTextFileName(), backup.getExportedTextFileDir()));
- builder.setPositiveButton(android.R.string.ok, null);
- builder.show();
- } else if (result == BackupUtils.STATE_SYSTEM_ERROR) {
- AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- builder.setTitle(NotesListActivity.this
- .getString(R.string.failed_sdcard_export));
- builder.setMessage(NotesListActivity.this
- .getString(R.string.error_sdcard_export));
- builder.setPositiveButton(android.R.string.ok, null);
- builder.show();
- }
- }
-
- }.execute();
- }
-
-
- private boolean isSyncMode() {
- return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
- }
-
- private void startPreferenceActivity() {
- Activity from = getParent() != null ? getParent() : this;
- Intent intent = new Intent(from, NotesPreferenceActivity.class);
- from.startActivityIfNeeded(intent, -1);
- }
-
- /**
- * @Package: net.micode.notes.ui
- * @ClassName: NotesListActivity
- * @Description: 响应了按钮的点击
- * @Author: YangYizhe
- * @CreateDate: 12/21/2023 8:09 AM
- * @Version: 1.0
- */
- private class OnListItemClickListener implements OnItemClickListener {
-
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- if (view instanceof NotesListItem) {
- NoteItemData item = ((NotesListItem) view).getItemData();
- if (mNotesListAdapter.isInChoiceMode()) {
- if (item.getType() == Notes.TYPE_NOTE) {
- position = position - mNotesListView.getHeaderViewsCount();
- mModeCallBack.onItemCheckedStateChanged(null, position, id,
- !mNotesListAdapter.isSelectedItem(position));
- }
- return;
- }
-
- switch (mState) {
- case NOTE_LIST:
- if (item.getType() == Notes.TYPE_FOLDER
- || item.getType() == Notes.TYPE_SYSTEM) {
- openFolder(item);
- } else if (item.getType() == Notes.TYPE_NOTE) {
- openNode(item);
- } else {
- Log.e(TAG, "Wrong note type in NOTE_LIST");
- }
- break;
- case SUB_FOLDER:
- case CALL_RECORD_FOLDER:
- if (item.getType() == Notes.TYPE_NOTE) {
- openNode(item);
- } else {
- Log.e(TAG, "Wrong note type in SUB_FOLDER");
- }
- break;
- default:
- break;
- }
- }
- }
-
- }
-
- /**
- * 查询目标文件
- */
- private void startQueryDestinationFolders() {
- String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?";
- selection = (mState == ListEditState.NOTE_LIST) ? selection:
- "(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")";
-
- mBackgroundQueryHandler.startQuery(FOLDER_LIST_QUERY_TOKEN,
- null,
- Notes.CONTENT_NOTE_URI,
- FoldersListAdapter.PROJECTION,
- selection,
- new String[] {
- String.valueOf(Notes.TYPE_FOLDER),
- String.valueOf(Notes.ID_TRASH_FOLER),
- String.valueOf(mCurrentFolderId)
- },
- NoteColumns.MODIFIED_DATE + " DESC");
- }
-
- /**
- * @method onItemLongClick
- * @description
- * 长按某一项时进行的操作
- * 如果长按的是便签,则通过ActionMode菜单实现;如果长按的是文件夹,则通过ContextMenu菜单实现;
- * @date: 12/21/2023 8:10 AM
- * @author: YangYizhe
- * @param
- * @return
- */
- public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
- if (view instanceof NotesListItem) {
- mFocusNoteDataItem = ((NotesListItem) view).getItemData();
- if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) {
- if (mNotesListView.startActionMode(mModeCallBack) != null) {
- mModeCallBack.onItemCheckedStateChanged(null, position, id, true);
- mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- } else {
- Log.e(TAG, "startActionMode fails");
- }
- } else if (mFocusNoteDataItem.getType() == Notes.TYPE_FOLDER) {
- mNotesListView.setOnCreateContextMenuListener(mFolderOnCreateContextMenuListener);
- }
- }
- return false;
- }
-}
\ No newline at end of file
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java
deleted file mode 100644
index d32a37b..0000000
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java
+++ /dev/null
@@ -1,123 +0,0 @@
-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;
-
-
-/**
- * @Package: net.micode.notes.ui
- * @ClassName: NotesListItem
- * @Description:
- * @Author: YangYizhe
- * @CreateDate: 12/23/2023 11:35 PM
- * @Version: 1.0
- */
-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); //super()它的主要作用是调整调用父类构造函数的顺序
- inflate(context, R.layout.note_item, this);//Inflate可用于将一个xml中定义的布局控件找出来,这里的xml是r。layout
- //findViewById用于从contentView中查找指定ID的View,转换出来的形式根据需要而定;
- 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);
- }
- ///根据data的属性对各个控件的属性的控制,主要是可见性Visibility,内容setText,格式setTextAppearance
- 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;
- ///设置控件属性,一共三种情况,由data的id和父id是否与保存到文件夹的id一致来决定
- if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
- mCallName.setVisibility(View.GONE);
- mAlert.setVisibility(View.VISIBLE);
- //设置该textview的style
- mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem);
- //settext为设置内容
- 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);
- ///设置title格式
- 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);
- }
- }
- }
- ///设置内容,获取相关时间,从data里编辑的日期中获取
- mTime. setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate()));
-
- setBackground(data);
- }
- //根据data的文件属性来设置背景
- private void setBackground(NoteItemData data) {
- int id = data.getBgColorId();
- //,若是note型文件,则4种情况,对于4种不同情况的背景来源
- 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 {
- //若不是note直接调用文件夹的背景来源
- setBackgroundResource(NoteItemBgResources.getFolderBgRes());
- }
- }
- public NoteItemData getItemData() {
- return mItemData;
- }
-}
\ No newline at end of file
diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java
deleted file mode 100644
index e4109c6..0000000
--- a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java
+++ /dev/null
@@ -1,492 +0,0 @@
-package net.micode.notes.ui;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.ActionBar;
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceCategory;
-import android.text.TextUtils;
-import android.text.format.DateFormat;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import net.micode.notes.R;
-import net.micode.notes.data.Notes;
-import net.micode.notes.data.Notes.NoteColumns;
-import net.micode.notes.gtask.remote.GTaskSyncService;
-
-/**
- * @Package: net.micode.notes.ui
- * @ClassName: NotesPreferenceActivity
- * @Description:
- * NotesPreferenceActivity,在小米便签中主要实现的是对背景颜色和字体大小的数据储存。
- * 继承了PreferenceActivity主要功能为对系统信息和配置进行自动保存的Activity
- * @Author: YangYizhe
- * @CreateDate: 12/23/2023 11:42 PM
- * @Version: 1.0
- */
-public class NotesPreferenceActivity extends PreferenceActivity {
- public static final String PREFERENCE_NAME = "notes_preferences";//优先名
- public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name";//同步账号
- public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time";//同步时间
- public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear";
- private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key";//同步密码
- private static final String AUTHORITIES_FILTER_KEY = "authorities";
- private PreferenceCategory mAccountCategory;//账户分组
- private GTaskReceiver mReceiver;//同步任务接收器
- private Account[] mOriAccounts;//账户
- private boolean mHasAddedAccount;//账户的hash标记
-
- @Override
- /**
- * @method onCreate
- * @description 创建一个activity,在函数里要完成所有的正常静态设置
- * @date: 12/23/2023 11:43 PM
- * @author: YangYizhe
- * @param [icicle]
- * @return void
- */
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- /* using the app icon for navigation */
- getActionBar().setDisplayHomeAsUpEnabled(true);//给左上角图标的左边加上一个返回的图标
- addPreferencesFromResource(R.xml.preferences);//添加xml来源并显示 xml
- mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);//根据同步账户关键码来初始化分组
- mReceiver = new GTaskReceiver();
- IntentFilter filter = new IntentFilter();
- filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME);
- registerReceiver(mReceiver, filter);//初始化同步组件
- mOriAccounts = null;
- View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);//获取listvivew,ListView的作用:用于列出所有选择
- getListView().addHeaderView(header, null, true);//在listview组件上方添加其他组件
- }
-
- @Override
- /**
- * @method onResume
- * @description activity交互功能的实现,用于接受用户的输入
- * @date: 12/23/2023 11:44 PM
- * @author: YangYizhe
- * @return void
- */
- protected void onResume() {
- super.onResume();
-
- // need to set sync account automatically if user has added a new
- // account
- if (mHasAddedAccount) {
- //若用户新加了账户则自动设置同步账户
- Account[] accounts = getGoogleAccounts();//获取google同步账户
- if (mOriAccounts != null && accounts.length > mOriAccounts.length) {
- //若原账户不为空且当前账户有增加
- for (Account accountNew : accounts) {
- boolean found = false;
- for (Account accountOld : mOriAccounts) {
- if (TextUtils.equals(accountOld.name, accountNew.name)) {
- //更新账户
- found = true;
- break;
- }
- }
- if (!found) {
- setSyncAccount(accountNew.name);
- //若是没有找到旧的账户,那么同步账号中就只添加新账户
- break;
- }
- }
- }
- }
-
- refreshUI();//刷新标签界面
- }
-
- @Override
- protected void onDestroy() {
- if (mReceiver != null) {
- unregisterReceiver(mReceiver);//注销接收器
- }
- super.onDestroy();//执行父类的销毁动作
- }
-
- /**
- * @method loadAccountPreference
- * @description 重新设置账户信息
- * @date: 12/23/2023 11:45 PM
- * @author: YangYizhe
- * @param
- * @return
- */
- private void loadAccountPreference() {
- mAccountCategory.removeAll();//销毁所有的分组
- Preference accountPref = new Preference(this);//建立首选项
- final String defaultAccount = getSyncAccountName(this);
- accountPref.setTitle(getString(R.string.preferences_account_title));
- accountPref.setSummary(getString(R.string.preferences_account_summary));//设置首选项的大标题和小标题
- accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- //建立监听器
- if (!GTaskSyncService.isSyncing()) {
- if (TextUtils.isEmpty(defaultAccount)) {
- // the first time to set account
- //若是第一次建立账户显示选择账户提示对话框
- showSelectAccountAlertDialog();
- } else {
- // if the account has already been set, we need to promp
- // user about the risk
- //若是已经建立则显示修改对话框并进行修改操作
- showChangeAccountConfirmAlertDialog();
- }
- } else {
- //若在没有同步的情况下,则在toast中显示不能修改
- Toast.makeText(NotesPreferenceActivity.this,
- R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT)
- .show();
- }
- return true;
- }
- });
- mAccountCategory.addPreference(accountPref);//根据新建首选项编辑新的账户分组
- }
- /**
- * @method loadSyncButton
- * @description 设置按键的状态和最后同步的时间
- * @date: 12/23/2023 11:46 PM
- * @author: YangYizhe
- * @param
- * @return
- */
- private void loadSyncButton() {
- Button syncButton = (Button) findViewById(R.id.preference_sync_button);
- TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
- //获取同步按钮控件和最终同步时间的的窗口
- // set button state
- //设置按钮的状态
- if (GTaskSyncService.isSyncing()) {
- //若是在同步状态下
- syncButton.setText(getString(R.string.preferences_button_sync_cancel));
- syncButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- GTaskSyncService.cancelSync(NotesPreferenceActivity.this);
- }
- });//设置按钮显示的文本为“取消同步”以及监听器
- } else {
- syncButton.setText(getString(R.string.preferences_button_sync_immediately));
- syncButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- GTaskSyncService.startSync(NotesPreferenceActivity.this);
- }
- });//若是不同步则设置按钮显示的文本为“立即同步”以及对应监听器
- }
- syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this)));//设置按键可用还是不可用
- // set last sync time
- // 设置最终同步时间
- if (GTaskSyncService.isSyncing()) {
- //若是在同步的情况下
- lastSyncTimeView.setText(GTaskSyncService.getProgressString());
- lastSyncTimeView.setVisibility(View.VISIBLE);
- // 根据当前同步服务器设置时间显示框的文本以及可见性
- } else {
- //若是非同步情况
- long lastSyncTime = getLastSyncTime(this);
- if (lastSyncTime != 0) {
- lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time,
- DateFormat.format(getString(R.string.preferences_last_sync_time_format),
- lastSyncTime)));
- lastSyncTimeView.setVisibility(View.VISIBLE);
- //则根据最后同步时间的信息来编辑时间显示框的文本内容和可见性
- } else {
- //若时间为空直接设置为不可见状态
- lastSyncTimeView.setVisibility(View.GONE);
- }
- }
- }
- /**
- * @method refreshUI
- * @description
- * 刷新标签界面
- * 调用上文设置账号和设置按键两个函数来实现
- * @date: 12/23/2023 11:46 PM
- * @author: YangYizhe
- */
- private void refreshUI() {
- loadAccountPreference();
- loadSyncButton();
- }
- /**
- * @method showSelectAccountAlertDialog
- * @description 显示账户选择的对话框并进行账户的设置
- * @date: 12/23/2023 11:47 PM
- * @author: YangYizhe
- * @param
- * @return
- */
- private void showSelectAccountAlertDialog() {
- AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);//创建一个新的对话框
-
- View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
- TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
- titleTextView.setText(getString(R.string.preferences_dialog_select_account_title));
- TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
- subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));//设置标题以及子标题的内容
- dialogBuilder.setCustomTitle(titleView);
- dialogBuilder.setPositiveButton(null, null);//设置对话框的自定义标题,建立一个YES的按钮
- Account[] accounts = getGoogleAccounts();
- String defAccount = getSyncAccountName(this);//获取同步账户信息
- mOriAccounts = accounts;
- mHasAddedAccount = false;
-
- if (accounts.length > 0) {
- //若账户不为空
- CharSequence[] items = new CharSequence[accounts.length];
- final CharSequence[] itemMapping = items;
- int checkedItem = -1;
- int index = 0;
- for (Account account : accounts) {
- if (TextUtils.equals(account.name, defAccount)) {
- checkedItem = index;//在账户列表中查询到所需账户
- }
- items[index++] = account.name;
- }
- dialogBuilder.setSingleChoiceItems(items, checkedItem,
- //在对话框建立一个单选的复选框
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- setSyncAccount(itemMapping[which].toString());
- dialog.dismiss();//取消对话框
- refreshUI();
- }
- });//建立对话框网络版的监听器
- }
-
- View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null);
- dialogBuilder.setView(addAccountView);//给新加账户对话框设置自定义样式
-
- final AlertDialog dialog = dialogBuilder.show();//显示对话框
- addAccountView.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- mHasAddedAccount = true;
- //将新加账户的hash置true
- Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
- //建立网络建立组件
- intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {
- "gmail-ls"
- });
- startActivityForResult(intent, -1);
- //跳回上一个选项
- dialog.dismiss();
- }
- });//建立新加账户对话框的监听器
- }
- /**
- * @method showChangeAccountConfirmAlertDialog
- * @description 显示账户选择对话框和相关账户操作
- * @date: 12/23/2023 11:48 PM
- * @author: YangYizhe
- */
- private void showChangeAccountConfirmAlertDialog() {
- AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);//创建一个新的对话框
- View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null);
- TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title);
- titleTextView.setText(getString(R.string.preferences_dialog_change_account_title,
- getSyncAccountName(this)));
- TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle);
- subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg));//根据同步修改的账户信息设置标题以及子标题的内容
- dialogBuilder.setCustomTitle(titleView);//设置对话框的自定义标题
- CharSequence[] menuItemArray = new CharSequence[] {
- getString(R.string.preferences_menu_change_account),
- getString(R.string.preferences_menu_remove_account),
- getString(R.string.preferences_menu_cancel)
- };
- dialogBuilder.setItems(menuItemArray, new DialogInterface.OnClickListener() {
- //设置对话框要显示的一个list,用于显示几个命令时,即change,remove,cancel
- public void onClick(DialogInterface dialog, int which) {
- //按键功能,由which来决定
- if (which == 0) {
- //进入账户选择对话框
- showSelectAccountAlertDialog();
- } else if (which == 1) {
- //删除账户并且跟新便签界面
- removeSyncAccount();
- refreshUI();
- }
- }
- });
- dialogBuilder.show();//显示对话框
- }
-
- /**
- * @method getGoogleAccounts
- * @description
- * 获取谷歌账户
- * 通过账户管理器直接获取
- * @date: 12/23/2023 11:49 PM
- * @author: YangYizhe
- */
- private Account[] getGoogleAccounts() {
- AccountManager accountManager = AccountManager.get(this);
- return accountManager.getAccountsByType("com.google");
- }
-
- /**
- * @method setSyncAccount
- * @description 设置同步账户
- * @date: 12/23/2023 11:49 PM
- * @author: YangYizhe
- * @param account
- */
- private void setSyncAccount(String account) {
- if (!getSyncAccountName(this).equals(account)) {
- //假如该账号不在同步账号列表中
- SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = settings.edit();//编辑共享的首选项
- if (account != null) {
- editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account);
- } else {
- editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
- }//将该账号加入到首选项中
-
- editor.commit();//提交修改的数据
- setLastSyncTime(this, 0);//将最后同步时间清零
-
- // clean up local gtask related info
- new Thread(new Runnable() {
- public void run() {
- ContentValues values = new ContentValues();
- values.put(NoteColumns.GTASK_ID, "");
- values.put(NoteColumns.SYNC_ID, 0);
- getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
- }
- }).start();
- //重置当地同步任务的信息
-
- Toast.makeText(NotesPreferenceActivity.this,
- getString(R.string.preferences_toast_success_set_accout, account),
- Toast.LENGTH_SHORT).show();
- //将toast的文本信息置为“设置账户成功”并显示出来
- }
- }
- /**
- * @method removeSyncAccount
- * @description 删除同步账户
- * @date: 12/23/2023 11:49 PM
- * @author: YangYizhe
- */
- private void removeSyncAccount() {
- SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = settings.edit();//设置共享首选项
-
- if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) {
- editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);//假如当前首选项中有账户就删除
- }
- if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) {
- editor.remove(PREFERENCE_LAST_SYNC_TIME);//删除当前首选项中有账户时间
- }
- editor.commit();//提交更新后的数据
-
- // clean up local gtask related info
- new Thread(new Runnable() {
- public void run() {
- ContentValues values = new ContentValues();
- values.put(NoteColumns.GTASK_ID, "");
- values.put(NoteColumns.SYNC_ID, 0);
- getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null);
- }
- }).start();
- //重置当地同步任务的信息
- }
- /**
- * @method getSyncAccountName
- * @description
- * 获取同步账户名称
- * 通过共享的首选项里的信息直接获取
- * @date: 12/23/2023 11:50 PM
- * @author: YangYizhe
- * @param context
- */
- public static String getSyncAccountName(Context context) {
- SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
- Context.MODE_PRIVATE);
- return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, "");
- }
- /**
- * @method setLastSyncTime
- * @description 设置最终同步的时间
- * @date: 12/23/2023 11:50 PM
- * @author: YangYizhe
- * @param
- * @return
- */
- public static void setLastSyncTime(Context context, long time) {
- SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
- Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = settings.edit();// 从共享首选项中找到相关账户并获取其编辑器
- editor.putLong(PREFERENCE_LAST_SYNC_TIME, time);
- editor.commit();//编辑最终同步时间并提交更新
- }
- /**
- * @method getLastSyncTime
- * @description
- * 获取最终同步时间
- * 通过共享的首选项里的信息直接获取
- * @date: 12/23/2023 11:51 PM
- * @author: YangYizhe
- * @param context
- */
- public static long getLastSyncTime(Context context) {
- SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME,
- Context.MODE_PRIVATE);
- return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0);
- }
-
- private class GTaskReceiver extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- refreshUI();
- if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) {
- //获取随广播而来的Intent中的同步服务的数据
- TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview);
- syncStatus.setText(intent
- .getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));//通过获取的数据在设置系统的状态
- }
-
- }
- }
- /**
- * @method onOptionsItemSelected
- * @description 处理菜单的选项
- * @date: 12/23/2023 11:52 PM
- * @author: YangYizhe
- * @param item
- */
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- //根据选项的id选择,这里只有一个主页
- case android.R.id.home:
- Intent intent = new Intent(this, NotesListActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
- //在主页情况下在创建连接组件intent,发出清空的信号并开始一个相应的activity
- default:
- return false;
- }
- }
-}
-
\ No newline at end of file
diff --git a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java
deleted file mode 100644
index d8eb50b..0000000
--- a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.widget;
-import android.app.PendingIntent;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.util.Log;
-import android.widget.RemoteViews;
-
-import net.micode.notes.R;
-import net.micode.notes.data.Notes;
-import net.micode.notes.data.Notes.NoteColumns;
-import net.micode.notes.tool.ResourceParser;
-import net.micode.notes.ui.NoteEditActivity;
-import net.micode.notes.ui.NotesListActivity;
-/**
- * @Package: net.micode.notes.widget
- * @ClassName: NoteWidgetProvider
- * @Description: 这个抽象类用作MiNote应用程序中笔记小部件的基础。它提供了在主屏幕上更新和管理笔记小部件的功能。
- * @Author: YangYizhe
- * @CreateDate: 12/23/2023 11:53 PM
- * @Version: 1.0
- */
-public abstract class NoteWidgetProvider extends AppWidgetProvider {
- public static final String [] PROJECTION = new String [] {
- NoteColumns.ID,
- NoteColumns.BG_COLOR_ID,
- NoteColumns.SNIPPET
- };
-
- public static final int COLUMN_ID = 0;
- public static final int COLUMN_BG_COLOR_ID = 1;
- public static final int COLUMN_SNIPPET = 2;
-
- private static final String TAG = "NoteWidgetProvider";
-
- @Override
- public void onDeleted(Context context, int[] appWidgetIds) {
- ContentValues values = new ContentValues();
- values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
- for (int i = 0; i < appWidgetIds.length; i++) {
- context.getContentResolver().update(Notes.CONTENT_NOTE_URI,
- values,
- NoteColumns.WIDGET_ID + "=?",
- new String[] { String.valueOf(appWidgetIds[i])});
- }
- }
-
- private Cursor getNoteWidgetInfo(Context context, int widgetId) {
- return context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
- PROJECTION,
- NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?",
- new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) },
- null);
- }
-
- protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
- update(context, appWidgetManager, appWidgetIds, false);
- }
-
- private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
- boolean privacyMode) {
- for (int i = 0; i < appWidgetIds.length; i++) {
- if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {
- int bgId = ResourceParser.getDefaultBgId(context);
- String snippet = "";
- Intent intent = new Intent(context, NoteEditActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
- intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]);
- intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());
-
- Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]);
- if (c != null && c.moveToFirst()) {
- if (c.getCount() > 1) {
- Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]);
- c.close();
- return;
- }
- snippet = c.getString(COLUMN_SNIPPET);
- bgId = c.getInt(COLUMN_BG_COLOR_ID);
- intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID));
- intent.setAction(Intent.ACTION_VIEW);
- } else {
- snippet = context.getResources().getString(R.string.widget_havenot_content);
- intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
- }
-
- if (c != null) {
- c.close();
- }
-
- RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId());
- rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId));
- intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId);
- /**
- * Generate the pending intent to start host for the widget
- */
- PendingIntent pendingIntent = null;
- if (privacyMode) {
- rv.setTextViewText(R.id.widget_text,
- context.getString(R.string.widget_under_visit_mode));
- pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent(
- context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
- } else {
- rv.setTextViewText(R.id.widget_text, snippet);
- pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- }
-
- rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
- appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
- }
- }
- }
-
- protected abstract int getBgResourceId(int bgId);
-
- protected abstract int getLayoutId();
-
- protected abstract int getWidgetType();
-}
diff --git a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java
deleted file mode 100644
index f3d5f1e..0000000
--- a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.widget;
-
-import android.appwidget.AppWidgetManager;
-import android.content.Context;
-
-import net.micode.notes.R;
-import net.micode.notes.data.Notes;
-import net.micode.notes.tool.ResourceParser;
-
-/**
- * @Package: net.micode.notes.widget
- * @ClassName: NoteWidgetProvider_2x
- * @Description:
- * 这个类是NoteWidgetProvider的一个具体实现,用于实现2x大小的笔记小部件。
- * 它继承自NoteWidgetProvider,并提供特定于2x小部件的布局ID、背景资源和小部件类型。
- * @Author: YangYizhe
- * @CreateDate: 12/23/2023 11:55 PM
- * @Version: 1.0
- */
-public class NoteWidgetProvider_2x extends NoteWidgetProvider {
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
- super.update(context, appWidgetManager, appWidgetIds);
- }
-
- @Override
- protected int getLayoutId() {
- return R.layout.widget_2x;
- }
-
- @Override
- protected int getBgResourceId(int bgId) {
- return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId);
- }
-
- @Override
- protected int getWidgetType() {
- return Notes.TYPE_WIDGET_2X;
- }
-}
diff --git a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java
deleted file mode 100644
index 0c3ae50..0000000
--- a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.widget;
-
-import android.appwidget.AppWidgetManager;
-import android.content.Context;
-
-import net.micode.notes.R;
-import net.micode.notes.data.Notes;
-import net.micode.notes.tool.ResourceParser;
-
-/**
- * @Package: net.micode.notes.widget
- * @ClassName: NoteWidgetProvider_4x
- * @Description:
- * 这个类是NoteWidgetProvider的一个具体实现,用于实现4x大小的笔记小部件。
- * 它继承自NoteWidgetProvider,并提供特定于4x小部件的布局ID、背景资源和小部件类型。
- * @Author: YangYizhe
- * @CreateDate: 12/23/2023 11:56 PM
- * @Version: 1.0
- */
-public class NoteWidgetProvider_4x extends NoteWidgetProvider {
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
- super.update(context, appWidgetManager, appWidgetIds);
- }
-
- protected int getLayoutId() {
- return R.layout.widget_4x;
- }
-
- @Override
- protected int getBgResourceId(int bgId) {
- return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId);
- }
-
- @Override
- protected int getWidgetType() {
- return Notes.TYPE_WIDGET_4X;
- }
-}
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index aebc482..952d7c5 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -1,57 +1,32 @@
-
-
-
-
-
-
+ android:versionName="0.1">
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
+
+
+
-
-
-
+ android:icon="@drawable/icon_app_1"
+ android:label="@string/app_name">
-
+
+ android:windowSoftInputMode="adjustPan">
-
-
-
-
-
-
+
+ android:theme="@style/NoteTheme">
-
+
+
-
-
-
+
+
+
-
+
+
-
+
-
+
+
-
+
-
-
-
+
-
-
+ android:multiprocess="true" />
+ android:label="@string/app_widget2x2">
-
+
-
+
+ android:label="@string/app_widget4x4">
-
+
-
+
-
-
-
-
+
+
-
-
-
+
-
-
-
+ android:name=".ui.AlarmReceiver"
+ android:process=":remote">
-
-
-
+ android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
-
-
-
+ android:theme="@android:style/Theme.Holo.Light">
-
-
-
+ android:name=".gtask.remote.GTaskSyncService"
+ android:exported="false">
-
+
+
\ No newline at end of file
diff --git a/src/main/java/net/micode/notes/data/Notes.java b/src/main/java/net/micode/notes/data/Notes.java
index aba2dbb..8762500 100644
--- a/src/main/java/net/micode/notes/data/Notes.java
+++ b/src/main/java/net/micode/notes/data/Notes.java
@@ -17,11 +17,17 @@
package net.micode.notes.data;
import android.net.Uri;
-//Notes类就定义了很多常量,是小米便签的数据库
+/**
+ * @Package: net.micode.notes.data
+ * @ClassName: Notes
+ * @Description:
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/21 19:32
+ * @Version: 1.0
+ */
public class Notes {
public static final String AUTHORITY = "micode_notes";
public static final String TAG = "Notes";
- //三个type
public static final int TYPE_NOTE = 0;
public static final int TYPE_FOLDER = 1;
public static final int TYPE_SYSTEM = 2;
@@ -32,7 +38,6 @@ public class Notes {
* {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder
* {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records
*/
- //不同种类的文件夹
public static final int ID_ROOT_FOLDER = 0;
public static final int ID_TEMPARAY_FOLDER = -1;
public static final int ID_CALL_RECORD_FOLDER = -2;
@@ -48,12 +53,12 @@ public class Notes {
public static final int TYPE_WIDGET_INVALIDE = -1;
public static final int TYPE_WIDGET_2X = 0;
public static final int TYPE_WIDGET_4X = 1;
- //数据常量 包括普通note和call_note
+
public static class DataConstants {
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE;
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE;
}
- //两个指针,一个找便签和文件夹,一个用来找数据
+
/**
* Uri to query all notes and folders
*/
@@ -62,201 +67,72 @@ public class Notes {
/**
* Uri to query data
*/
-
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
- //Notecolumns类,用于创建数据库的表头
+
public interface NoteColumns {
- //具体每一项都给了英文注释
- /**
- * The unique ID for a row
- * Type: INTEGER (long)
- */
+
public static final String ID = "_id";
- /**
- * The parent's id for note or folder
- * Type: INTEGER (long)
- */
public static final String PARENT_ID = "parent_id";
- /**
- * Created data for note or folder
- * Type: INTEGER (long)
- */
public static final String CREATED_DATE = "created_date";
- /**
- * Latest modified date
- * Type: INTEGER (long)
- */
public static final String MODIFIED_DATE = "modified_date";
-
- /**
- * Alert date
- * Type: INTEGER (long)
- */
public static final String ALERTED_DATE = "alert_date";
- /**
- * Folder's name or text content of note
- * Type: TEXT
- */
public static final String SNIPPET = "snippet";
- /**
- * Note's widget id
- * Type: INTEGER (long)
- */
public static final String WIDGET_ID = "widget_id";
- /**
- * Note's widget type
- * Type: INTEGER (long)
- */
public static final String WIDGET_TYPE = "widget_type";
- /**
- * Note's background color's id
- * Type: INTEGER (long)
- */
public static final String BG_COLOR_ID = "bg_color_id";
- /**
- * For text note, it doesn't has attachment, for multi-media
- * note, it has at least one attachment
- * Type: INTEGER
- */
public static final String HAS_ATTACHMENT = "has_attachment";
- /**
- * Folder's count of notes
- * Type: INTEGER (long)
- */
public static final String NOTES_COUNT = "notes_count";
- /**
- * The file type: folder or note
- * Type: INTEGER
- */
public static final String TYPE = "type";
- /**
- * The last sync id
- * Type: INTEGER (long)
- */
public static final String SYNC_ID = "sync_id";
- /**
- * Sign to indicate local modified or not
- * Type: INTEGER
- */
public static final String LOCAL_MODIFIED = "local_modified";
- /**
- * Original parent id before moving into temporary folder
- * Type : INTEGER
- */
public static final String ORIGIN_PARENT_ID = "origin_parent_id";
- /**
- * The gtask id
- * Type : TEXT
- */
public static final String GTASK_ID = "gtask_id";
- /**
- * The version code
- * Type : INTEGER (long)
- */
public static final String VERSION = "version";
+ }
- public static final String PASSWORD = "password";
-
- public static final String IMPORTANCE = "importance";
- }//便签的各种属性
- /*
- * 便签数据在数据库中的表头
- */
public interface DataColumns {
- /**
- * The unique ID for a row
- * Type: INTEGER (long)
- */
+
public static final String ID = "_id";
- /**
- * The MIME type of the item represented by this row.
- * Type: Text
- */
public static final String MIME_TYPE = "mime_type";
- /**
- * The reference id to note that this data belongs to
- * Type: INTEGER (long)
- */
public static final String NOTE_ID = "note_id";
- /**
- * Created data for note or folder
- * Type: INTEGER (long)
- */
public static final String CREATED_DATE = "created_date";
- /**
- * Latest modified date
- * Type: INTEGER (long)
- */
public static final String MODIFIED_DATE = "modified_date";
- /**
- * Data's content
- * Type: TEXT
- */
public static final String CONTENT = "content";
-
- /**
- * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
- * integer data type
- * Type: INTEGER
- */
public static final String DATA1 = "data1";
- /**
- * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
- * integer data type
- * Type: INTEGER
- */
public static final String DATA2 = "data2";
- /**
- * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
- * TEXT data type
- * Type: TEXT
- */
public static final String DATA3 = "data3";
- /**
- * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
- * TEXT data type
- * Type: TEXT
- */
public static final String DATA4 = "data4";
- /**
- * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
- * TEXT data type
- * Type: TEXT
- */
public static final String DATA5 = "data5";
- }//一个便签内部各种数据类型
+ }
public static final class TextNote implements DataColumns {
- /**
- * Mode to indicate the text in check list mode or not
- * Type: Integer 1:check list mode 0: normal mode
- */
+
public static final String MODE = DATA1;
public static final int MODE_CHECK_LIST = 1;
@@ -266,19 +142,12 @@ public class Notes {
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");
- }//一种是文本textnote
+ }
public static final class CallNote implements DataColumns {
- /**
- * Call date for this record
- * Type: INTEGER (long)
- */
+
public static final String CALL_DATE = DATA1;
- /**
- * Phone number for this record
- * Type: TEXT
- */
public static final String PHONE_NUMBER = DATA3;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";
@@ -286,5 +155,5 @@ public class Notes {
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");
- }//另一种是通话类型的callnote
+ }
}
diff --git a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
index bedbf65..1f05bbf 100644
--- a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
+++ b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
@@ -16,22 +16,31 @@
package net.micode.notes.data;
-import android.content.ContentValues;
+import android.content.ContentValues;//就是用于保存一些数据(string boolean ...)信息,这些信息可以被数据库操作时使用。
import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteDatabase;//主要提供了对应于添加、删除、更新、查询的操作方法: insert()、delete()、update()和query()。配合content.values
+import android.database.sqlite.SQLiteOpenHelper;//用来管理数据的创建和版本更新
import android.util.Log;
-//引用了同一个包中的另一个子包Notes中一些接口
+
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
-//数据库操作
+/**
+ * @Package: net.micode.notes.data
+ * @ClassName: NotesDatabaseHelper
+ * @Description: 便签数据库操作底层实现
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/21 19:46
+ * @Version: 1.0
+ */
public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "note.db";
private static final int DB_VERSION = 4;
- //接口两部分一个Note一个DATA
+ /**
+ * 接口,创建数据库表头
+ */
public interface TABLE {
public static final String NOTE = "note";
@@ -41,7 +50,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "NotesDatabaseHelper";
private static NotesDatabaseHelper mInstance;
- //基于NoteColumn创建一个NOTE_TABLE表格,并附上初始数据
+ /**
+ * 便签的属性数据库
+ */
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
@@ -62,7 +73,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";
- //主要基于datacolumn来创建DATA_TABLE
+ /**
+ * 便签的内容数据库
+ */
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
@@ -77,13 +90,13 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";
- //这个数据是关于INDEX编号的
+
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
/**
- * Increase folder's note count when move note to the folder
+ * 文件夹内移进便签时需要修改的数据
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update "+
@@ -93,9 +106,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
- //移入note时触发,修改一系列数据,从哪来之类的
+
/**
- * Decrease folder's note count when move note from folder
+ * 便签移出文件夹时需要修改的数据
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " +
@@ -106,9 +119,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
- //移除Note时触发,与上面移入对应
+
/**
- * Increase folder's note count when insert new note to the folder
+ * 插入(新建)便签时需要修改的数据
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " +
@@ -118,9 +131,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
- //插入Note
+
/**
- * Decrease folder's note count when delete note from the folder
+ * 删除便签时需要修改的数据
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " +
@@ -131,7 +144,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
- //删除note
+
/**
* Update note's content when insert data with type {@link DataConstants#NOTE}
*/
@@ -144,7 +157,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
- //当给note插入新数据时触发
+
/**
* Update note's content when data with {@link DataConstants#NOTE} type has changed
*/
@@ -156,7 +169,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
- " END";//note数据被修改update
+ " END";
/**
* Update note's content when data with {@link DataConstants#NOTE} type has deleted
@@ -169,7 +182,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
- " END";//更新已经删除的便签的数据
+ " END";
/**
* Delete datas belong to note which has been deleted
@@ -180,7 +193,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
- " END";//删除 已经被删除的便签的数据
+ " END";
/**
* Delete notes belong to folder which has been deleted
@@ -191,7 +204,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
- " END";//删除 已删除folder文件夹 中的便签要修改的数据
+ " END";
/**
* Move notes belong to folder which has been moved to trash folder
@@ -204,12 +217,12 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
- " END";//移动trash_folder中的便签
+ " END";
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
- //构造函数
+
public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL);
reCreateNoteTableTriggers(db);
@@ -233,49 +246,48 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
- }//数据库操作的API,重新创建
-
+ }
+ /**
+ * @method createSystemFolder
+ * @description: 创建系统缺省文件夹:通话记录、缺省根目录、临时文件夹、回收文件夹
+ * @date: 2023/12/21 20:19
+ * @author: WuShuxian
+ * @param: db
+ * @return: void
+ */
private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues();
- /**
- * call record foler for call notes
- */
+ //通话记录文件夹
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
- /**
- * root folder which is default folder
- */
+ //缺省根目录
values.clear();
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
- /**
- * temporary folder which is used for moving note
- */
+ //临时文件夹
values.clear();
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
- /**
- * create trash folder
- */
+ //回收站文件夹
values.clear();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
- }//创建系统文件夹
+ }
public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL);
reCreateDataTableTriggers(db);
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
Log.d(TAG, "data table has been created");
- }//创建数据表格
+ }
private void reCreateDataTableTriggers(SQLiteDatabase db) {
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
@@ -285,38 +297,45 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
- }//类似于recreatenotetable,重新创建触发器
+ }
static synchronized NotesDatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context);
}
return mInstance;
- }//sync同步,同一时刻只有一个线程执行
+ }
@Override
public void onCreate(SQLiteDatabase db) {
- createNoteTable(db);
- createDataTable(db);
- }//创建Note Data两个表格
-
+ createNoteTable(db);//属性数据库
+ createDataTable(db);//内容数据库
+ }
+ /**
+ * @method onUpgrade
+ * @description: 便签版本更新?没有使用者判断不了
+ * @date: 2023/12/21 20:42
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
boolean reCreateTriggers = false;
boolean skipV2 = false;
-
+ //V1->V2
if (oldVersion == 1) {
upgradeToV2(db);
skipV2 = true; // this upgrade including the upgrade from v2 to v3
oldVersion++;
}
-
+ //V2->V3
if (oldVersion == 2 && !skipV2) {
upgradeToV3(db);
reCreateTriggers = true;
oldVersion++;
}
-
+ //V3->V4
if (oldVersion == 3) {
upgradeToV4(db);
oldVersion++;
@@ -331,15 +350,19 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails");
}
- }//数据库版本更新
-
+ }
+ /**
+ * 升级到V2,修改相应数据库
+ */
private void upgradeToV2(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
createNoteTable(db);
createDataTable(db);
- }//更新到V2
-
+ }
+ /**
+ * 升级到V3,修改相应数据库
+ */
private void upgradeToV3(SQLiteDatabase db) {
// drop unused triggers
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
@@ -353,10 +376,12 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
- }//更新到V3
-
+ }
+ /**
+ * 升级到V4,修改相应数据库
+ */
private void upgradeToV4(SQLiteDatabase db) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
- }//更新到V4
+ }
}
diff --git a/src/main/java/net/micode/notes/data/NotesProvider.java b/src/main/java/net/micode/notes/data/NotesProvider.java
index 6897999..ddb2282 100644
--- a/src/main/java/net/micode/notes/data/NotesProvider.java
+++ b/src/main/java/net/micode/notes/data/NotesProvider.java
@@ -1,5 +1,22 @@
+/*
+ * 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.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
@@ -16,15 +33,19 @@ import net.micode.notes.R;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
-//为存储和获取数据提供接口。可以在不同的应用程序之间共享数据
-//ContentProvider提供的方法
-//query:查询
-//insert:插入
-//update:更新
-//delete:删除
-//getType:得到数据类型
+
+/**
+ * @Package: net.micode.notes.data
+ * @ClassName: NotesProvider
+ * @Description: 为存储和获取数据提供接口。可以在不同的应用程序之间共享数据
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/21 20:50
+ * @Version: 1.0
+ */
public class NotesProvider extends ContentProvider {
- // UriMatcher用于匹配Uri
+ /**
+ * UriMatcher用于匹配Uri
+ */
private static final UriMatcher mMatcher;
private NotesDatabaseHelper mHelper;
@@ -40,9 +61,7 @@ public class NotesProvider extends ContentProvider {
private static final int URI_SEARCH_SUGGEST = 6;
static {
- // 创建UriMatcher时,调用UriMatcher(UriMatcher.NO_MATCH)表示不匹配任何路径的返回码
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- // 把需要匹配Uri路径全部给注册上
mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE);
mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA);
@@ -53,43 +72,44 @@ public class NotesProvider extends ContentProvider {
}
/**
+ * 搜索字段
* x'0A' represents the '\n' character in sqlite. For title and content in the search result,
* we will trim '\n' and white space in order to show more information.
*/
- // 声明 NOTES_SEARCH_PROJECTION
private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + ","
- + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + ","
- + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + ","
- + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + ","
- + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + ","
- + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + ","
- + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA;
- // 声明NOTES_SNIPPET_SEARCH_QUERY
+ + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + ","
+ + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + ","
+ + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + ","
+ + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + ","
+ + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + ","
+ + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA;
+
private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION
- + " FROM " + TABLE.NOTE
- + " WHERE " + NoteColumns.SNIPPET + " LIKE ?"
- + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
- + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
+ + " FROM " + TABLE.NOTE
+ + " WHERE " + NoteColumns.SNIPPET + " LIKE ?"
+ + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
+ + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
@Override
- // Context只有在onCreate()中才被初始化
- // 对mHelper进行实例化
public boolean onCreate() {
mHelper = NotesDatabaseHelper.getInstance(getContext());
return true;
}
-
+ /**
+ * @Package: net.micode.notes.data
+ * @ClassName: NotesProvider
+ * @Description: 查询Uri在数据库中的位置
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/21 21:06
+ * @Version: 1.0
+ */
@Override
- // 查询uri在数据库中对应的位置
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
+ String sortOrder) {
Cursor c = null;
- // 获取可读数据库
- SQLiteDatabase db = mHelper.getReadableDatabase();
+ SQLiteDatabase db = mHelper.getReadableDatabase();//读数据库
String id = null;
- // 匹配查找uri
switch (mMatcher.match(uri)) {
- // 对于不同的匹配值,在数据库中查找相应的条目
case URI_NOTE:
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder);
@@ -111,7 +131,6 @@ public class NotesProvider extends ContentProvider {
case URI_SEARCH:
case URI_SEARCH_SUGGEST:
if (sortOrder != null || projection != null) {
- // 不合法的参数异常
throw new IllegalArgumentException(
"do not specify sortOrder, selection, selectionArgs, or projection" + "with this query");
}
@@ -119,8 +138,6 @@ public class NotesProvider extends ContentProvider {
String searchString = null;
if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {
if (uri.getPathSegments().size() > 1) {
- // getPathSegments()方法得到一个String的List,
- // 在uri.getPathSegments().get(1)为第2个元素
searchString = uri.getPathSegments().get(1);
}
} else {
@@ -132,7 +149,7 @@ public class NotesProvider extends ContentProvider {
}
try {
- searchString = String.format("%%%s%%", searchString);
+ searchString = String.format("%%%s%%", searchString);//在新建便签并输入内容保存后会跳到这里,暂时不知道为什么
c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY,
new String[] { searchString });
} catch (IllegalStateException ex) {
@@ -140,7 +157,6 @@ public class NotesProvider extends ContentProvider {
}
break;
default:
- // 抛出异常
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (c != null) {
@@ -149,18 +165,22 @@ public class NotesProvider extends ContentProvider {
return c;
}
+ /**
+ * @method insert
+ * @description: 插入一个Uri,只有新建便签并保存后才会触发,修改内容不会触发
+ * @date: 2023/12/21 21:16
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
- // 插入一个uri
public Uri insert(Uri uri, ContentValues values) {
- // 获得可写的数据库
SQLiteDatabase db = mHelper.getWritableDatabase();
long dataId = 0, noteId = 0, insertedId = 0;
switch (mMatcher.match(uri)) {
- // 新增一个条目
case URI_NOTE:
insertedId = noteId = db.insert(TABLE.NOTE, null, values);
break;
- // 如果存在,查找NOTE_ID
case URI_DATA:
if (values.containsKey(DataColumns.NOTE_ID)) {
noteId = values.getAsLong(DataColumns.NOTE_ID);
@@ -173,7 +193,6 @@ public class NotesProvider extends ContentProvider {
throw new IllegalArgumentException("Unknown URI " + uri);
}
// Notify the note uri
- // notifyChange获得一个ContextResolver对象并且更新里面的内容
if (noteId > 0) {
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);
@@ -185,17 +204,20 @@ public class NotesProvider extends ContentProvider {
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);
}
- // 返回插入的uri的路径
return ContentUris.withAppendedId(uri, insertedId);
}
-
+ /**
+ * @method delete
+ * @description: 删除一个Uri,删除便签时会触发
+ * @date: 2023/12/21 21:17
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
- // 删除一个uri
public int delete(Uri uri, String selection, String[] selectionArgs) {
- //Uri代表要操作的数据,Android上可用的每种资源 -包括 图像、视频片段、音频资源等都可以用Uri来表示。
int count = 0;
String id = null;
- // 获得可写的数据库
SQLiteDatabase db = mHelper.getWritableDatabase();
boolean deleteData = false;
switch (mMatcher.match(uri)) {
@@ -204,7 +226,7 @@ public class NotesProvider extends ContentProvider {
count = db.delete(TABLE.NOTE, selection, selectionArgs);
break;
case URI_NOTE_ITEM:
- id = uri.getPathSegments().get(1);
+ id = uri.getPathSegments().get(1);//修改便签内容时会触发,原因不明
/**
* ID that smaller than 0 is system folder which is not allowed to
* trash
@@ -237,9 +259,15 @@ public class NotesProvider extends ContentProvider {
}
return count;
}
-
+ /**
+ * @method update
+ * @description: 更新Uri,修改便签时会触发。期间会跳到delete中执行,原因不明
+ * @date: 2023/12/21 21:19
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
- // 更新一个uri
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0;
String id = null;
@@ -279,12 +307,10 @@ public class NotesProvider extends ContentProvider {
return count;
}
- // 将字符串解析成规定格式
private String parseSelection(String selection) {
return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
}
- //增加一个noteVersion
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
StringBuilder sql = new StringBuilder(120);
sql.append("UPDATE ");
@@ -307,7 +333,6 @@ public class NotesProvider extends ContentProvider {
sql.append(selectString);
}
- // execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句
mHelper.getWritableDatabase().execSQL(sql.toString());
}
@@ -317,4 +342,4 @@ public class NotesProvider extends ContentProvider {
return null;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/net/micode/notes/gtask/data/MetaData.java b/src/main/java/net/micode/notes/gtask/data/MetaData.java
index 3a2050b..9b96094 100644
--- a/src/main/java/net/micode/notes/gtask/data/MetaData.java
+++ b/src/main/java/net/micode/notes/gtask/data/MetaData.java
@@ -24,12 +24,26 @@ import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException;
import org.json.JSONObject;
-
+/**
+ * @Package: net.micode.notes.gtask.data
+ * @ClassName: MetaData
+ * @Description: 一些元数据的操作
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/22 21:45
+ * @Version: 1.0
+ */
public class MetaData extends Task {
private final static String TAG = MetaData.class.getSimpleName();
private String mRelatedGid = null;
-
+ /**
+ * @method setMeta
+ * @description: 生成元数据库
+ * @date: 2023/12/24 20:07
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
public void setMeta(String gid, JSONObject metaInfo) {
try {
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
@@ -48,7 +62,14 @@ public class MetaData extends Task {
public boolean isWorthSaving() {
return getNotes() != null;
}
-
+ /**
+ * @method setContentByRemoteJSON
+ * @description: 从远程Json对象设置元数据库内容
+ * @date: 2023/12/24 20:11
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
public void setContentByRemoteJSON(JSONObject js) {
super.setContentByRemoteJSON(js);
@@ -62,7 +83,14 @@ public class MetaData extends Task {
}
}
}
-
+ /**
+ * @method setContentByLocalJSON
+ * @description: 根据本地Json对象设置元数据库内容
+ * @date: 2023/12/24 20:12
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
public void setContentByLocalJSON(JSONObject js) {
// this function should not be called
diff --git a/src/main/java/net/micode/notes/gtask/data/Node.java b/src/main/java/net/micode/notes/gtask/data/Node.java
index 63950e0..c3ebd5a 100644
--- a/src/main/java/net/micode/notes/gtask/data/Node.java
+++ b/src/main/java/net/micode/notes/gtask/data/Node.java
@@ -19,24 +19,50 @@ package net.micode.notes.gtask.data;
import android.database.Cursor;
import org.json.JSONObject;
-
+/**
+ * @Package: net.micode.notes.gtask.data
+ * @ClassName: Node
+ * @Description: 定义了同步节点:多个关于同步的常量,实现类似于Git的版本控制
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/21 21:30
+ * @Version: 1.0
+ */
public abstract class Node {
+ /**
+ * 本地与云端一致
+ */
public static final int SYNC_ACTION_NONE = 0;
-
+ /**
+ * 需要云端添加内容
+ */
public static final int SYNC_ACTION_ADD_REMOTE = 1;
-
+ /**
+ * 需要本地添加内容
+ */
public static final int SYNC_ACTION_ADD_LOCAL = 2;
-
+ /**
+ * 需要删除云端的内容
+ */
public static final int SYNC_ACTION_DEL_REMOTE = 3;
-
+ /**
+ * 需要删除本地的内容
+ */
public static final int SYNC_ACTION_DEL_LOCAL = 4;
-
+ /**
+ * 本地同步到云端
+ */
public static final int SYNC_ACTION_UPDATE_REMOTE = 5;
-
+ /**
+ * 云端同步到本地
+ */
public static final int SYNC_ACTION_UPDATE_LOCAL = 6;
-
+ /**
+ * 同步出现冲突
+ */
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;
-
+ /**
+ * 同步错误
+ */
public static final int SYNC_ACTION_ERROR = 8;
private String mGid;
diff --git a/src/main/java/net/micode/notes/gtask/data/SqlData.java b/src/main/java/net/micode/notes/gtask/data/SqlData.java
index d3ec3be..76ffb9f 100644
--- a/src/main/java/net/micode/notes/gtask/data/SqlData.java
+++ b/src/main/java/net/micode/notes/gtask/data/SqlData.java
@@ -34,7 +34,15 @@ import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException;
import org.json.JSONObject;
-
+/**
+ * @Package: net.micode.notes.gtask.data
+ * @ClassName: SqlData
+ * @Description: 用于支持小米便签最底层的数据库相关操作,和sqlnote的关系上是子集关系,即data是note的子集(节点)
+ * SqlData其实就是也就是所谓数据中的数据
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 20:13
+ * @Version: 1.0
+ */
public class SqlData {
private static final String TAG = SqlData.class.getSimpleName();
@@ -44,7 +52,9 @@ public class SqlData {
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3
};
-
+ /**
+ * 以下五个变量作为sql表中5列的编号
+ */
public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1;
@@ -70,7 +80,14 @@ public class SqlData {
private String mDataContentData3;
private ContentValues mDiffDataValues;
-
+ /**
+ * @method SqlData
+ * @description: 构造函数,用于初始化数据
+ * @date: 2023/12/24 20:17
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
public SqlData(Context context) {
mContentResolver = context.getContentResolver();
mIsCreate = true;
@@ -81,14 +98,28 @@ public class SqlData {
mDataContentData3 = "";
mDiffDataValues = new ContentValues();
}
-
+ /**
+ * @method SqlData
+ * @description: 构造函数,根据已有数据初始化一个新的数据对象
+ * @date: 2023/12/24 20:17
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
public SqlData(Context context, Cursor c) {
mContentResolver = context.getContentResolver();
mIsCreate = false;
loadFromCursor(c);
mDiffDataValues = new ContentValues();
}
-
+ /**
+ * @method loadFromCursor
+ * @description: 从光标处加载数据
+ * @date: 2023/12/24 20:18
+ * @author: WuShuxian
+ * @param: c:光标的位置
+ * @return: void
+ */
private void loadFromCursor(Cursor c) {
mDataId = c.getLong(DATA_ID_COLUMN);
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
@@ -96,7 +127,14 @@ public class SqlData {
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
-
+ /**
+ * @method setContent
+ * @description: 设置用于共享的数据,并提供异常抛出与处理机制
+ * @date: 2023/12/24 20:19
+ * @author: WuShuxian
+ * @param: js: Json对象
+ * @return: void
+ */
public void setContent(JSONObject js) throws JSONException {
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
if (mIsCreate || mDataId != dataId) {
@@ -143,7 +181,16 @@ public class SqlData {
js.put(DataColumns.DATA3, mDataContentData3);
return js;
}
-
+ /**
+ * @method commit
+ * @description: commit函数用于把当前造作所做的修改保存到数据库
+ * @date: 2023/12/24 20:21
+ * @author: WuShuxian
+ * @param: noteId:要保存的便签ID
+ * validateVersion:判断此次修改是否合法
+ * version:版本号
+ * @return: void
+ */
public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) {
diff --git a/src/main/java/net/micode/notes/gtask/data/SqlNote.java b/src/main/java/net/micode/notes/gtask/data/SqlNote.java
index 79a4095..ae97d68 100644
--- a/src/main/java/net/micode/notes/gtask/data/SqlNote.java
+++ b/src/main/java/net/micode/notes/gtask/data/SqlNote.java
@@ -37,7 +37,14 @@ import org.json.JSONObject;
import java.util.ArrayList;
-
+/**
+ * @Package: net.micode.notes.gtask.data
+ * @ClassName: SqlNote
+ * @Description: 用于支持小米便签最底层的数据库相关操作,和sqldata的关系上是父集关系,即note是data的子父集
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 20:23
+ * @Version: 1.0
+ */
public class SqlNote {
private static final String TAG = SqlNote.class.getSimpleName();
@@ -121,17 +128,24 @@ public class SqlNote {
private ContentValues mDiffNoteValues;
private ArrayList mDataList;
-
+ /**
+ * @method SqlNote
+ * @description: 构造函数,初始化context的所有数据
+ * @date: 2023/12/24 20:24
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
public SqlNote(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
- mIsCreate = true;
+ mIsCreate = true;//用于标识构造方法
mId = INVALID_ID;
mAlertDate = 0;
mBgColorId = ResourceParser.getDefaultBgId(context);
- mCreatedDate = System.currentTimeMillis();
+ mCreatedDate = System.currentTimeMillis();//调用系统函数获得创建时间
mHasAttachment = 0;
- mModifiedDate = System.currentTimeMillis();
+ mModifiedDate = System.currentTimeMillis();//最后一次修改时间初始化为创建时间
mParentId = 0;
mSnippet = "";
mType = Notes.TYPE_NOTE;
@@ -142,22 +156,36 @@ public class SqlNote {
mDiffNoteValues = new ContentValues();
mDataList = new ArrayList();
}
-
+ /**
+ * @method SqlNote
+ * @description: 构造函数,根据光标所指向的已有数据构造新对象
+ * @date: 2023/12/24 20:25
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
public SqlNote(Context context, Cursor c) {
mContext = context;
mContentResolver = context.getContentResolver();
- mIsCreate = false;
+ mIsCreate = false;//用于标识构造方法
loadFromCursor(c);
mDataList = new ArrayList();
if (mType == Notes.TYPE_NOTE)
loadDataContent();
mDiffNoteValues = new ContentValues();
}
-
+ /**
+ * @method SqlNote
+ * @description: 构造函数,根据ID构造新对象
+ * @date: 2023/12/24 20:27
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
public SqlNote(Context context, long id) {
mContext = context;
mContentResolver = context.getContentResolver();
- mIsCreate = false;
+ mIsCreate = false;//标识构造方法
loadFromCursor(id);
mDataList = new ArrayList();
if (mType == Notes.TYPE_NOTE)
@@ -199,7 +227,14 @@ public class SqlNote {
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
mVersion = c.getLong(VERSION_COLUMN);
}
-
+ /**
+ * @method loadDataContent
+ * @description: 通过content机制获取共享数据并加载到数据库当前游标处
+ * @date: 2023/12/24 20:29
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
private void loadDataContent() {
Cursor c = null;
mDataList.clear();
@@ -439,7 +474,14 @@ public class SqlNote {
public boolean isNoteType() {
return mType == Notes.TYPE_NOTE;
}
-
+ /**
+ * @method commit
+ * @description: commit函数用于把当前所做的修改保存到数据库
+ * @date: 2023/12/24 20:30
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
public void commit(boolean validateVersion) {
if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
diff --git a/src/main/java/net/micode/notes/gtask/data/Task.java b/src/main/java/net/micode/notes/gtask/data/Task.java
index 6a19454..bafeb0f 100644
--- a/src/main/java/net/micode/notes/gtask/data/Task.java
+++ b/src/main/java/net/micode/notes/gtask/data/Task.java
@@ -31,7 +31,14 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-
+/**
+ * @Package: net.micode.notes.gtask.data
+ * @ClassName: Task
+ * @Description: Node类的子类,用于支持任务列表的操作
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 20:31
+ * @Version: 1.0
+ */
public class Task extends Node {
private static final String TAG = Task.class.getSimpleName();
@@ -53,22 +60,25 @@ public class Task extends Node {
mParent = null;
mMetaInfo = null;
}
-
+ /**
+ * @method getCreateAction
+ * @description: 获取创建信息,以Json格式返回
+ * @date: 2023/12/24 20:33
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
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");
@@ -79,17 +89,13 @@ public class Task extends Node {
}
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());
}
@@ -102,22 +108,25 @@ public class Task extends Node {
return js;
}
-
+ /**
+ * @method getUpdateAction
+ * @description: 获取创建动作,以Json格式返回
+ * @date: 2023/12/24 20:34
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
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) {
@@ -138,32 +147,26 @@ public class Task extends Node {
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));
}
@@ -208,7 +211,6 @@ public class Task extends Node {
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;
@@ -225,7 +227,6 @@ public class Task extends Node {
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);
@@ -275,29 +276,24 @@ public class Task extends Node {
return SYNC_ACTION_UPDATE_LOCAL;
}
- // validate the note id now
+ // 立即验证note id
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;
diff --git a/src/main/java/net/micode/notes/gtask/data/TaskList.java b/src/main/java/net/micode/notes/gtask/data/TaskList.java
index 4ea21c5..56802e9 100644
--- a/src/main/java/net/micode/notes/gtask/data/TaskList.java
+++ b/src/main/java/net/micode/notes/gtask/data/TaskList.java
@@ -29,7 +29,14 @@ import org.json.JSONObject;
import java.util.ArrayList;
-
+/**
+ * @Package: net.micode.notes.gtask.data
+ * @ClassName: TaskList
+ * @Description: 对Node的拓展,主要用于支持任务列表的操作
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 20:40
+ * @Version: 1.0
+ */
public class TaskList extends Node {
private static final String TAG = TaskList.class.getSimpleName();
@@ -47,17 +54,13 @@ public class TaskList extends Node {
JSONObject js = new JSONObject();
try {
- // action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
- GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
+ GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);// 动作类型
- // action_id
- js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
+ 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");
@@ -78,17 +81,13 @@ public class TaskList extends Node {
JSONObject js = new JSONObject();
try {
- // action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
- GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
+ GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);//动作类型
- // action_id
- js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
+ 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());
@@ -106,17 +105,14 @@ public class TaskList extends Node {
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));
}
@@ -225,7 +221,6 @@ public class TaskList extends Node {
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);
@@ -244,7 +239,7 @@ public class TaskList extends Node {
if (task != null && pos == -1) {
mChildren.add(index, task);
- // update the task list
+ // 更新任务列表
Task preTask = null;
Task afterTask = null;
if (index != 0)
@@ -267,11 +262,9 @@ public class TaskList extends Node {
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));
diff --git a/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java b/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java
index 15504be..e46c70a 100644
--- a/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java
+++ b/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java
@@ -15,8 +15,19 @@
*/
package net.micode.notes.gtask.exception;
-
+/**
+ * @Package: net.micode.notes.gtask.exception
+ * @ClassName: ActionFailureException
+ * @Description: 支持小米便签运行过程中的运行异常处理
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 20:45
+ * @Version: 1.0
+ */
public class ActionFailureException extends RuntimeException {
+ /**
+ * serialVersionUID相当于java类的身份证。主要用于版本控制
+ * serialVersionUID作用是序列化时保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性
+ */
private static final long serialVersionUID = 4425249765923293627L;
public ActionFailureException() {
diff --git a/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java b/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java
index b08cfb1..4291ece 100644
--- a/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java
+++ b/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java
@@ -15,8 +15,19 @@
*/
package net.micode.notes.gtask.exception;
-
+/**
+ * @Package: net.micode.notes.gtask.exception
+ * @ClassName: NetworkFailureException
+ * @Description: 支持小米便签运行过程中的网络异常处理
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 20:46
+ * @Version: 1.0
+ */
public class NetworkFailureException extends Exception {
+ /**
+ * serialVersionUID相当于java类的身份证。主要用于版本控制。
+ * serialVersionUID作用是序列化时保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性
+ */
private static final long serialVersionUID = 2107610287180234136L;
public NetworkFailureException() {
diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java b/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
index 0e332f3..075abe0 100644
--- a/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
+++ b/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
@@ -28,7 +28,14 @@ import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity;
-
+/**
+ * @Package: net.micode.notes.gtask.remote
+ * @ClassName: GTaskASyncTask
+ * @Description: 异步操作类,实现GTask的异步操作过程
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 20:49
+ * @Version: 1.0
+ */
public class GTaskASyncTask extends AsyncTask {
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
@@ -62,9 +69,22 @@ public class GTaskASyncTask extends AsyncTask {
message
});
}
-
+ /**
+ * @method showNotification
+ * @description: 向用户提示当前同步的状态,是一个用于交互的方法
+ * @date: 2023/12/24 20:50
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
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;
+ //如果同步不成功,那么从系统取得一个用于启动一个NotesPreferenceActivity的PendingIntent对象
+ //如果同步成功,那么从系统取得一个用于启动一个NotesListActivity的PendingIntent对象
if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), 0);
@@ -73,21 +93,18 @@ public class GTaskASyncTask extends AsyncTask {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0);
}
-
-
- Notification.Builder builder = new Notification.Builder(mContext)
- .setAutoCancel(true)
- .setContentTitle(mContext.getString(R.string.app_name))
- .setContentText(content)
- .setContentIntent(pendingIntent)
- .setWhen(System.currentTimeMillis())
- .setOngoing(true);
- Notification notification=builder.getNotification();
+ //notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
+ //pendingIntent);
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
}
-
-
-
+ /**
+ * @method doInBackground
+ * @description: 此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间
+ * @date: 2023/12/24 20:51
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
protected Integer doInBackground(Void... unused) {
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
@@ -95,6 +112,14 @@ public class GTaskASyncTask extends AsyncTask {
return mTaskManager.sync(mContext, this);
}
+ /**
+ * @method onProgressUpdate
+ * @description: 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度
+ * @date: 2023/12/24 20:51
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
protected void onProgressUpdate(String... progress) {
showNotification(R.string.ticker_syncing, progress[0]);
@@ -103,6 +128,14 @@ public class GTaskASyncTask extends AsyncTask {
}
}
+ /**
+ * @method onPostExecute
+ * @description: 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI
+ * @date: 2023/12/24 20:51
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
@Override
protected void onPostExecute(Integer result) {
if (result == GTaskManager.STATE_SUCCESS) {
diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java b/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java
index c67dfdf..f8a0547 100644
--- a/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java
+++ b/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java
@@ -60,7 +60,14 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
-
+/**
+ * @Package: net.micode.notes.gtask.remote
+ * @ClassName: GTaskClient
+ * @Description: 实现GTASK的登录操作,进行GTASK任务的创建,创建任务列表,从网络上获取任务和任务列表的内容
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 20:55
+ * @Version: 1.0
+ */
public class GTaskClient {
private static final String TAG = GTaskClient.class.getSimpleName();
@@ -90,6 +97,12 @@ public class GTaskClient {
private JSONArray mUpdateArray;
+ /**
+ * @method GTaskClient
+ * @description: 构造函数
+ * @date: 2023/12/24 20:56
+ * @author: WuShuxian
+ */
private GTaskClient() {
mHttpClient = null;
mGetUrl = GTASK_GET_URL;
@@ -108,35 +121,40 @@ public class GTaskClient {
}
return mInstance;
}
-
+ /**
+ * @method login
+ * @description: 用来实现登录操作,有两种登录方式,使用用户自己的URL登录或者使用谷歌官方的URL登录
+ * @date: 2023/12/24 21:15
+ * @author: WuShuxian
+ * @param: activity
+ * @return: boolean
+ */
public boolean login(Activity activity) {
- // we suppose that the cookie would expire after 5 minutes
- // then we need to re-login
+ //判断距离最后一次登录操作是否超过5分钟
final long interval = 1000 * 60 * 5;
if (mLastLoginTime + interval < System.currentTimeMillis()) {
mLoggedin = false;
}
- // need to re-login after account switch
+ // 重新登陆操作
if (mLoggedin
&& !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity
.getSyncAccountName(activity))) {
mLoggedin = false;
}
-
+ //如果没超过时间,则不需要重新登录
if (mLoggedin) {
Log.d(TAG, "already logged in");
return true;
}
- mLastLoginTime = System.currentTimeMillis();
- String authToken = loginGoogleAccount(activity, false);
+ mLastLoginTime = System.currentTimeMillis();//更新最后登录时间为系统当前的时间
+ String authToken = loginGoogleAccount(activity, false);//判断是否登录到谷歌账户
if (authToken == null) {
Log.e(TAG, "login google account failed");
return false;
}
- // login with custom domain if necessary
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase()
.endsWith("googlemail.com"))) {
StringBuilder url = new StringBuilder(GTASK_URL).append("a/");
@@ -150,8 +168,7 @@ public class GTaskClient {
mLoggedin = true;
}
}
-
- // try to login with google official url
+ //如果用户账户无法登录,则使用谷歌官方的URI进行登录
if (!mLoggedin) {
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
@@ -163,7 +180,14 @@ public class GTaskClient {
mLoggedin = true;
return true;
}
-
+ /**
+ * @method loginGoogleAccount
+ * @description: 具体实现登录谷歌账户的方法
+ * @date: 2023/12/24 23:07
+ * @author: WuShuxian
+ * @param: activity
+ * @return: String
+ */
private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
String authToken;
AccountManager accountManager = AccountManager.get(activity);
@@ -176,6 +200,7 @@ public class GTaskClient {
String accountName = NotesPreferenceActivity.getSyncAccountName(activity);
Account account = null;
+ //遍历获得的accounts信息,寻找已经记录过的账户信息
for (Account a : accounts) {
if (a.name.equals(accountName)) {
account = a;
@@ -189,7 +214,7 @@ public class GTaskClient {
return null;
}
- // get the token now
+ //获取令牌
AccountManagerFuture accountManagerFuture = accountManager.getAuthToken(account,
"goanna_mobile", null, activity, null, null);
try {
@@ -206,11 +231,16 @@ public class GTaskClient {
return authToken;
}
-
+ /**
+ * @method tryToLoginGtask
+ * @description: 尝试登陆Gtask,这只是一个预先判断令牌是否是有效以及是否能登上GTask的方法,而不是具体实现登陆的方法
+ * @date: 2023/12/24 21:01
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
private boolean tryToLoginGtask(Activity activity, String authToken) {
if (!loginGtask(authToken)) {
- // maybe the auth token is out of date, now let's invalidate the
- // token and try again
authToken = loginGoogleAccount(activity, true);
if (authToken == null) {
Log.e(TAG, "login google account failed");
@@ -224,26 +254,33 @@ public class GTaskClient {
}
return true;
}
-
+ /**
+ * @method loginGtask
+ * @description: 具体实现登录操作
+ * @date: 2023/12/24 21:05
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
private boolean loginGtask(String authToken) {
int timeoutConnection = 10000;
- int timeoutSocket = 15000;
- HttpParams httpParameters = new BasicHttpParams();
- HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
- HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
+ int timeoutSocket = 15000; //socket是一种通信连接实现数据的交换的端口
+ HttpParams httpParameters = new BasicHttpParams(); //实例化一个新的HTTP参数类
+ HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);//设置连接超时时间
+ HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);//设置设置端口超时时间
mHttpClient = new DefaultHttpClient(httpParameters);
BasicCookieStore localBasicCookieStore = new BasicCookieStore();
mHttpClient.setCookieStore(localBasicCookieStore);
HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false);
- // login gtask
+ //登录操作
try {
- String loginUrl = mGetUrl + "?auth=" + authToken;
- HttpGet httpGet = new HttpGet(loginUrl);
+ String loginUrl = mGetUrl + "?auth=" + authToken;//设置登录的URL
+ HttpGet httpGet = new HttpGet(loginUrl);//通过登录的uri实例化网页上资源的查找
HttpResponse response = null;
response = mHttpClient.execute(httpGet);
- // get the cookie now
+ //获取CookieStore里存放的cookie,如果存有“GTL”,则cookie有效
List cookies = mHttpClient.getCookieStore().getCookies();
boolean hasAuthCookie = false;
for (Cookie cookie : cookies) {
@@ -255,7 +292,7 @@ public class GTaskClient {
Log.w(TAG, "it seems that there is no auth cookie");
}
- // get the client version
+ //获取client的内容
String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup(";
String jsEnd = ")}";
@@ -272,7 +309,6 @@ public class GTaskClient {
e.printStackTrace();
return false;
} catch (Exception e) {
- // simply catch all exceptions
Log.e(TAG, "httpget gtask_url failed");
return false;
}
@@ -283,14 +319,24 @@ public class GTaskClient {
private int getActionId() {
return mActionId++;
}
-
+ /**
+ * @method createHttpPost
+ * @description: 实例化创建一个用于向网络传输数据的对象
+ * @date: 2023/12/24 23:13
+ * @author: WuShuxian
+ */
private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
httpPost.setHeader("AT", "1");
return httpPost;
}
-
+ /**
+ * @method getResponseContent
+ * @description: 通过URL获取响应后返回的数据,也就是网络上的数据和资源
+ * @date: 2023/12/24 21:06
+ * @author: WuShuxian
+ */
private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null;
if (entity.getContentEncoding() != null) {
@@ -322,13 +368,20 @@ public class GTaskClient {
input.close();
}
}
-
+ /**
+ * @method postRequest
+ * @description: 通过Json发送请求
+ * @date: 2023/12/24 21:07
+ * @author: WuShuxian
+ * @param: js
+ * @return:
+ */
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) {
Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in");
}
-
+ //实例化一个httpPost的对象用来向服务器传输数据,在这里就是发送请求,而请求的内容在js里
HttpPost httpPost = createHttpPost();
try {
LinkedList list = new LinkedList();
@@ -336,9 +389,8 @@ public class GTaskClient {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
httpPost.setEntity(entity);
- // execute the post
HttpResponse response = mHttpClient.execute(httpPost);
- String jsString = getResponseContent(response.getEntity());
+ String jsString = getResponseContent(response.getEntity());//得到返回的数据和资源
return new JSONObject(jsString);
} catch (ClientProtocolException e) {
@@ -359,21 +411,25 @@ public class GTaskClient {
throw new ActionFailureException("error occurs when posting request");
}
}
-
+ /**
+ * @method createTask
+ * @description: 创建单个任务
+ * @date: 2023/12/24 21:08
+ * @author: WuShuxian
+ * @param: task
+ * @return: void
+ */
public void createTask(Task task) throws NetworkFailureException {
commitUpdate();
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
- // action_list
actionList.put(task.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
- // client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
- // post
JSONObject jsResponse = postRequest(jsPost);
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
@@ -385,25 +441,29 @@ public class GTaskClient {
throw new ActionFailureException("create task: handing jsonobject failed");
}
}
-
+ /**
+ * @method createTaskList
+ * @description: 建一个任务列表,与createTask几乎一样,区别就是最后设置的是tasklist的gid
+ * @date: 2023/12/24 21:09
+ * @author: WuShuxian
+ * @param: tasklist
+ * @return: void
+ */
public void createTaskList(TaskList tasklist) throws NetworkFailureException {
commitUpdate();
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
- // action_list
actionList.put(tasklist.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
- // client version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
- // post
- JSONObject jsResponse = postRequest(jsPost);
+ JSONObject jsResponse = postRequest(jsPost);//得到任务的返回信息
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
- tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));
+ tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));//设置task的new_id
} catch (JSONException e) {
Log.e(TAG, e.toString());
@@ -417,10 +477,8 @@ public class GTaskClient {
try {
JSONObject jsPost = new JSONObject();
- // action_list
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray);
- // client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost);
@@ -432,11 +490,17 @@ public class GTaskClient {
}
}
}
-
+ /**
+ * @method addUpdateNode
+ * @description: 添加更新的事项
+ * @date: 2023/12/24 23:19
+ * @author: WuShuxian
+ * @param: node
+ * @return: void
+ */
public void addUpdateNode(Node node) throws NetworkFailureException {
if (node != null) {
- // too many update items may result in an error
- // set max to 10 items
+ //设置更新(同步)项目数量上限:10
if (mUpdateArray != null && mUpdateArray.length() > 10) {
commitUpdate();
}
@@ -446,7 +510,14 @@ public class GTaskClient {
mUpdateArray.put(node.getUpdateAction(getActionId()));
}
}
-
+ /**
+ * @method moveTask
+ * @description: 移动task,比如讲task移动到不同的task列表中去
+ * @date: 2023/12/24 23:19
+ * @author: WuShuxian
+ * @param: task、preParent、curParent
+ * @return: void
+ */
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
commitUpdate();
@@ -455,26 +526,22 @@ public class GTaskClient {
JSONArray actionList = new JSONArray();
JSONObject action = new JSONObject();
- // action_list
+ // 动作序列
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE);
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
action.put(GTaskStringUtils.GTASK_JSON_ID, task.getGid());
if (preParent == curParent && task.getPriorSibling() != null) {
- // put prioring_sibing_id only if moving within the tasklist and
- // it is not the first one
- action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling());
+ action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling());//设置优先级ID,只有当移动是发生在文件中
}
action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid());
action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid());
if (preParent != curParent) {
- // put the dest_list only if moving between tasklists
- action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());
+ action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());//仅当在任务列表之间移动时才放入dest_list
}
actionList.put(action);
- jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
+ jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);//将ACTION_LIST加入到jsPost中
- // client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost);
@@ -485,22 +552,27 @@ public class GTaskClient {
throw new ActionFailureException("move task: handing jsonobject failed");
}
}
-
+ /**
+ * @method deleteNode
+ * @description: 删除操作节点
+ * @date: 2023/12/24 23:22
+ * @author: WuShuxian
+ * @param: node
+ * @return: void
+ */
public void deleteNode(Node node) throws NetworkFailureException {
commitUpdate();
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
- // action_list
node.setDeleted(true);
- actionList.put(node.getUpdateAction(getActionId()));
+ actionList.put(node.getUpdateAction(getActionId()));//获取删除操作的ID,加入actionLiast
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
- // client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
- postRequest(jsPost);
+ postRequest(jsPost);//使用postRequest发送删除后的结果
mUpdateArray = null;
} catch (JSONException e) {
Log.e(TAG, e.toString());
@@ -508,7 +580,14 @@ public class GTaskClient {
throw new ActionFailureException("delete node: handing jsonobject failed");
}
}
-
+ /**
+ * @method getTaskLists
+ * @description: 获取任务列表
+ * @date: 2023/12/24 23:24
+ * @author: WuShuxian
+ * @param: void
+ * @return:
+ */
public JSONArray getTaskLists() throws NetworkFailureException {
if (!mLoggedin) {
Log.e(TAG, "please login first");
@@ -520,8 +599,8 @@ public class GTaskClient {
HttpResponse response = null;
response = mHttpClient.execute(httpGet);
- // get the task list
- String resString = getResponseContent(response.getEntity());
+ // 获取任务列表,把筛选出的字符串放入jsString
+ String resString = getResponseContent(response.getEntity());//从网上获取数据
String jsBegin = "_setup(";
String jsEnd = ")}";
int begin = resString.indexOf(jsBegin);
@@ -546,7 +625,14 @@ public class GTaskClient {
throw new ActionFailureException("get task lists: handing jasonobject failed");
}
}
-
+ /**
+ * @method getTaskList
+ * @description: 通过传入的TASKList的gid,从网络上获取相应属于这个任务列表的任务
+ * @date: 2023/12/24 23:28
+ * @author: WuShuxian
+ * @param: listGid
+ * @return:
+ */
public JSONArray getTaskList(String listGid) throws NetworkFailureException {
commitUpdate();
try {
@@ -554,7 +640,6 @@ public class GTaskClient {
JSONArray actionList = new JSONArray();
JSONObject action = new JSONObject();
- // action_list
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL);
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
@@ -563,7 +648,6 @@ public class GTaskClient {
actionList.put(action);
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
- // client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
JSONObject jsResponse = postRequest(jsPost);
diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java b/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java
index d2b4082..e7771a2 100644
--- a/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java
+++ b/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java
@@ -47,7 +47,14 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
-
+/**
+ * @Package: net.micode.notes.gtask.remote
+ * @ClassName: GTaskManager
+ * @Description: 同步管理操作
+ * @Author: WuShuxian
+ * @CreateDate: 2023/12/24 21:13
+ * @Version: 1.0
+ */
public class GTaskManager {
private static final String TAG = GTaskManager.class.getSimpleName();
@@ -86,10 +93,17 @@ public class GTaskManager {
private HashMap mGidToNid;
private HashMap mNidToGid;
-
+ /**
+ * @method GTaskManager
+ * @description: 构造函数,初始化实例对象
+ * @date: 2023/12/24 23:30
+ * @author: WuShuxian
+ * @param: void
+ * @return: void
+ */
private GTaskManager() {
- mSyncing = false;
- mCancelled = false;
+ mSyncing = false;//正在同步,flase代表未执行
+ mCancelled = false;//全局标识,flase代表可以执行
mGTaskListHashMap = new HashMap();
mGTaskHashMap = new HashMap();
mMetaHashMap = new HashMap();
@@ -98,7 +112,14 @@ public class GTaskManager {
mGidToNid = new HashMap();
mNidToGid = new HashMap();
}
-
+ /**
+ * @method getInstance
+ * @description: 包含关键字synchronized,语言级同步,指明该函数可能运行在多线程的环境下
+ * @date: 2023/12/24 23:31
+ * @author: WuShuxian
+ * @param: void
+ * @return: GTaskManager
+ */
public static synchronized GTaskManager getInstance() {
if (mInstance == null) {
mInstance = new GTaskManager();
@@ -107,10 +128,17 @@ public class GTaskManager {
}
public synchronized void setActivityContext(Activity activity) {
- // used for getting authtoken
mActivity = activity;
}
-
+ /**
+ * @method sync
+ * @description: 用于同步的核心函数,实现了本地同步操作和远端同步操作
+ * @date: 2023/12/24 23:32
+ * @author: WuShuxian
+ * @param: context:获取上下文
+ * asyncTask:用于同步的异步操作类
+ * @return: int
+ */
public int sync(Context context, GTaskASyncTask asyncTask) {
if (mSyncing) {
Log.d(TAG, "Sync is in progress");
@@ -127,8 +155,9 @@ public class GTaskManager {
mGidToNid.clear();
mNidToGid.clear();
+ //进行同步操作,并作异常处理:网络异常、操作异常
try {
- GTaskClient client = GTaskClient.getInstance();
+ GTaskClient client = GTaskClient.getInstance();//创建一个实例:client
client.resetUpdateArray();
// login google task
@@ -139,18 +168,19 @@ public class GTaskManager {
}
// get the task list from google
+ //从google获取task list
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list));
initGTaskList();
- // do content sync work
+ //进行同步操作
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing));
syncContent();
} catch (NetworkFailureException e) {
Log.e(TAG, e.toString());
- return STATE_NETWORK_ERROR;
+ return STATE_NETWORK_ERROR;//网络异常
} catch (ActionFailureException e) {
Log.e(TAG, e.toString());
- return STATE_INTERNAL_ERROR;
+ return STATE_INTERNAL_ERROR;//操作异常
} catch (Exception e) {
Log.e(TAG, e.toString());
e.printStackTrace();
@@ -167,7 +197,14 @@ public class GTaskManager {
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;
}
-
+ /**
+ * @method initGTaskList
+ * @description: 初始化GtaskList,获取Google上的JSONtasklist转为本地TaskList
+ * @date: 2023/12/24 23:39
+ * @author: WuShuxian
+ * @param:
+ * @return:
+ */
private void initGTaskList() throws NetworkFailureException {
if (mCancelled)
return;
@@ -175,7 +212,7 @@ public class GTaskManager {
try {
JSONArray jsTaskLists = client.getTaskLists();
- // init meta list first
+ //初始化元列表
mMetaList = null;
for (int i = 0; i < jsTaskLists.length(); i++) {
JSONObject object = jsTaskLists.getJSONObject(i);
diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java b/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java
index 08abea2..cca36f7 100644
--- a/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java
+++ b/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java
@@ -23,14 +23,6 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
-/**
- * @Package: net.micode.notes.gtask.remote
- * @ClassName: GTaskSyncService
- * @Description:
- * @Author: WuShuxian
- * @CreateDate: 2024/1/15 21:36
- * @Version: 1.0
- */
public class GTaskSyncService extends Service {
public final static String ACTION_STRING_NAME = "sync_action_type";
@@ -126,12 +118,6 @@ public class GTaskSyncService extends Service {
context.startService(intent);
}
- /**
- * @method isSyncing
- * @description: 查询是否正在同步
- * @date: 2024/1/15 21:38
- * @author: WuShuxian
- */
public static boolean isSyncing() {
return mSyncTask != null;
}
diff --git a/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java b/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java
index 96f28bf..e6a9d73 100644
--- a/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java
+++ b/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java
@@ -46,21 +46,23 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- requestWindowFeature(Window.FEATURE_NO_TITLE);//设置界面显示——无标题
+ // 设置界面显示——无标题
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
final Window win = getWindow();
-
- win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);//设置窗体属性——在锁屏时显示
+ // 设置窗体属性——在锁屏时显示
+ win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
if (!isScreenOn()) {
- win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON//保持点亮、点亮屏幕、允许点亮时解锁
+ // 设置窗体属性——保持点亮、点亮屏幕、允许点亮时解锁
+ win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
}
- Intent intent = getIntent();//获取传递的 Intent
+ // 获取传递的 Intent
+ Intent intent = getIntent();
try {
// 从 Intent 中获取数据并处理——获取标签 ID
@@ -78,33 +80,24 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
mPlayer = new MediaPlayer();
if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) {
- showActionDialog();// 显示对话框
- playAlarmSound();// 播放闹钟提示音
+ // 显示对话框
+ showActionDialog();
+ // 播放闹钟提示音
+ playAlarmSound();
} else {
- finish();// 结束当前 Activity
+ // 结束当前 Activity
+ finish();
}
}
- /**
- * @method isScreenOn
- * @description
- * 判断屏幕是否锁屏,调用系统函数判断,最后返回值是布尔类型
- * @date: 12/23/2023 11:21 PM
- * @author: YangYizhe
- * @param
- * @return
- */
+
private boolean isScreenOn() {
+ //判断屏幕是否锁屏,调用系统函数判断,最后返回值是布尔类型
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
return pm.isScreenOn();
}
- /**
- * @method playAlarmSound
- * @description
- * 播放闹钟提示音
- * @date: 12/23/2023 11:21 PM
- * @author: YangYizhe
- */
+
private void playAlarmSound() {
+ //闹钟提示音激发
Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM);
//调用系统的铃声管理URI,得到闹钟提示音
int silentModeStreams = Settings.System.getInt(getContentResolver(),
@@ -117,12 +110,19 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
}
try {
mPlayer.setDataSource(this, url);
+ //方法:setDataSource(Context context, Uri uri)
+ //解释:无返回值,设置多媒体数据来源【根据 Uri】
mPlayer.prepare();
- mPlayer.setLooping(true);//设置是否循环播放
- mPlayer.start();//开始播放
+ //准备同步
+ mPlayer.setLooping(true);
+ //设置是否循环播放
+ mPlayer.start();
+ //开始播放
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
+ //e.printStackTrace()函数功能是抛出异常, 还将显示出更深的调用信息
+ //System.out.println(e),这个方法打印出异常,并且输出在哪里出现的异常
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -134,67 +134,61 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD
e.printStackTrace();
}
}
- /**
- * @method showActionDialog
- * @description
- * AlertDialog的构造方法全部是Protected的
- * 所以不能直接通过new一个AlertDialog来创建出一个AlertDialog。
- * 要创建一个AlertDialog,就要用到AlertDialog.Builder中的create()方法
- * 如这里的dialog就是新建了一个AlertDialog
- * @date: 12/23/2023 11:28 PM
- * @author: YangYizhe
- */
+
private void showActionDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
- dialog.setTitle(R.string.app_name);//为对话框设置标题
- dialog.setMessage(mSnippet);//为对话框设置内容
- dialog.setPositiveButton(R.string.notealert_ok, this);//给对话框添加"Yes"按钮
+ /* AlertDialog的构造方法全部是Protected的
+ * 所以不能直接通过new一个AlertDialog来创建出一个AlertDialog。
+ * 要创建一个AlertDialog,就要用到AlertDialog.Builder中的create()方法
+ * 如这里的dialog就是新建了一个AlertDialog
+ */
+ dialog.setTitle(R.string.app_name);
+ //为对话框设置标题
+ dialog.setMessage(mSnippet);
+ //为对话框设置内容
+ dialog.setPositiveButton(R.string.notealert_ok, this);
+ //给对话框添加"Yes"按钮
if (isScreenOn()) {
- dialog.setNegativeButton(R.string.notealert_enter, this);//对话框添加"No"按钮
- }
+ dialog.setNegativeButton(R.string.notealert_enter, this);
+ }//对话框添加"No"按钮
dialog.show().setOnDismissListener(this);
}
- /**
- * @method onClick
- * @description 处理点击事件
- * @date: 12/23/2023 11:27 PM
- * @author: YangYizhe
- * @param dialog
- * @param which
- */
+
public void onClick(DialogInterface dialog, int which) {
- switch (which) {//用which来选择click后下一步的操作
- case DialogInterface.BUTTON_NEGATIVE://这是取消操作
- Intent intent = new Intent(this, NoteEditActivity.class);//实现两个类间的数据传输
- intent.setAction(Intent.ACTION_VIEW);//设置动作属性
- intent.putExtra(Intent.EXTRA_UID, mNoteId);//实现key-value对 EXTRA_UID为key;mNoteId为键
- startActivity(intent);//开始动作
+ switch (which) {
+ //用which来选择click后下一步的操作
+ case DialogInterface.BUTTON_NEGATIVE:
+ //这是取消操作
+ Intent intent = new Intent(this, NoteEditActivity.class);
+ //实现两个类间的数据传输
+ intent.setAction(Intent.ACTION_VIEW);
+ //设置动作属性
+ intent.putExtra(Intent.EXTRA_UID, mNoteId);
+ //实现key-value对
+ //EXTRA_UID为key;mNoteId为键
+ startActivity(intent);
+ //开始动作
break;
default:
+ //这是确定操作
break;
}
}
- /**
- * @method onDismiss
- * @description 忽略
- * @date: 12/23/2023 11:25 PM
- * @author: YangYizhe
- * @param dialog
- */
+
public void onDismiss(DialogInterface dialog) {
- stopAlarmSound();//停止闹钟声音
+ //忽略
+ stopAlarmSound();
+ //停止闹钟声音
finish();
+ //完成该动作
}
- /**
- * @method stopAlarmSound
- * @description 停止闹钟的声音
- * @date: 12/23/2023 11:26 PM
- * @author: YangYizhe
- */
+
private void stopAlarmSound() {
if (mPlayer != null) {
- mPlayer.stop();//停止播放
- mPlayer.release();//释放MediaPlayer对象
+ mPlayer.stop();
+ //停止播放
+ mPlayer.release();
+ //释放MediaPlayer对象
mPlayer = null;
}
}
diff --git a/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/src/main/java/net/micode/notes/ui/NoteEditActivity.java
index e18819a..4a0f840 100644
--- a/src/main/java/net/micode/notes/ui/NoteEditActivity.java
+++ b/src/main/java/net/micode/notes/ui/NoteEditActivity.java
@@ -14,15 +14,11 @@ import android.content.SharedPreferences;
import android.graphics.Paint;
import android.os.Bundle;
import android.preference.PreferenceManager;
-import android.speech.tts.TextToSpeech;
-import android.speech.tts.TextToSpeech.OnInitListener;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
-import android.text.Editable;// 引入textwatcher和Editable
-import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -34,14 +30,11 @@ import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
-import androidx.core.app.ActivityCompat;
-
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
@@ -61,6 +54,8 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import jp.wasabeef.richeditor.RichEditor;
+
/**
* @Package: net.micode.notes.ui
* @ClassName: NoteEditActivity
@@ -73,9 +68,6 @@ import java.util.regex.Pattern;
*/
public class NoteEditActivity extends Activity implements OnClickListener,
NoteSettingChangedListener, OnTextViewChangeListener {
- /**
- * 类属性的定义
- */
private class HeadViewHolder {
public TextView tvModified;
@@ -87,7 +79,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public TextView textNum;
}
-
private static final Map sBgSelectorBtnsMap = new HashMap();
static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
@@ -122,20 +113,19 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
}
- public static final int PHOTO_REQUEST = 1;//添加图片
- private static final int REQUEST_EXTERNAL_STORAGE=1;//权限申请
- private static String[] PERMISSIONS_STORAGE = {
- "android.permission.READ_EXTERNAL_STORAGE",
- "android.permission.WRITE_EXTERNAL_STORAGE" };//权限名称
-
private static final String TAG = "NoteEditActivity";
private HeadViewHolder mNoteHeaderHolder;
private View mHeadViewPanel;
private View mNoteBgColorSelector;
private View mFontSizeSelector;
- private EditText mNoteEditor;
+ //private EditText mNoteEditor;
+ private RichEditor mNoteEditor;//富文本编辑器
+ private TextView mPreview;
+ private String mText;//mText和mNoteLength是给富文本编辑器的
+ private int mNoteLength;
+ private int mFontSize;
private View mNoteEditorPanel;
- private WorkingNote mWorkingNote;
+ public WorkingNote mWorkingNote;
private SharedPreferences mSharedPrefs;
private int mFontSizeId;
@@ -151,42 +141,296 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private String mUserQuery;
private Pattern mPattern;
+
/**
- * @method Textchange
+ * 新增方法:
+ * 初始化富文本编辑框
+ */
+ public void initRichEditor(){
+ mNoteEditor.setEditorHeight(200);//设置编辑器界面高度
+ mNoteEditor.setEditorFontSize(22);//字体大小
+ mNoteEditor.setEditorFontColor(1);//字体颜色
+ mNoteEditor.setPadding(0, 0, 0, 0);//内边距
+ mNoteEditor.setPlaceholder("点击输入内容");//设置默认显示语句
+ mNoteEditor.setInputEnabled(true);//设置编辑器是否可用
+ mNoteEditor.setBackgroundResource(R.drawable.edit_yellow);//编辑背景
+ mNoteEditor.setOnTextChangeListener(new RichEditor.OnTextChangeListener() {
+ @Override
+ public void onTextChange(String text) {
+ mText = text;
+ mNoteLength = textChange(mText).length();
+ mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(NoteEditActivity.this,
+ mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
+ | DateUtils.FORMAT_SHOW_YEAR)+"\n字符数:"+mNoteLength);
+ }
+ });
+
+ findViewById(R.id.action_undo).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.undo();
+ }
+ });
+
+ findViewById(R.id.action_redo).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.redo();
+ }
+ });
+
+ findViewById(R.id.action_bold).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setBold();
+ }
+ });
+
+ findViewById(R.id.action_italic).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setItalic();
+ }
+ });
+ findViewById(R.id.action_subscript).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setSubscript();
+ }
+ });
+
+ findViewById(R.id.action_superscript).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setSuperscript();
+ }
+ });
+
+ findViewById(R.id.action_strikethrough).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setStrikeThrough();
+ }
+ });
+
+ findViewById(R.id.action_underline).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setUnderline();
+ }
+ });
+
+ findViewById(R.id.action_heading1).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setHeading(1);
+ }
+ });
+
+ findViewById(R.id.action_heading2).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setHeading(2);
+ }
+ });
+
+ findViewById(R.id.action_heading3).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setHeading(3);
+ }
+ });
+
+ findViewById(R.id.action_heading4).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setHeading(4);
+ }
+ });
+
+ findViewById(R.id.action_heading5).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setHeading(5);
+ }
+ });
+
+ findViewById(R.id.action_heading6).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setHeading(6);
+ }
+ });
+
+ /**findViewById(R.id.action_txt_color).setOnClickListener(new View.OnClickListener() {
+ private boolean isChanged;
+
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setTextColor(isChanged ? Color.BLACK : Color.RED);
+ isChanged = !isChanged;
+ }
+ });*/
+
+ /**findViewById(R.id.action_bg_color).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {//设置点击响应方法
+ mNoteEditor.focusEditor();
+ new AlertDialog.Builder(NoteEditActivity.this).setTitle("选择字体背景颜色")//设置一个AlertDialog供用户选择具体的颜色
+ .setSingleChoiceItems(R.array.text_bg_color, 0,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ //红
+ case 0:
+ mNoteEditor.setTextBackgroundColor(Color.RED);
+ break;
+ //黄
+ case 1:
+ mNoteEditor.setTextBackgroundColor(Color.YELLOW);
+ break;
+ //蓝
+ case 2:
+ mNoteEditor.setTextBackgroundColor(Color.BLUE);
+ break;
+ //绿
+ case 3:
+ mNoteEditor.setTextBackgroundColor(Color.GREEN);
+ break;
+ //黑
+ case 4:
+ mNoteEditor.setTextBackgroundColor(Color.BLACK);
+ break;
+
+ case 5:
+ mNoteEditor.setTextBackgroundColor(Color.WHITE);
+ break;
+ }
+ }
+ }).show();
+ }
+ });*/
+ findViewById(R.id.action_indent).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setIndent();
+ }
+ });
+
+ findViewById(R.id.action_outdent).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setOutdent();
+ }
+ });
+
+ findViewById(R.id.action_align_left).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setAlignLeft();
+ }
+ });
+
+ findViewById(R.id.action_align_center).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setAlignCenter();
+ }
+ });
+
+ findViewById(R.id.action_align_right).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setAlignRight();
+ }
+ });
+
+ findViewById(R.id.action_blockquote).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setBlockquote();
+ }
+ });
+
+ findViewById(R.id.action_insert_bullets).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setBullets();
+ }
+ });
+
+ findViewById(R.id.action_insert_numbers).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.setNumbers();
+ }
+ });
+ /**findViewById(R.id.action_insert_link).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.insertLink("https://github.com/wasabeef", "wasabeef");
+ }
+ });*/
+ /**findViewById(R.id.action_insert_image).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.insertImage("https://raw.githubusercontent.com/wasabeef/art/master/chip.jpg",
+ "dachshund", 320);
+ }
+ });*/
+ findViewById(R.id.action_insert_checkbox).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNoteEditor.insertTodo();
+ }
+ });
+
+ }
+
+ /**
+ * @method textChange
* @description 对原始文本进行处理,去除图片字符、换行符和空格字符
* @date: 1/3/2024 8:48 AM
* @author: YangYizhe
* @param oriText
* @return 处理后的文本
*/
- private String Textchange(String oriText){
- StringBuffer stringBuffer = new StringBuffer(oriText);
- int Flag1 = -1;
- int Flag2 = -1;
- do {//不计入表示图片的字符
- Flag1 = stringBuffer.indexOf("");
- if (Flag1 != -1 && Flag2 != -1) {
- stringBuffer = stringBuffer.replace(Flag1, Flag2+1, "");
+ private String textChange(String oriText) {
+ StringBuilder stringBuilder = new StringBuilder(oriText);
+ // 移除所有<>
+ removeAngleBrackets(stringBuilder);
+ // 移除换行符和空格
+ for (int i = 0; i < stringBuilder.length(); i++) {
+ char c = stringBuilder.charAt(i);
+ if (c == '\n' || c == ' ') {
+ stringBuilder.deleteCharAt(i);
+ i--;
}
- } while (Flag1 != -1 && Flag2 != -1);
+ }
+
+ return stringBuilder.toString();
+ }
+ /**
+ * @method removeAngleBrackets
+ * @description 用以辅助移除<>>
+ * @date: 1/18/2024 7:22 PM
+ * @author: YangYizhe
+ * @param
+ * @return
+ */
+ private void removeAngleBrackets(StringBuilder stringBuilder) {
+ int startIndex = stringBuilder.indexOf("<");
+ int endIndex = stringBuilder.indexOf(">");
+ if (startIndex != -1 && endIndex != -1 && startIndex < endIndex) {
+ stringBuilder.delete(startIndex, endIndex + 1);
+ removeAngleBrackets(stringBuilder);
+ }
+ }
- do {//不计入换行字符
- Flag1 = stringBuffer.indexOf("\n");
- if (Flag1 != -1){
- stringBuffer = stringBuffer.replace(Flag1, Flag1+1, "");
- }
- } while (Flag1 != -1);
- do {//不计入空格字符
- Flag1 = stringBuffer.indexOf(" ");
- if (Flag1 != -1) {
- stringBuffer = stringBuffer.replace(Flag1, Flag1+1, "");
- }
- } while (Flag1 != -1);
- return stringBuffer.toString();
- }
/**
* @method count
@@ -194,7 +438,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* @date: 1/3/2024 9:09 AM
* @author: YangYizhe
*/
- private void count() {
+ /**private void count() {
mNoteEditor.addTextChangedListener(new TextWatcher() {
int currentLength = 0;
@Override
@@ -204,7 +448,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
- currentLength = Textchange(mNoteEditor.getText().toString()).length();
+ currentLength = textChange(mNoteEditor.getText().toString()).length();
}
@Override
@@ -212,7 +456,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteHeaderHolder.textNum.setText("字数:" + currentLength);
}
});
- }
+ }*/
/**
*在 Activity 创建时进行一些初始化工作,包括设置布局、初始化状态和资源等操作
@@ -221,31 +465,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.note_edit);
- checkStoragePermissions(this);//动态申请权限
-
if (savedInstanceState == null && !initActivityState(getIntent())) {
finish();
return;
}
initResources();
-
- final ImageButton add_img_btn = (ImageButton) findViewById(R.id.add_img_btn);//根据id获取添加图片按钮
- //为点击图片按钮设置监听器
- add_img_btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Log.d(TAG, "onClick: click add image button");
- //ACTION_GET_CONTENT: 允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音)
- Intent loadImage = new Intent(Intent.ACTION_GET_CONTENT);
- //Category属性用于指定当前动作(Action)被执行的环境.
- //CATEGORY_OPENABLE; 用来指示一个ACTION_GET_CONTENT的intent
- loadImage.addCategory(Intent.CATEGORY_OPENABLE);
- loadImage.setType("image/*");
- startActivityForResult(loadImage, PHOTO_REQUEST);
- }
- });
- convertToImage();//将路径显示为图片
- count();
+ initRichEditor();
+ //count();
}
/**
@@ -266,6 +492,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
+
private boolean initActivityState(Intent intent) {
/**
* If the user specified the {@link Intent#ACTION_VIEW} but not provided with id,
@@ -306,7 +533,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
} else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
- // New note
long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
@@ -314,8 +540,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Notes.TYPE_WIDGET_INVALIDE);
int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
ResourceParser.getDefaultBgId(this));
-
- // Parse call-record note
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
if (callDate != 0 && phoneNumber != null) {
@@ -367,13 +591,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* @author: YangYizhe
*/
private void initNoteScreen() {
- mNoteEditor.setTextAppearance(this, TextAppearanceResources
- .getTexAppearanceResource(mFontSizeId));
+ mNoteEditor.setEditorFontSize(30);
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
switchToListMode(mWorkingNote.getContent());
} else {
- mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
- mNoteEditor.setSelection(mNoteEditor.getText().length());
+ mNoteEditor.setHtml(String.valueOf(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery)));
+ //mNoteEditor.setSelection(mText.length());
}
for (Integer id : sBgSelectorSelectionMap.keySet()) {
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
@@ -391,7 +614,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* is not ready
*/
showAlertHeader();
- convertToImage();//将路径转化未图片
}
/**
* @method showAlertHeader
@@ -409,7 +631,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
long time = System.currentTimeMillis();
if (time > mWorkingNote.getAlertDate()) {
mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired);
- } else {
+ }
+ else {
mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString(
mWorkingNote.getAlertDate(), time, DateUtils.MINUTE_IN_MILLIS));
}
@@ -421,12 +644,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
};
}
+
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
initActivityState(intent);
}
-
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -441,7 +664,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
}
-
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
@@ -466,9 +688,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
if (ev.getX() < x
|| ev.getX() > (x + view.getWidth())
|| ev.getY() < y
- || ev.getY() > (y + view.getHeight())) {
- return false;
- }
+ || ev.getY() > (y + view.getHeight()))
+ {
+ return false;
+ }
return true;
}
@@ -481,7 +704,18 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color);
mNoteHeaderHolder.textNum = (TextView) findViewById(R.id.text_num);
mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this);
- mNoteEditor = (EditText) findViewById(R.id.note_edit_view);
+ mNoteEditor = findViewById(R.id.note_edit_view);
+ mNoteEditor.setOnTextChangeListener(new RichEditor.OnTextChangeListener() {
+ @Override
+ public void onTextChange(String text) {
+ mText = text;
+ mNoteLength = textChange(mText).length();
+ mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(NoteEditActivity.this,
+ mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
+ | DateUtils.FORMAT_SHOW_YEAR)+"\n字符数:"+mNoteLength);
+ }
+ });
mNoteEditorPanel = findViewById(R.id.sv_note_edit);
mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector);
for (int id : sBgSelectorBtnsMap.keySet()) {
@@ -505,24 +739,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
}
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
-
- //朗读
- mTTS = new TextToSpeech(this,new TextToSpeech.OnInitListener(){
- @Override
- public void onInit(int status){
- // 判断是否转化成功
- if (status == TextToSpeech.SUCCESS){
- //默认设定语言为中文
- int result = mTTS.setLanguage(Locale.CHINESE);
- if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED){
- Toast.makeText(NoteEditActivity.this, "Language not available.", Toast.LENGTH_SHORT).show();
- }else{
- //不支持中文就将语言设置为英文
- mTTS.setLanguage(Locale.US);
- }
- }
- }
- });
}
@Override
@@ -558,6 +774,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
setResult(RESULT_OK, intent);
}
+
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_set_bg_color) {
@@ -578,8 +795,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
getWorkingText();
switchToListMode(mWorkingNote.getContent());
} else {
- mNoteEditor.setTextAppearance(this,
- TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
+ mNoteEditor.setEditorFontSize(mFontSizeId);
}
mFontSizeSelector.setVisibility(View.GONE);
}
@@ -623,7 +839,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
}
-
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (isFinishing()) {
@@ -648,7 +863,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return true;
}
-
@Override
/**
* @method onOptionsItemSelected
@@ -691,9 +905,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
setReminder();
} else if (itemId == R.id.menu_delete_remind) {
mWorkingNote.setAlertDate(0, false);
- } else if (itemId == R.id.menu_voice){
- Log.d("voiceOut","in");
- textToSpeach();
}
return true;
}
@@ -715,6 +926,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
d.show();
}
+
/**
* Share note to apps that support {@link Intent#ACTION_SEND} action
* and {@text/plain} type
@@ -878,15 +1090,15 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mEditTextList.setVisibility(View.VISIBLE);
}
/**
- * @method getHighlightQueryResult
+ * @param fullText 完整文本
+ * @param userQuery 用户查询关键词
+ * @return 带有高亮效果的 Spannable 对象
+ * @method getHighlightQueryResult
* @description 获取高亮查询结果
* @date: 12/24/2023 6:18 PM
* @author: YangYizhe
- * @param fullText 完整文本
- * @param userQuery 用户查询关键词
- * @return 带有高亮效果的 Spannable 对象
*/
- private Spannable getHighlightQueryResult(String fullText, String userQuery) {
+ private SpannableString getHighlightQueryResult(String fullText, String userQuery) {
SpannableString spannable = new SpannableString(fullText == null ? "" : fullText);
if (!TextUtils.isEmpty(userQuery)) {
mPattern = Pattern.compile(userQuery);
@@ -970,21 +1182,17 @@ public class NoteEditActivity extends Activity implements OnClickListener,
*/
public void onCheckListModeChanged(int oldMode, int newMode) {
if (newMode == TextNote.MODE_CHECK_LIST) {
- switchToListMode(mNoteEditor.getText().toString());
- //检查模式切换到列表模式
+ switchToListMode(mText.toString());
} else {
if (!getWorkingText()) {
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
""));
}
- //若是获取到文本就改变其检查标记
- mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
+ mNoteEditor.setHtml(String.valueOf(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery)));
mEditTextList.setVisibility(View.GONE);
mNoteEditor.setVisibility(View.VISIBLE);
- //修改文本编辑器的内容和可见性
}
}
-
/**
* @method getWorkingText
* @description 获取正在编辑的文本内容
@@ -993,23 +1201,26 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* @return 是否存在已打钩的选项
*/
private boolean getWorkingText() {
- boolean hasChecked = false;
- //初始化check标记
+ boolean hasChecked = false;//初始化check标记
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
- // 若模式为CHECK_LIST
+ /**
+ * 若模式为CHECK_LIST
+ * 先创建可变字符串
+ * 遍历所有子编辑框的视图
+ */
StringBuilder sb = new StringBuilder();
- //创建可变字符串
for (int i = 0; i < mEditTextList.getChildCount(); i++) {
View view = mEditTextList.getChildAt(i);
- //遍历所有子编辑框的视图
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
if (!TextUtils.isEmpty(edit.getText())) {
- //若文本不为空
+ /**
+ * 若文本不为空
+ * 该选项框已打钩
+ * 扩展字符串为已打钩并把标记置true
+ */
if (((CheckBox) view.findViewById(R.id.cb_edit_item)).isChecked()) {
- //该选项框已打钩
sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n");
hasChecked = true;
- //扩展字符串为已打钩并把标记置true
} else {
//扩展字符串添加未打钩
sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n");
@@ -1017,14 +1228,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
mWorkingNote.setWorkingText(sb.toString());//利用编辑好的字符串设置运行便签的内容
- //利用编辑好的字符串设置运行便签的内容
} else {// 若不是该模式直接用编辑器中的内容设置运行中标签的内容
- mWorkingNote.setWorkingText(mNoteEditor.getText().toString());
- //若是获取到文本就改变其检查标记
- mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
- mEditTextList.setVisibility(View.GONE);
- mNoteEditor.setVisibility(View.VISIBLE);
- //修改文本编辑器的内容和可见性
+ mWorkingNote.setWorkingText(mText.toString());
}
return hasChecked;
}
@@ -1038,11 +1243,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private boolean saveNote() {
getWorkingText();
boolean saved = mWorkingNote.saveNote();
- //如果便签内容为空,则删除
- if (TextUtils.isEmpty(mWorkingNote.getContent())) {
- deleteCurrentNote();//删除当前便签
- saved = false; // 标记为未保存
- }
//运行 getWorkingText()之后保存
if (saved) {
/**
@@ -1098,7 +1298,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
showToast(R.string.error_note_empty_for_send_to_desktop);
}
}
-
/**
* @method makeShortcutIconTitle
* @description 生成快捷方式图标标题
@@ -1113,239 +1312,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0,
SHORTCUT_ICON_TITLE_MAX_LEN) : content;
}
-
private void showToast(int resId) {
showToast(resId, Toast.LENGTH_SHORT);
}
-
private void showToast(int resId, int duration) {
Toast.makeText(this, resId, duration).show();
}
-
- /**
- * @method convertToImage
- * @description: 路径字符串格式 转换为 图片image格式
- * @date: 2024/1/3 19:19
- * @author: WuShuxian
- * @param: void
- * @return: void
- */
- private void convertToImage() {
- NoteEditText noteEditText = (NoteEditText) findViewById(R.id.note_edit_view); //获取当前的edit
- Editable editable = noteEditText.getText();//1.获取text
- String noteText = editable.toString(); //2.将note内容转换为字符串
- int length = editable.length(); //内容的长度
- //3.截取img片段 [local]+uri+[/local],提取uri。算法效率有待改善可以考虑KMP
- for(int i = 0; i < length; i++) {
- for(int j = i; j < length; j++) {
- String img_fragment = noteText.substring(i, j+1); //img_fragment:关于图片路径的片段
- if(img_fragment.length() > 15 && img_fragment.endsWith("[/local]") &&
- img_fragment.startsWith("[local]")){
- int limit = 7; //[local]为7个字符
- int len = img_fragment.length()-15;//[local][/local]共15个字符,剩下的为真正的path长度
- String path = img_fragment.substring(limit,limit+len);//获取到了图片路径从[local]之后的len个字符就是path
- Bitmap bitmap = null;
- Log.d(TAG, "图片的路径是:"+path);
- try {
- bitmap = BitmapFactory.decodeFile(path);//将图片路径解码为图片格式
- } catch (Exception e) {
- e.printStackTrace();
- }
- //若图片存在
- if(bitmap!=null){
- Log.d(TAG, "图片不为null");
- ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
- String ss = "[local]" + path + "[/local]";
- SpannableString spannableString = new SpannableString(ss);//4.创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
-
- spannableString.setSpan(imageSpan, 0, ss.length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);//5.将指定的标记对象附加到文本的开始...结束范围
- Log.d(TAG, "Create spannable string success!");
- Editable edit_text = noteEditText.getEditableText();
- edit_text.delete(i,i+len+15); //6.删掉图片路径的文字
- edit_text.insert(i, spannableString); //7.在路径的起始位置插入图片
- }
- }
- }
- }
- }
-
- /**
- * @method onActivityResult
- * @description: 插入图片时:重写onActivityResult()来处理返回的数据,点击插入图片返回后执行
- * @date: 2024/1/3 19:20
- * @author: WuShuxian
- * @param:
- * @return: void
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
- super.onActivityResult(requestCode, resultCode, intent);
- ContentResolver resolver = getContentResolver();
- switch (requestCode) {
- case PHOTO_REQUEST:
- Uri originalUri = intent.getData(); //1.获得图片的真实路径
- Bitmap bitmap = null;
- try {
- bitmap = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));//2.解码图片
- } catch (FileNotFoundException e) {
- Log.d(TAG, "onActivityResult: get file_exception");
- e.printStackTrace();
- }
- //3.根据Bitmap对象创建ImageSpan对象
- if(bitmap != null){
- Log.d(TAG, "onActivityResult: bitmap is not null");
- ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
- String path = getPath(this,originalUri);
- String img_fragment= "[local]" + path + "[/local]";//4.使用[local][/local]将path括起来,用于之后方便识别图片路径在note中的位置
- SpannableString spannableString = new SpannableString(img_fragment);//创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
- spannableString.setSpan(imageSpan, 0,
- img_fragment.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- NoteEditText e = (NoteEditText) findViewById(R.id.note_edit_view);//5.将选择的图片追加到EditText中光标所在位置
- int index = e.getSelectionStart(); //获取光标所在位置
- Log.d(TAG, "Index是: " + index);
- Editable edit_text = e.getEditableText();
- edit_text.insert(index, spannableString); //将图片插入到光标所在位置
-
- mWorkingNote.setWorkingText(e.getText().toString());
- //6.把改动提交到数据库中,两个数据库表都要改的
- ContentResolver contentResolver = getContentResolver();
- ContentValues contentValues = new ContentValues();
- final long id = mWorkingNote.getNoteId();
- contentValues.put("snippet",mWorkingNote.getContent());
- contentResolver.update(Uri.parse("content://micode_notes/note"),
- contentValues,"_id=?",new String[]{""+id});
- ContentValues contentValues1 = new ContentValues();
- contentValues1.put("content",mWorkingNote.getContent());
- contentResolver.update(Uri.parse("content://micode_notes/data"),
- contentValues1,"mime_type=? and note_id=?",
- new String[]{"vnd.android.cursor.item/text_note",""+id});
-
- }else{
- Toast.makeText(NoteEditActivity.this, "获取图片失败", Toast.LENGTH_SHORT).show();
- }
- break;
- default:
- break;
- }
- }
-
- /**
- * @method getPath
- * @description: 获取文件的real path
- * @date: 2024/1/3 19:22
- * @author: WuShuxian
- * @param:
- * @return:
- */
- public String getPath(final Context context, final Uri uri) {
-
- final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
-
- // DocumentProvider
- if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
- if (isMediaDocument(uri)) {
- final String docId = DocumentsContract.getDocumentId(uri);
- final String[] split = docId.split(":");
- final String type = split[0];
-
- Uri contentUri = null;
- if ("image".equals(type)) {
- contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
- }
-
- final String selection = "_id=?";
- final String[] selectionArgs = new String[]{split[1]};
-
- return getDataColumn(context, contentUri, selection, selectionArgs);
- }
- }
- // Media
- else if ("content".equalsIgnoreCase(uri.getScheme())) {
- return getDataColumn(context, uri, null, null);
- }
- // File
- else if ("file".equalsIgnoreCase(uri.getScheme())) {
- return uri.getPath();
- }
- return null;
- }
-
- /**
- * @method isMediaDocument
- * @description: 判断是否为媒体文件
- * @date: 2024/1/3 19:23
- * @author: WuShuxian
- * @param: uri
- * @return:
- */
- public boolean isMediaDocument(Uri uri) {
- return "com.android.providers.media.documents".equals(uri.getAuthority());
- }
-
- /**
- * @method getDataColumn
- * @description: 获取数据列_获取此 Uri 的数据列的值。这对MediaStore Uris 和其他基于文件的 ContentProvider。
- * @date: 2024/1/3 19:23
- * @author: WuShuxian
- * @param:
- * @return:
- */
- public String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
-
- Cursor cursor = null;
- final String column = "_data";
- final String[] projection = {column};
-
- try {
- cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
- if (cursor != null && cursor.moveToFirst()) {
- final int column_index = cursor.getColumnIndexOrThrow(column);
- return cursor.getString(column_index);
- }
- } finally {
- if (cursor != null)
- cursor.close();
- }
- return null;
- }
-
- /**
- * @method checkStoragePermissions
- * @description: 用于动态申请权限
- * @date: 2024/1/6 8:58
- * @author: WuShuxian
- * @param: activity
- * @return: void
- */
- public static void checkStoragePermissions(Activity activity){
- try{
- //监测是否有写/读的权限
- int permission= ActivityCompat.checkSelfPermission(activity,
- "android.permission.WRITE_EXTERNAL_STORAGE");
- int permission1= ActivityCompat.checkSelfPermission(activity,
- "android.permission.READ_EXTERNAL_STORAGE");
- if(permission != PackageManager.PERMISSION_GRANTED){
- //没有写的权限,去申请写的权限,或弹出对话框
- ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
- }
- if(permission1 != PackageManager.PERMISSION_GRANTED){
- //没有读的权限,去申请读的权限,或弹出对话框
- ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
- }
-
- }catch (Exception e){
- e.printStackTrace();
- }
- }
-
- /**
- * @method textToSpeach
- * @description: 朗读功能
- * @date: 2024/1/16 20:21
- * @author: WuShuxian
- */
- private void textToSpeach(){
- mTTS.speak(mNoteEditor.getText().toString(),TextToSpeech.QUEUE_FLUSH,null);
- }
}
diff --git a/src/main/java/net/micode/notes/ui/NoteEditText.java b/src/main/java/net/micode/notes/ui/NoteEditText.java
index c935358..d29d3d2 100644
--- a/src/main/java/net/micode/notes/ui/NoteEditText.java
+++ b/src/main/java/net/micode/notes/ui/NoteEditText.java
@@ -46,19 +46,12 @@ import java.util.Map;
* @Version: 1.0
*/
public class NoteEditText extends EditText {
- //常量标识
private static final String TAG = "NoteEditText";
- //声明整型变量,文本索引
private int mIndex;
- //声明整型变量
private int mSelectionStartBeforeDelete;
-
- //声明字符串常量,标志电话、网址、邮件
private static final String SCHEME_TEL = "tel:" ;
private static final String SCHEME_HTTP = "http:" ;
private static final String SCHEME_EMAIL = "mailto:" ;
-
- //设置映射,将文本内容(电话、网址、邮件)做链接处理
private static final Map sSchemaActionResMap = new HashMap();
static {
sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel);
@@ -103,7 +96,9 @@ public class NoteEditText extends EditText {
mIndex = 0;
}
- //设置索引号
+ /**
+ * 设置索引号
+ */
public void setIndex(int index) {
mIndex = index;
}
@@ -129,15 +124,15 @@ public class NoteEditText extends EditText {
// TODO Auto-generated constructor stub
}
+ @Override
/**
* @method onTouchEvent
* @description 处理触摸事件,根据触摸点的位置设置光标的位置
- * @date: 12/21/2023 12:41 AM
+ * @date: 12/24/2023 6:07 PM
* @author: YangYizhe
- * @param
- * @return
+ * @param [event]
+ * @return boolean
*/
- @Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
@@ -240,15 +235,15 @@ public class NoteEditText extends EditText {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
+ @Override
/**
* @method onCreateContextMenu
- * @description
- * @date: 12/21/2023 12:39 AM
+ * @description 创建上下文菜单
+ * @date: 12/24/2023 6:08 PM
* @author: YangYizhe
- * @param
- * @return
+ * @param [menu]
+ * @return void
*/
- @Override
protected void onCreateContextMenu(ContextMenu menu) {
if (getText() instanceof Spanned) {
int selStart = getSelectionStart();
diff --git a/src/main/java/net/micode/notes/ui/NoteItemData.java b/src/main/java/net/micode/notes/ui/NoteItemData.java
index ad1b9ca..ca9bcbe 100644
--- a/src/main/java/net/micode/notes/ui/NoteItemData.java
+++ b/src/main/java/net/micode/notes/ui/NoteItemData.java
@@ -25,7 +25,14 @@ import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils;
-
+/**
+ * @Package: net.micode.notes.ui
+ * @ClassName: NoteItemData
+ * @Description: 这个类用于封装笔记列表项的数据,包括笔记的各种属性和状态。
+ * @Author: YangYizhe
+ * @CreateDate: 12/24/2023 6:00 PM
+ * @Version: 1.0
+ */
public class NoteItemData {
// 用于定义查询操作中要返回的列
static final String [] PROJECTION = new String [] {
@@ -76,7 +83,16 @@ public class NoteItemData {
private boolean mIsOnlyOneItem;
private boolean mIsOneNoteFollowingFolder;
private boolean mIsMultiNotesFollowingFolder;
-
+ /**
+ * @method NoteItemData
+ * @description
+ * 创建一个笔记项数据对象
+ * 通过传入的游标和上下文对象初始化笔记项数据
+ * @date: 12/24/2023 6:00 PM
+ * @author: YangYizhe
+ * @param context 上下文对象
+ * @param cursor 游标对象,用于获取数据库中的笔记数据
+ */
public NoteItemData(Context context, Cursor cursor) {
mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
@@ -109,7 +125,13 @@ public class NoteItemData {
}
checkPostion(cursor);
}
-
+ /**
+ * @method checkPostion
+ * @description 检查当前笔记项在游标中的位置,并设置相应的标志位
+ * @date: 12/24/2023 6:00 PM
+ * @author: YangYizhe
+ * @param cursor 游标对象
+ */
private void checkPostion(Cursor cursor) {
mIsLastItem = cursor.isLast() ? true : false;
mIsFirstItem = cursor.isFirst() ? true : false;
@@ -134,59 +156,87 @@ public class NoteItemData {
}
}
}
-
+ /**
+ * 判断是否只有一个笔记项跟随在文件夹后面
+ */
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;
}
-
+ /**
+ * 获取笔记项的ID
+ */
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;
}
-
+ /**
+ * 获取笔记项的背景颜色ID
+ */
public int getBgColorId() {
return mBgColorId;
}
-
+ /**
+ * 获取笔记项的父文件夹ID
+ */
public long getParentId() {
return mParentId;
}
-
+ /**
+ * 获取笔记项的子笔记数量
+ */
public int getNotesCount() {
return mNotesCount;
}
diff --git a/src/main/res/drawable-hdpi/bg.png b/src/main/res/drawable-hdpi/bg.png
new file mode 100644
index 0000000..edd0fa3
Binary files /dev/null and b/src/main/res/drawable-hdpi/bg.png differ
diff --git a/src/main/res/drawable-hdpi/bg_color.png b/src/main/res/drawable-hdpi/bg_color.png
new file mode 100644
index 0000000..c6bd0ef
Binary files /dev/null and b/src/main/res/drawable-hdpi/bg_color.png differ
diff --git a/src/main/res/drawable-hdpi/blockquote.png b/src/main/res/drawable-hdpi/blockquote.png
new file mode 100644
index 0000000..638a40c
Binary files /dev/null and b/src/main/res/drawable-hdpi/blockquote.png differ
diff --git a/src/main/res/drawable-hdpi/bold.png b/src/main/res/drawable-hdpi/bold.png
new file mode 100644
index 0000000..7184e00
Binary files /dev/null and b/src/main/res/drawable-hdpi/bold.png differ
diff --git a/src/main/res/drawable-hdpi/bullets.png b/src/main/res/drawable-hdpi/bullets.png
new file mode 100644
index 0000000..91a0fc0
Binary files /dev/null and b/src/main/res/drawable-hdpi/bullets.png differ
diff --git a/src/main/res/drawable-hdpi/check.png b/src/main/res/drawable-hdpi/check.png
new file mode 100644
index 0000000..59a56ae
Binary files /dev/null and b/src/main/res/drawable-hdpi/check.png differ
diff --git a/src/main/res/drawable-hdpi/h1.png b/src/main/res/drawable-hdpi/h1.png
new file mode 100644
index 0000000..774786c
Binary files /dev/null and b/src/main/res/drawable-hdpi/h1.png differ
diff --git a/src/main/res/drawable-hdpi/h2.png b/src/main/res/drawable-hdpi/h2.png
new file mode 100644
index 0000000..3715b7a
Binary files /dev/null and b/src/main/res/drawable-hdpi/h2.png differ
diff --git a/src/main/res/drawable-hdpi/h3.png b/src/main/res/drawable-hdpi/h3.png
new file mode 100644
index 0000000..4a8915c
Binary files /dev/null and b/src/main/res/drawable-hdpi/h3.png differ
diff --git a/src/main/res/drawable-hdpi/h4.png b/src/main/res/drawable-hdpi/h4.png
new file mode 100644
index 0000000..6781447
Binary files /dev/null and b/src/main/res/drawable-hdpi/h4.png differ
diff --git a/src/main/res/drawable-hdpi/h5.png b/src/main/res/drawable-hdpi/h5.png
new file mode 100644
index 0000000..682a91d
Binary files /dev/null and b/src/main/res/drawable-hdpi/h5.png differ
diff --git a/src/main/res/drawable-hdpi/h6.png b/src/main/res/drawable-hdpi/h6.png
new file mode 100644
index 0000000..dee7ff4
Binary files /dev/null and b/src/main/res/drawable-hdpi/h6.png differ
diff --git a/src/main/res/drawable-hdpi/html_edit.png b/src/main/res/drawable-hdpi/html_edit.png
new file mode 100644
index 0000000..3bbdedb
Binary files /dev/null and b/src/main/res/drawable-hdpi/html_edit.png differ
diff --git a/src/main/res/drawable-hdpi/image.png b/src/main/res/drawable-hdpi/image.png
new file mode 100644
index 0000000..752fdf1
Binary files /dev/null and b/src/main/res/drawable-hdpi/image.png differ
diff --git a/src/main/res/drawable-hdpi/indent.png b/src/main/res/drawable-hdpi/indent.png
new file mode 100644
index 0000000..77efb71
Binary files /dev/null and b/src/main/res/drawable-hdpi/indent.png differ
diff --git a/src/main/res/drawable-hdpi/insert_image.png b/src/main/res/drawable-hdpi/insert_image.png
new file mode 100644
index 0000000..3c88842
Binary files /dev/null and b/src/main/res/drawable-hdpi/insert_image.png differ
diff --git a/src/main/res/drawable-hdpi/insert_link.png b/src/main/res/drawable-hdpi/insert_link.png
new file mode 100644
index 0000000..e86e04c
Binary files /dev/null and b/src/main/res/drawable-hdpi/insert_link.png differ
diff --git a/src/main/res/drawable-hdpi/italic.png b/src/main/res/drawable-hdpi/italic.png
new file mode 100644
index 0000000..f1a1363
Binary files /dev/null and b/src/main/res/drawable-hdpi/italic.png differ
diff --git a/src/main/res/drawable-hdpi/justify_center.png b/src/main/res/drawable-hdpi/justify_center.png
new file mode 100644
index 0000000..450ce24
Binary files /dev/null and b/src/main/res/drawable-hdpi/justify_center.png differ
diff --git a/src/main/res/drawable-hdpi/justify_left.png b/src/main/res/drawable-hdpi/justify_left.png
new file mode 100644
index 0000000..5125d0e
Binary files /dev/null and b/src/main/res/drawable-hdpi/justify_left.png differ
diff --git a/src/main/res/drawable-hdpi/justify_right.png b/src/main/res/drawable-hdpi/justify_right.png
new file mode 100644
index 0000000..47be92b
Binary files /dev/null and b/src/main/res/drawable-hdpi/justify_right.png differ
diff --git a/src/main/res/drawable-hdpi/music.png b/src/main/res/drawable-hdpi/music.png
new file mode 100644
index 0000000..88ee22d
Binary files /dev/null and b/src/main/res/drawable-hdpi/music.png differ
diff --git a/src/main/res/drawable-hdpi/numbers.png b/src/main/res/drawable-hdpi/numbers.png
new file mode 100644
index 0000000..44d388e
Binary files /dev/null and b/src/main/res/drawable-hdpi/numbers.png differ
diff --git a/src/main/res/drawable-hdpi/outdent.png b/src/main/res/drawable-hdpi/outdent.png
new file mode 100644
index 0000000..3a953ce
Binary files /dev/null and b/src/main/res/drawable-hdpi/outdent.png differ
diff --git a/src/main/res/drawable-hdpi/redo.png b/src/main/res/drawable-hdpi/redo.png
new file mode 100644
index 0000000..eb9bf47
Binary files /dev/null and b/src/main/res/drawable-hdpi/redo.png differ
diff --git a/src/main/res/drawable-hdpi/strikethrough.png b/src/main/res/drawable-hdpi/strikethrough.png
new file mode 100644
index 0000000..7f3e464
Binary files /dev/null and b/src/main/res/drawable-hdpi/strikethrough.png differ
diff --git a/src/main/res/drawable-hdpi/subscript.png b/src/main/res/drawable-hdpi/subscript.png
new file mode 100644
index 0000000..34d4c57
Binary files /dev/null and b/src/main/res/drawable-hdpi/subscript.png differ
diff --git a/src/main/res/drawable-hdpi/superscript.png b/src/main/res/drawable-hdpi/superscript.png
new file mode 100644
index 0000000..0ad3576
Binary files /dev/null and b/src/main/res/drawable-hdpi/superscript.png differ
diff --git a/src/main/res/drawable-hdpi/txt_color.png b/src/main/res/drawable-hdpi/txt_color.png
new file mode 100644
index 0000000..7d0e2eb
Binary files /dev/null and b/src/main/res/drawable-hdpi/txt_color.png differ
diff --git a/src/main/res/drawable-hdpi/underline.png b/src/main/res/drawable-hdpi/underline.png
new file mode 100644
index 0000000..24d55a4
Binary files /dev/null and b/src/main/res/drawable-hdpi/underline.png differ
diff --git a/src/main/res/drawable-hdpi/undo.png b/src/main/res/drawable-hdpi/undo.png
new file mode 100644
index 0000000..9fa457a
Binary files /dev/null and b/src/main/res/drawable-hdpi/undo.png differ
diff --git a/src/main/res/drawable-hdpi/video.png b/src/main/res/drawable-hdpi/video.png
new file mode 100644
index 0000000..bbbc39e
Binary files /dev/null and b/src/main/res/drawable-hdpi/video.png differ
diff --git a/src/main/res/drawable-hdpi/youtube.png b/src/main/res/drawable-hdpi/youtube.png
new file mode 100644
index 0000000..0f35775
Binary files /dev/null and b/src/main/res/drawable-hdpi/youtube.png differ
diff --git a/src/main/res/layout/note_edit.xml b/src/main/res/layout/note_edit.xml
index 49a63e3..b8ecd5a 100644
--- a/src/main/res/layout/note_edit.xml
+++ b/src/main/res/layout/note_edit.xml
@@ -30,6 +30,7 @@
android:id="@+id/note_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
+
+
+
+ android:scrollbars="none">
-
+ android:textAppearance="@style/TextAppearancePrimaryItem" />
@@ -387,23 +395,249 @@
+ android:focusable="false"
+ android:src="@drawable/selected"
+ android:visibility="gone" />
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/values/ids.xml b/src/main/res/values/ids.xml
new file mode 100644
index 0000000..efc0262
--- /dev/null
+++ b/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 7dfa4a5..469b04c 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -15,8 +15,7 @@
limitations under the License.
-->
-
+
Notes
Notes 2x2
Notes 4x4
@@ -40,7 +39,6 @@
notes_%s.txt
(%d)
- Add picture
New Folder
Export text
Sync
@@ -140,58 +138,11 @@
SplashActivity
EAZZY\nNOTE
-
- - %1$s result for \"%2$s\"
-
- - %1$s results for \"%2$s\"
-
-
-
-
-
-
-
-
-
-
-
-
-
- %1$s result for \"%2$s\"
- %1$s results for \"%2$s\"
+
+
diff --git a/src/main/res/values/styles.xml b/src/main/res/values/styles.xml
index 201293d..db56d26 100644
--- a/src/main/res/values/styles.xml
+++ b/src/main/res/values/styles.xml
@@ -16,18 +16,22 @@
-->
+
+
+
+
-
-
-