修改了部分代码文件

修改了部分代码文件的注释以及修复了潜在的漏洞
pull/37/head
p5vjqsb6e 3 months ago
commit 0d74be0a52

@ -0,0 +1,2 @@
#Wed Jan 28 09:46:21 CST 2026
gradle.version=9.2.0

File diff suppressed because one or more lines are too long

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) <!--
Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
@ -9,44 +10,83 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
AndroidManifest.xml - 应用清单文件
定义了应用的基本信息、权限、组件Activity、Service、Receiver、Provider等配置
-->
<!--
Manifest根元素
package: 应用的包名,用于唯一标识应用
versionCode: 版本代码,用于版本比较(内部版本号)
versionName: 版本名称,显示给用户的版本号
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.micode.notes" package="net.micode.notes"
android:versionCode="1" android:versionCode="1"
android:versionName="0.1" > android:versionName="0.1" >
<!-- 已移除package属性已注释minSdkVersion可选删除 -->
<!-- <uses-sdk android:minSdkVersion="14" /> --> <!-- ==================== 权限声明区域 ==================== -->
<!-- 写入外部存储权限用于导出笔记到SD卡、保存图片等 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 读取外部存储权限:用于读取图片、导入文件等 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 安装快捷方式权限:用于在桌面创建笔记快捷方式 -->
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<!-- 网络访问权限用于Google Tasks同步、在线语音识别等功能 -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- 读取联系人权限:用于在笔记中识别电话号码并显示联系人名称 -->
<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- 管理账户权限用于管理Google账户进行Google Tasks同步 -->
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<!-- 账户认证权限用于Google账户认证 -->
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" /> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<!-- 获取账户列表权限用于获取系统中的Google账户列表 -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- 使用凭证权限用于使用Google账户凭证进行同步 -->
<uses-permission android:name="android.permission.USE_CREDENTIALS" /> <uses-permission android:name="android.permission.USE_CREDENTIALS" />
<!-- 接收开机完成广播权限:用于在系统启动后重新设置闹钟提醒 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- 录音权限:用于语音识别功能,记录音频输入 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 语音识别权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- 访问网络状态权限用于检查网络连接状态Android 6.0+需要) -->
<!-- 网络权限(用于在线语音识别) -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 存储权限(用于保存语音识别结果) -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- Android 6.0+ 需要的权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 从相册选择图片需要 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <!-- 读取媒体图片权限Android 13+API 33+)需要,用于从相册选择图片 -->
<!-- 如果Android 13+,可能需要读取媒体文件 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<!-- ==================== 应用配置区域 ==================== -->
<!--
Application元素定义应用的全局配置
icon: 应用图标
label: 应用名称(显示在应用列表中)
-->
<application <application
android:icon="@drawable/icon_app" android:icon="@drawable/icon_app"
android:label="@string/app_name" > android:label="@string/app_name" >
<!-- ==================== Activity组件 ==================== -->
<!--
笔记列表Activity - 应用主界面
功能:显示笔记列表、文件夹管理、搜索等
configChanges: 配置变化时不重启Activity键盘、屏幕方向、屏幕尺寸
launchMode: singleTop - 如果Activity已在栈顶则复用实例
uiOptions: 窄屏时分割操作栏
windowSoftInputMode: adjustPan - 软键盘弹出时平移窗口
exported: true - 允许其他应用启动此Activity
-->
<activity <activity
android:name=".ui.NotesListActivity" android:name=".ui.NotesListActivity"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
@ -55,35 +95,44 @@
android:theme="@style/NoteTheme" android:theme="@style/NoteTheme"
android:uiOptions="splitActionBarWhenNarrow" android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="adjustPan" android:windowSoftInputMode="adjustPan"
android:exported="true" > <!-- 新增 --> android:exported="true" >
<!-- 主启动器Intent过滤器应用入口显示在应用列表中 -->
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<!-- 搜索Intent过滤器支持系统搜索功能 -->
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEARCH" /> <action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
<!-- 搜索配置元数据:指定搜索配置文件 -->
<meta-data <meta-data
android:name="android.app.searchable" android:name="android.app.searchable"
android:resource="@xml/searchable" /> android:resource="@xml/searchable" />
</activity> </activity>
<!--
笔记编辑Activity
功能:创建和编辑笔记内容
configChanges: 配置变化时不重启Activity
launchMode: singleTop - 如果Activity已在栈顶则复用实例
exported: true - 允许其他应用启动此Activity
-->
<activity <activity
android:name=".ui.NoteEditActivity" android:name=".ui.NoteEditActivity"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/NoteTheme" android:theme="@style/NoteTheme"
android:exported="true"> android:exported="true">
<!-- 查看笔记Intent过滤器支持查看文本笔记和通话记录笔记 -->
<intent-filter > <intent-filter >
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/text_note" /> <data android:mimeType="vnd.android.cursor.item/text_note" />
<data android:mimeType="vnd.android.cursor.item/call_note" /> <data android:mimeType="vnd.android.cursor.item/call_note" />
</intent-filter > </intent-filter >
<!-- 插入或编辑笔记Intent过滤器支持创建或编辑笔记 -->
<intent-filter > <intent-filter >
<action android:name="android.intent.action.INSERT_OR_EDIT" /> <action android:name="android.intent.action.INSERT_OR_EDIT" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
@ -93,55 +142,98 @@
</activity> </activity>
<!-- ==================== ContentProvider组件 ==================== -->
<!--
笔记数据提供者
功能:提供笔记数据的访问接口,支持其他应用访问笔记数据
authorities: 内容提供者的唯一标识符
multiprocess: true - 允许在多个进程中运行
-->
<provider <provider
android:name="net.micode.notes.data.NotesProvider" android:name="net.micode.notes.data.NotesProvider"
android:authorities="micode_notes" android:authorities="micode_notes"
android:multiprocess="true" /> android:multiprocess="true" />
<!-- ==================== BroadcastReceiver组件 ==================== -->
<!--
2x2尺寸桌面小部件提供者
功能提供2x2尺寸的桌面小部件显示笔记内容
exported: true - 允许系统启动此Receiver
-->
<receiver <receiver
android:name=".widget.NoteWidgetProvider_2x" android:name=".widget.NoteWidgetProvider_2x"
android:label="@string/app_widget2x2" android:label="@string/app_widget2x2"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<!-- 小部件更新动作:当需要更新小部件时触发 -->
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<!-- 小部件删除动作:当小部件被删除时触发 -->
<action android:name="android.appwidget.action.APPWIDGET_DELETED" /> <action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<!-- 隐私模式变化动作:当隐私模式改变时触发 -->
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED" /> <action android:name="android.intent.action.PRIVACY_MODE_CHANGED" />
</intent-filter> </intent-filter>
<!-- 小部件配置元数据:指定小部件的配置文件 -->
<meta-data <meta-data
android:name="android.appwidget.provider" android:name="android.appwidget.provider"
android:resource="@xml/widget_2x_info" /> android:resource="@xml/widget_2x_info" />
</receiver> </receiver>
<!--
4x4尺寸桌面小部件提供者
功能提供4x4尺寸的桌面小部件显示更多笔记内容
exported: true - 允许系统启动此Receiver
-->
<receiver <receiver
android:name=".widget.NoteWidgetProvider_4x" android:name=".widget.NoteWidgetProvider_4x"
android:label="@string/app_widget4x4" android:label="@string/app_widget4x4"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<!-- 小部件更新动作 -->
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<!-- 小部件删除动作 -->
<action android:name="android.appwidget.action.APPWIDGET_DELETED" /> <action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<!-- 隐私模式变化动作 -->
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED" /> <action android:name="android.intent.action.PRIVACY_MODE_CHANGED" />
</intent-filter> </intent-filter>
<!-- 小部件配置元数据 -->
<meta-data <meta-data
android:name="android.appwidget.provider" android:name="android.appwidget.provider"
android:resource="@xml/widget_4x_info" /> android:resource="@xml/widget_4x_info" />
</receiver> </receiver>
<!--
闹钟初始化接收器
功能:在系统启动完成后重新设置所有笔记的闹钟提醒
exported: true - 允许系统启动此Receiver
-->
<receiver android:name=".ui.AlarmInitReceiver" <receiver android:name=".ui.AlarmInitReceiver"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<!-- 开机完成广播:系统启动完成后触发 -->
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<!--
闹钟提醒接收器
功能:接收闹钟提醒广播,启动提醒界面
process: :remote - 在独立进程中运行,避免影响主进程
-->
<receiver <receiver
android:name="net.micode.notes.ui.AlarmReceiver" android:name="net.micode.notes.ui.AlarmReceiver"
android:process=":remote" > android:process=":remote" >
</receiver> </receiver>
<!-- ==================== 其他Activity组件 ==================== -->
<!--
闹钟提醒Activity
功能:显示笔记提醒对话框,播放提醒声音
launchMode: singleInstance - 独立任务栈,确保只有一个实例
theme: 使用壁纸主题,无标题栏
-->
<activity <activity
android:name=".ui.AlarmAlertActivity" android:name=".ui.AlarmAlertActivity"
android:label="@string/app_name" android:label="@string/app_name"
@ -149,14 +241,25 @@
android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar" > android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar" >
</activity> </activity>
<!--
设置Activity
功能:应用设置界面,管理同步账户、背景颜色等偏好设置
launchMode: singleTop - 如果Activity已在栈顶则复用实例
theme: 使用浅色主题
-->
<activity <activity
android:name="net.micode.notes.ui.NotesPreferenceActivity" android:name="net.micode.notes.ui.NotesPreferenceActivity"
android:label="@string/preferences_title" android:label="@string/preferences_title"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@android:style/Theme.Holo.Light" > android:theme="@android:style/Theme.Holo.Light" >
</activity> </activity>
<!--
回收站Activity
功能:显示和管理已删除的便签,支持恢复和彻底删除
launchMode: singleTop - 如果Activity已在栈顶则复用实例
exported: true - 允许其他应用启动此Activity
-->
<activity <activity
android:name=".ui.TrashActivity" android:name=".ui.TrashActivity"
android:label="@string/menu_trash" android:label="@string/menu_trash"
@ -164,6 +267,12 @@
android:theme="@style/NoteTheme" android:theme="@style/NoteTheme"
android:exported="true" > android:exported="true" >
</activity> </activity>
<!--
密码输入Activity
功能:输入加密便签的密码,验证后跳转到编辑界面
exported: false - 不允许其他应用启动,仅内部使用
-->
<activity <activity
android:name=".ui.PasswordInputActivity" android:name=".ui.PasswordInputActivity"
android:label="@string/password_input_title" android:label="@string/password_input_title"
@ -171,11 +280,24 @@
android:exported="false" > android:exported="false" >
</activity> </activity>
<!-- ==================== Service组件 ==================== -->
<!--
Google Tasks同步服务
功能在后台执行Google Tasks同步操作
exported: false - 不允许其他应用启动,仅内部使用
-->
<service <service
android:name="net.micode.notes.gtask.remote.GTaskSyncService" android:name="net.micode.notes.gtask.remote.GTaskSyncService"
android:exported="false" > android:exported="false" >
</service> </service>
<!-- ==================== 应用元数据 ==================== -->
<!--
默认搜索Activity配置
功能指定应用的默认搜索Activity为NotesListActivity
-->
<meta-data <meta-data
android:name="android.app.default_searchable" android:name="android.app.default_searchable"
android:value=".ui.NotesListActivity" /> android:value=".ui.NotesListActivity" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) <!--
Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -12,7 +13,11 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
密码输入界面布局文件
用于显示密码输入界面,包含标题、密码输入框和操作按钮
--> -->
<!-- 根布局:垂直方向的线性布局,内容居中显示 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -20,6 +25,7 @@
android:padding="16dp" android:padding="16dp"
android:gravity="center"> android:gravity="center">
<!-- 标题文本视图:显示"请输入密码"标题 -->
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -28,6 +34,7 @@
android:textStyle="bold" android:textStyle="bold"
android:layout_marginBottom="24dp" /> android:layout_marginBottom="24dp" />
<!-- 密码输入框:用于输入加密便签的密码,输入类型为密码模式(隐藏输入内容) -->
<EditText <EditText
android:id="@+id/et_password" android:id="@+id/et_password"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -36,12 +43,14 @@
android:inputType="textPassword" android:inputType="textPassword"
android:layout_marginBottom="16dp" /> android:layout_marginBottom="16dp" />
<!-- 按钮容器:水平方向的线性布局,按钮右对齐 -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="end"> android:gravity="end">
<!-- 返回按钮:点击后关闭当前界面,返回上一界面 -->
<Button <Button
android:id="@+id/btn_return" android:id="@+id/btn_return"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -49,6 +58,7 @@
android:text="@string/return_button" android:text="@string/return_button"
android:layout_marginEnd="8dp" /> android:layout_marginEnd="8dp" />
<!-- 确认按钮:点击后验证密码,密码正确则跳转到便签编辑界面 -->
<Button <Button
android:id="@+id/btn_confirm" android:id="@+id/btn_confirm"
android:layout_width="wrap_content" android:layout_width="wrap_content"

@ -118,9 +118,6 @@ public class ResourceParser {
* @return ID * @return ID
*/ */
public static int getNoteBgResource(int id) { public static int getNoteBgResource(int id) {
if (id < 0 || id >= BG_EDIT_RESOURCES.length) {
return BG_EDIT_RESOURCES[BG_DEFAULT_COLOR];
}
return BG_EDIT_RESOURCES[id]; return BG_EDIT_RESOURCES[id];
} }
@ -130,9 +127,6 @@ public class ResourceParser {
* @return ID * @return ID
*/ */
public static int getNoteTitleBgResource(int id) { public static int getNoteTitleBgResource(int id) {
if (id < 0 || id >= BG_EDIT_TITLE_RESOURCES.length) {
return BG_EDIT_TITLE_RESOURCES[BG_DEFAULT_COLOR];
}
return BG_EDIT_TITLE_RESOURCES[id]; return BG_EDIT_TITLE_RESOURCES[id];
} }
} }
@ -211,9 +205,6 @@ public class ResourceParser {
* @return ID * @return ID
*/ */
public static int getNoteBgFirstRes(int id) { public static int getNoteBgFirstRes(int id) {
if (id < 0 || id >= BG_FIRST_RESOURCES.length) {
return BG_FIRST_RESOURCES[BG_DEFAULT_COLOR];
}
return BG_FIRST_RESOURCES[id]; return BG_FIRST_RESOURCES[id];
} }
@ -223,9 +214,6 @@ public class ResourceParser {
* @return ID * @return ID
*/ */
public static int getNoteBgLastRes(int id) { public static int getNoteBgLastRes(int id) {
if (id < 0 || id >= BG_LAST_RESOURCES.length) {
return BG_LAST_RESOURCES[BG_DEFAULT_COLOR];
}
return BG_LAST_RESOURCES[id]; return BG_LAST_RESOURCES[id];
} }
@ -235,9 +223,6 @@ public class ResourceParser {
* @return ID * @return ID
*/ */
public static int getNoteBgSingleRes(int id) { public static int getNoteBgSingleRes(int id) {
if (id < 0 || id >= BG_SINGLE_RESOURCES.length) {
return BG_SINGLE_RESOURCES[BG_DEFAULT_COLOR];
}
return BG_SINGLE_RESOURCES[id]; return BG_SINGLE_RESOURCES[id];
} }
@ -247,9 +232,6 @@ public class ResourceParser {
* @return ID * @return ID
*/ */
public static int getNoteBgNormalRes(int id) { public static int getNoteBgNormalRes(int id) {
if (id < 0 || id >= BG_NORMAL_RESOURCES.length) {
return BG_NORMAL_RESOURCES[BG_DEFAULT_COLOR];
}
return BG_NORMAL_RESOURCES[id]; return BG_NORMAL_RESOURCES[id];
} }
@ -285,9 +267,6 @@ public class ResourceParser {
* @return 2xID * @return 2xID
*/ */
public static int getWidget2xBgResource(int id) { public static int getWidget2xBgResource(int id) {
if (id < 0 || id >= BG_2X_RESOURCES.length) {
return BG_2X_RESOURCES[BG_DEFAULT_COLOR];
}
return BG_2X_RESOURCES[id]; return BG_2X_RESOURCES[id];
} }
@ -309,9 +288,6 @@ public class ResourceParser {
* @return 4xID * @return 4xID
*/ */
public static int getWidget4xBgResource(int id) { public static int getWidget4xBgResource(int id) {
if (id < 0 || id >= BG_4X_RESOURCES.length) {
return BG_4X_RESOURCES[BG_DEFAULT_COLOR];
}
return BG_4X_RESOURCES[id]; return BG_4X_RESOURCES[id];
} }
} }

@ -234,14 +234,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private EditText mTagInput; // 标签输入框 private EditText mTagInput; // 标签输入框
private Button mAddTagButton; // 添加标签按钮 private Button mAddTagButton; // 添加标签按钮
private ArrayList<String> mTagsList; // 标签列表 private ArrayList<String> mTagsList; // 标签列表
// 视图缓存,减少对象创建
private ArrayList<View> mViewCache = new ArrayList<>();
private static final int MAX_CACHE_SIZE = 10; // 最大缓存大小
// 延迟保存相关
private android.os.Handler mSaveNoteHandler = new android.os.Handler();
private TextView mSaveHint; // 保存成功提示视图
// 搜索历史相关 // 搜索历史相关
private static final String PREFERENCE_SEARCH_HISTORY = "search_history"; // 搜索历史偏好设置键 private static final String PREFERENCE_SEARCH_HISTORY = "search_history"; // 搜索历史偏好设置键
@ -1345,114 +1337,58 @@ public class NoteEditActivity extends Activity implements OnClickListener,
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
Log.d(TAG, "switchToListMode started, text length: " + (text != null ? text.length() : 0)); Log.d(TAG, "switchToListMode started, text length: " + (text != null ? text.length() : 0));
// 处理null文本避免空指针异常 // 处理null文本避免空指针异常OMO
final String processedText = text != null ? text : ""; final String processedText = text != null ? text : "";
// 优化:直接在主线程处理,减少线程切换开销 // 预处理:在后台线程中分割文本和准备数据
// 对于大多数情况,文本分割和视图创建的开销很小 new Thread(new Runnable() {
// 只有在文本特别长时才需要考虑后台线程 @Override
if (processedText.length() > 10000) { public void run() {
// 对于长文本,使用后台线程 final String[] items = processedText.split("\n"); // 按行分割文本
new Thread(new Runnable() { Log.d(TAG, "switchToListMode: split into " + items.length + " items");
@Override
public void run() { // 切换回主线程更新UI
final String[] items = processTextForListMode(processedText); runOnUiThread(new Runnable() {
Log.d(TAG, "switchToListMode: split into " + items.length + " items"); @Override
public void run() {
runOnUiThread(new Runnable() { // 批量创建和添加视图,减少布局重绘
@Override mEditTextList.removeAllViews(); // 清空编辑文本列表
public void run() {
createListModeViews(items); int index = 0;
long endTime = System.currentTimeMillis(); View lastItem = null;
Log.d(TAG, "switchToListMode completed in " + (endTime - startTime) + "ms");
// 先创建所有视图
ArrayList<View> viewsToAdd = new ArrayList<>();
for (String item : items) {
if(!TextUtils.isEmpty(item)) {
View listItem = getListItem(item, index);
viewsToAdd.add(listItem);
index++;
}
} }
});
}
}).start();
} else {
// 对于短文本,直接在主线程处理
final String[] items = processTextForListMode(processedText);
Log.d(TAG, "switchToListMode: split into " + items.length + " items");
createListModeViews(items);
long endTime = System.currentTimeMillis();
Log.d(TAG, "switchToListMode completed in " + (endTime - startTime) + "ms");
}
}
/** // 添加最后一个空列表项
* lastItem = getListItem("", index);
* @param text viewsToAdd.add(lastItem);
* @return
*/
private String[] processTextForListMode(String text) {
// 移除HTML标签只保留纯文本
String plainText = removeHtmlTags(text);
// 按行分割
return plainText.split("\n");
}
/** // 一次性添加所有视图到容器
* HTML for (View view : viewsToAdd) {
* @param html HTML mEditTextList.addView(view);
* @return }
*/
private String removeHtmlTags(String html) {
// 简单的HTML标签移除适合大多数情况
if (TextUtils.isEmpty(html)) {
return "";
}
// 移除常见HTML标签
String plainText = html.replaceAll("<[^>]+>", "");
// 处理HTML实体
plainText = plainText.replaceAll("&nbsp;", " ");
plainText = plainText.replaceAll("&lt;", "<");
plainText = plainText.replaceAll("&gt;", ">");
plainText = plainText.replaceAll("&amp;", "&");
return plainText;
}
/** // 设置焦点
* ListItemViewHolder holder = (ListItemViewHolder) lastItem.getTag();
* @param items holder.etEditText.requestFocus();
*/
private void createListModeViews(String[] items) { mNoteEditor.setVisibility(View.GONE); // 隐藏普通编辑器
// 回收现有视图到缓存,减少内存占用 mEditTextList.setVisibility(View.VISIBLE); // 显示清单编辑器
int childCount = mEditTextList.getChildCount();
for (int i = childCount - 1; i >= 0; i--) { long endTime = System.currentTimeMillis();
View view = mEditTextList.getChildAt(i); Log.d(TAG, "switchToListMode completed in " + (endTime - startTime) + "ms");
recycleView(view); }
} });
// 清空编辑文本列表
mEditTextList.removeAllViews();
// 批量创建视图
ArrayList<View> viewsToAdd = new ArrayList<>();
int index = 0;
for (String item : items) {
if (!TextUtils.isEmpty(item)) {
View listItem = getListItem(item, index);
viewsToAdd.add(listItem);
index++;
} }
} }).start();
// 添加最后一个空列表项
View lastItem = getListItem("", index);
viewsToAdd.add(lastItem);
// 批量添加视图,减少布局重绘
for (View view : viewsToAdd) {
mEditTextList.addView(view);
}
// 设置焦点
ListItemViewHolder holder = (ListItemViewHolder) lastItem.getTag();
holder.etEditText.requestFocus();
// 显示/隐藏编辑器
mNoteEditor.setVisibility(View.GONE);
mEditTextList.setVisibility(View.VISIBLE);
} }
/** /**
@ -1510,22 +1446,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* @return * @return
*/ */
private View getListItem(String item, int index) { private View getListItem(String item, int index) {
// 优先从缓存中获取视图减少布局inflate开销 View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
View view = null;
if (!mViewCache.isEmpty()) {
view = mViewCache.remove(0);
} else {
view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
}
// 创建并缓存ViewHolder // 创建并缓存ViewHolder
ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); ListItemViewHolder holder = new ListItemViewHolder();
if (holder == null) { holder.etEditText = (NoteEditText) view.findViewById(R.id.et_edit_text);
holder = new ListItemViewHolder(); holder.cbEditItem = (CheckBox) view.findViewById(R.id.cb_edit_item);
holder.etEditText = (NoteEditText) view.findViewById(R.id.et_edit_text); view.setTag(holder);
holder.cbEditItem = (CheckBox) view.findViewById(R.id.cb_edit_item);
view.setTag(holder);
}
final NoteEditText edit = holder.etEditText; final NoteEditText edit = holder.etEditText;
edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
@ -1535,20 +1462,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() { cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) { if (isChecked) {
// 添加删除线和灰色效果
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
edit.setTextColor(Color.GRAY);
// 将已完成项目移到列表底部
moveCompletedItemToBottom(edit);
} else { } else {
// 移除删除线和恢复颜色
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG); edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
edit.setTextColor(Color.BLACK);
// 将未完成项目移到列表顶部
moveUncompletedItemToTop(edit);
} }
// 延迟保存,避免频繁操作导致卡顿
saveNoteDelayed();
} }
}); });
@ -1556,120 +1473,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
if (item.startsWith(TAG_CHECKED)) { if (item.startsWith(TAG_CHECKED)) {
cb.setChecked(true); cb.setChecked(true);
edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
edit.setTextColor(Color.GRAY);
item = item.substring(TAG_CHECKED.length(), item.length()).trim(); item = item.substring(TAG_CHECKED.length(), item.length()).trim();
} else if (item.startsWith(TAG_UNCHECKED)) { } else if (item.startsWith(TAG_UNCHECKED)) {
cb.setChecked(false); cb.setChecked(false);
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG); edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
edit.setTextColor(Color.BLACK);
item = item.substring(TAG_UNCHECKED.length(), item.length()).trim(); item = item.substring(TAG_UNCHECKED.length(), item.length()).trim();
} else {
// 重置为默认状态
cb.setChecked(false);
edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);
edit.setTextColor(Color.BLACK);
} }
// 设置列表项点击事件监听器,用于标记项目为已完成状态
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 添加点击反馈效果
v.setBackgroundColor(Color.parseColor("#E0E0E0"));
v.postDelayed(new Runnable() {
@Override
public void run() {
v.setBackgroundColor(Color.TRANSPARENT);
}
}, 100);
// 处理列表项点击事件,标记项目为已完成状态
CheckBox checkBox = (CheckBox) v.findViewById(R.id.cb_edit_item);
checkBox.setChecked(!checkBox.isChecked());
}
});
// 设置复选框点击事件监听器
cb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 直接切换选中状态,避免与列表项点击事件冲突
cb.setChecked(!cb.isChecked());
}
});
// 设置编辑文本点击事件监听器,用于进入详细编辑模式
edit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 阻止事件冒泡,避免触发列表项的点击事件
v.setClickable(true);
v.setFocusable(true);
v.setFocusableInTouchMode(true);
// 添加点击反馈效果
edit.setBackgroundColor(Color.parseColor("#F0F0F0"));
edit.postDelayed(new Runnable() {
@Override
public void run() {
edit.setBackgroundColor(Color.TRANSPARENT);
}
}, 100);
// 处理编辑文本点击事件,进入详细编辑模式
edit.requestFocus();
edit.setSelection(edit.length());
// 显示软键盘
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
});
// 为编辑文本添加文本变化监听器,确保修改能够被保存
edit.addTextChangedListener(new android.text.TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(android.text.Editable s) {
// 文本变化后延迟保存笔记,避免频繁操作导致卡顿
saveNoteDelayed();
}
});
// 设置列表项长按事件监听器
edit.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
try {
// 添加长按反馈效果
edit.setBackgroundColor(Color.parseColor("#D0D0D0"));
edit.postDelayed(new Runnable() {
@Override
public void run() {
edit.setBackgroundColor(Color.TRANSPARENT);
}
}, 100);
// 处理长按事件,将清单标记为已完成状态
View parentView = (View) v.getParent();
if (parentView != null) {
CheckBox checkBox = (CheckBox) parentView.findViewById(R.id.cb_edit_item);
if (checkBox != null) {
checkBox.setChecked(!checkBox.isChecked());
}
}
} catch (Exception e) {
Log.e(TAG, "Error in long click listener: " + e.getMessage());
}
return true;
}
});
edit.setOnTextViewChangeListener(this); edit.setOnTextViewChangeListener(this);
edit.setIndex(index); edit.setIndex(index);
edit.setText(getHighlightQueryResult(item, mUserQuery)); edit.setText(getHighlightQueryResult(item, mUserQuery));
@ -1698,161 +1508,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
} }
/**
*
* @param edit
*/
private void moveCompletedItemToBottom(NoteEditText edit) {
try {
int childCount = mEditTextList.getChildCount();
if (childCount <= 1 || edit == null) {
return;
}
// 找到当前项目的索引
int currentIndex = -1;
for (int i = 0; i < childCount; i++) {
View view = mEditTextList.getChildAt(i);
if (view != null) {
ListItemViewHolder holder = (ListItemViewHolder) view.getTag();
if (holder != null && holder.etEditText == edit) {
currentIndex = i;
break;
}
}
}
if (currentIndex == -1 || currentIndex == childCount - 1) {
return;
}
// 找到第一个未完成的项目索引
int firstUncompletedIndex = -1;
for (int i = currentIndex + 1; i < childCount; i++) {
View view = mEditTextList.getChildAt(i);
if (view != null) {
ListItemViewHolder holder = (ListItemViewHolder) view.getTag();
if (holder != null && holder.cbEditItem != null && !holder.cbEditItem.isChecked()) {
firstUncompletedIndex = i;
break;
}
}
}
if (firstUncompletedIndex != -1) {
// 保存当前项目
View currentView = mEditTextList.getChildAt(currentIndex);
if (currentView != null) {
mEditTextList.removeViewAt(currentIndex);
// 插入到第一个未完成项目之前
mEditTextList.addView(currentView, firstUncompletedIndex - 1);
// 更新索引
updateItemIndices();
}
}
} catch (Exception e) {
Log.e(TAG, "Error in moveCompletedItemToBottom: " + e.getMessage());
}
}
/**
*
* @param edit
*/
private void moveUncompletedItemToTop(NoteEditText edit) {
try {
int childCount = mEditTextList.getChildCount();
if (childCount <= 1 || edit == null) {
return;
}
// 找到当前项目的索引
int currentIndex = -1;
for (int i = 0; i < childCount; i++) {
View view = mEditTextList.getChildAt(i);
if (view != null) {
ListItemViewHolder holder = (ListItemViewHolder) view.getTag();
if (holder != null && holder.etEditText == edit) {
currentIndex = i;
break;
}
}
}
if (currentIndex == -1 || currentIndex == 0) {
return;
}
// 找到最后一个已完成的项目索引
int lastCompletedIndex = -1;
for (int i = 0; i < currentIndex; i++) {
View view = mEditTextList.getChildAt(i);
if (view != null) {
ListItemViewHolder holder = (ListItemViewHolder) view.getTag();
if (holder != null && holder.cbEditItem != null && holder.cbEditItem.isChecked()) {
lastCompletedIndex = i;
}
}
}
// 保存当前项目
View currentView = mEditTextList.getChildAt(currentIndex);
if (currentView != null) {
mEditTextList.removeViewAt(currentIndex);
// 插入到最后一个已完成项目之后
mEditTextList.addView(currentView, lastCompletedIndex + 1);
// 更新索引
updateItemIndices();
}
} catch (Exception e) {
Log.e(TAG, "Error in moveUncompletedItemToTop: " + e.getMessage());
}
}
/**
*
*/
private void updateItemIndices() {
try {
int childCount = mEditTextList.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = mEditTextList.getChildAt(i);
if (view != null) {
ListItemViewHolder holder = (ListItemViewHolder) view.getTag();
if (holder != null && holder.etEditText != null) {
holder.etEditText.setIndex(i);
}
}
}
} catch (Exception e) {
Log.e(TAG, "Error in updateItemIndices: " + e.getMessage());
}
}
/**
*
* @param view
*/
private void recycleView(View view) {
if (view != null && mViewCache.size() < MAX_CACHE_SIZE) {
// 清除视图的内容和监听器,避免内存泄漏
ListItemViewHolder holder = (ListItemViewHolder) view.getTag();
if (holder != null) {
holder.etEditText.setText("");
holder.etEditText.setOnTextViewChangeListener(null);
holder.cbEditItem.setOnCheckedChangeListener(null);
}
mViewCache.add(view);
}
}
/**
*
*/
private void clearViewCache() {
mViewCache.clear();
}
/** /**
* *
* NoteSettingChangedListener * NoteSettingChangedListener
@ -1925,35 +1580,26 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private boolean getWorkingText() { private boolean getWorkingText() {
boolean hasChecked = false; boolean hasChecked = false;
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
// 优化使用StringBuilder的初始容量减少扩容开销 StringBuilder sb = new StringBuilder();
StringBuilder sb = new StringBuilder(mEditTextList.getChildCount() * 50); // 预估每个项目平均50字符
for (int i = 0; i < mEditTextList.getChildCount(); i++) { for (int i = 0; i < mEditTextList.getChildCount(); i++) {
View view = mEditTextList.getChildAt(i); View view = mEditTextList.getChildAt(i);
if (view != null) { ListItemViewHolder holder = (ListItemViewHolder) view.getTag();
ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); NoteEditText edit = holder.etEditText;
if (holder != null && holder.etEditText != null && holder.cbEditItem != null) { if (!TextUtils.isEmpty(edit.getText())) {
NoteEditText edit = holder.etEditText; if (holder.cbEditItem.isChecked()) {
if (!TextUtils.isEmpty(edit.getText())) { sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n");
if (holder.cbEditItem.isChecked()) { hasChecked = true;
sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n"); } else {
hasChecked = true; sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n");
} else {
sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n");
}
}
} }
} }
} }
mWorkingNote.setWorkingText(sb.toString()); mWorkingNote.setWorkingText(sb.toString());
} else { } else {
// 对于富文本模式保存当前的HTML内容包括Base64图片 // 对于富文本模式保存当前的HTML内容包括Base64图片
// 优化避免不必要的日志输出减少IO开销 String currentHtml = mNoteEditor.getHtml();
if (mNoteEditor != null) { Log.d(TAG, "getWorkingText called for rich text mode, saving HTML content: " + currentHtml);
String currentHtml = mNoteEditor.getHtml(); mWorkingNote.setWorkingText(currentHtml);
if (currentHtml != null) {
mWorkingNote.setWorkingText(currentHtml);
}
}
} }
return hasChecked; return hasChecked;
} }
@ -2202,71 +1848,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Toast.makeText(this, resId, duration).show(); Toast.makeText(this, resId, duration).show();
} }
/**
*
*/
private void saveNoteDelayed() {
// 移除之前的延迟保存任务
if (mSaveNoteHandler != null) {
mSaveNoteHandler.removeCallbacksAndMessages(null);
}
// 延迟500毫秒保存避免频繁操作导致卡顿
mSaveNoteHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (saveNote()) {
// 保存成功的简短提示
showSaveSuccessHint();
}
}
}, 500);
}
/**
*
*/
private void showSaveSuccessHint() {
if (mSaveHint == null) {
mSaveHint = new TextView(this);
mSaveHint.setText("已保存");
mSaveHint.setTextColor(Color.GRAY);
mSaveHint.setTextSize(12);
mSaveHint.setPadding(10, 5, 10, 5);
mSaveHint.setGravity(Gravity.CENTER);
mSaveHint.setBackgroundColor(Color.parseColor("#E0E0E0"));
mSaveHint.setAlpha(0.0f);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.gravity = Gravity.CENTER;
params.topMargin = 10;
mEditTextList.addView(mSaveHint, params);
}
// 显示动画
mSaveHint.animate()
.alpha(1.0f)
.setDuration(300)
.withEndAction(new Runnable() {
@Override
public void run() {
// 延迟后隐藏
mSaveHint.postDelayed(new Runnable() {
@Override
public void run() {
mSaveHint.animate()
.alpha(0.0f)
.setDuration(300)
.start();
}
}, 1000);
}
})
.start();
}
/** /**
* OMO * OMO
*/ */

@ -33,67 +33,107 @@ import net.micode.notes.ui.NoteEditActivity;
/** /**
* Activity * Activity
* 便 * 便
*
*
* 1. Intent便ID
* 2.
* 3.
* 4. 便
*/ */
public class PasswordInputActivity extends Activity { public class PasswordInputActivity extends Activity {
/** 日志标签,用于调试和日志输出 */
private static final String TAG = "PasswordInputActivity"; private static final String TAG = "PasswordInputActivity";
/** Intent Extra键名用于传递便签ID */
public static final String EXTRA_NOTE_ID = "note_id"; public static final String EXTRA_NOTE_ID = "note_id";
/** 密码输入框控件 */
private EditText mPasswordEditText; private EditText mPasswordEditText;
/** 返回按钮控件 */
private Button mReturnButton; private Button mReturnButton;
/** 确认按钮控件 */
private Button mConfirmButton; private Button mConfirmButton;
/** 当前要访问的便签ID */
private long mNoteId; private long mNoteId;
/**
* Activity
* Intent便ID
*
* @param savedInstanceState Activity
*/
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// 设置布局文件
setContentView(R.layout.activity_password_input); setContentView(R.layout.activity_password_input);
// 从Intent中获取便签ID
mNoteId = getIntent().getLongExtra(EXTRA_NOTE_ID, 0); mNoteId = getIntent().getLongExtra(EXTRA_NOTE_ID, 0);
// 验证便签ID是否有效
if (mNoteId <= 0) { if (mNoteId <= 0) {
// 便签ID无效显示错误提示并关闭Activity
Toast.makeText(this, R.string.error_note_not_exist, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.error_note_not_exist, Toast.LENGTH_SHORT).show();
finish(); finish();
return; return;
} }
// 初始化界面控件
initViews(); initViews();
} }
/**
*
*
*/
private void initViews() { private void initViews() {
// 获取密码输入框控件
mPasswordEditText = (EditText) findViewById(R.id.et_password); mPasswordEditText = (EditText) findViewById(R.id.et_password);
// 获取返回按钮控件
mReturnButton = (Button) findViewById(R.id.btn_return); mReturnButton = (Button) findViewById(R.id.btn_return);
// 获取确认按钮控件
mConfirmButton = (Button) findViewById(R.id.btn_confirm); mConfirmButton = (Button) findViewById(R.id.btn_confirm);
// 设置返回按钮的点击事件监听器
mReturnButton.setOnClickListener(new OnClickListener() { mReturnButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
// 返回主界面 // 返回主界面关闭当前Activity
finish(); finish();
} }
}); });
// 设置确认按钮的点击事件监听器
mConfirmButton.setOnClickListener(new OnClickListener() { mConfirmButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
// 获取用户输入的密码
String password = mPasswordEditText.getText().toString(); String password = mPasswordEditText.getText().toString();
// 检查密码是否为空
if (TextUtils.isEmpty(password)) { if (TextUtils.isEmpty(password)) {
// 密码为空,显示提示信息
Toast.makeText(PasswordInputActivity.this, Toast.makeText(PasswordInputActivity.this,
R.string.password_empty, Toast.LENGTH_SHORT).show(); R.string.password_empty, Toast.LENGTH_SHORT).show();
return; return;
} }
// 验证密码 // 验证密码是否正确
if (PasswordUtils.verifyPassword(PasswordInputActivity.this, mNoteId, password)) { if (PasswordUtils.verifyPassword(PasswordInputActivity.this, mNoteId, password)) {
// 密码正确,跳转到便签编辑界面 // 密码正确,创建Intent跳转到便签编辑界面
Intent intent = new Intent(PasswordInputActivity.this, NoteEditActivity.class); Intent intent = new Intent(PasswordInputActivity.this, NoteEditActivity.class);
// 设置Intent动作为查看
intent.setAction(Intent.ACTION_VIEW); intent.setAction(Intent.ACTION_VIEW);
// 传递便签ID
intent.putExtra(Intent.EXTRA_UID, mNoteId); intent.putExtra(Intent.EXTRA_UID, mNoteId);
// 启动便签编辑Activity
startActivity(intent); startActivity(intent);
// 关闭当前Activity
finish(); finish();
} else { } else {
// 密码错误 // 密码错误,显示错误提示
Toast.makeText(PasswordInputActivity.this, Toast.makeText(PasswordInputActivity.this,
R.string.password_error, Toast.LENGTH_SHORT).show(); R.string.password_error, Toast.LENGTH_SHORT).show();
// 清空密码输入框,方便用户重新输入
mPasswordEditText.setText(""); mPasswordEditText.setText("");
} }
} }

@ -37,68 +37,132 @@ import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils; import net.micode.notes.tool.DataUtils;
/**
* Activity
* 便
*
*
* 1. 便
* 2. 便
* 3. 便
* 4. 便
*/
public class TrashActivity extends Activity implements OnClickListener { public class TrashActivity extends Activity implements OnClickListener {
/** 日志标签,用于调试和日志输出 */
private static final String TAG = "TrashActivity"; private static final String TAG = "TrashActivity";
/** 回收站列表查询的Token标识 */
private static final int TRASH_LIST_QUERY_TOKEN = 0; private static final int TRASH_LIST_QUERY_TOKEN = 0;
/** 返回按钮控件 */
private Button mReturnButton; private Button mReturnButton;
/** 清空所有按钮控件 */
private Button mCleanAllButton; private Button mCleanAllButton;
/** 回收站列表视图 */
private ListView mTrashListView; private ListView mTrashListView;
/** 回收站列表适配器 */
private NotesListAdapter mTrashListAdapter; private NotesListAdapter mTrashListAdapter;
/** 内容解析器,用于访问数据库 */
private ContentResolver mContentResolver; private ContentResolver mContentResolver;
/** 后台查询处理器,用于异步查询回收站数据 */
private BackgroundQueryHandler mBackgroundQueryHandler; private BackgroundQueryHandler mBackgroundQueryHandler;
/**
* Activity
*
*
* @param savedInstanceState
*/
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// 设置布局文件
setContentView(R.layout.activity_trash); setContentView(R.layout.activity_trash);
// 初始化界面控件和资源
initResources(); initResources();
} }
/**
* Activity
* Activity
*/
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
// 启动异步查询回收站列表
startAsyncTrashListQuery(); startAsyncTrashListQuery();
} }
/**
*
*
*/
private void initResources() { private void initResources() {
// 获取内容解析器
mContentResolver = this.getContentResolver(); mContentResolver = this.getContentResolver();
// 创建后台查询处理器
mBackgroundQueryHandler = new BackgroundQueryHandler(mContentResolver); mBackgroundQueryHandler = new BackgroundQueryHandler(mContentResolver);
// 绑定返回按钮
mReturnButton = (Button) findViewById(R.id.btn_return); mReturnButton = (Button) findViewById(R.id.btn_return);
if (mReturnButton != null) { if (mReturnButton != null) {
mReturnButton.setOnClickListener(this); mReturnButton.setOnClickListener(this);
} }
// 绑定清空所有按钮
mCleanAllButton = (Button) findViewById(R.id.btn_clean_all); mCleanAllButton = (Button) findViewById(R.id.btn_clean_all);
if (mCleanAllButton != null) { if (mCleanAllButton != null) {
mCleanAllButton.setOnClickListener(this); mCleanAllButton.setOnClickListener(this);
} }
// 绑定回收站列表视图
mTrashListView = (ListView) findViewById(R.id.trash_list); mTrashListView = (ListView) findViewById(R.id.trash_list);
if (mTrashListView != null) { if (mTrashListView != null) {
// 创建列表适配器
mTrashListAdapter = new NotesListAdapter(this); mTrashListAdapter = new NotesListAdapter(this);
// 设置适配器
mTrashListView.setAdapter(mTrashListAdapter); mTrashListView.setAdapter(mTrashListAdapter);
// 设置列表项点击监听器
mTrashListView.setOnItemClickListener(new OnTrashItemClickListener()); mTrashListView.setOnItemClickListener(new OnTrashItemClickListener());
} }
} }
/**
*
* 使
*/
private void startAsyncTrashListQuery() { private void startAsyncTrashListQuery() {
mBackgroundQueryHandler.startQuery(TRASH_LIST_QUERY_TOKEN, null, mBackgroundQueryHandler.startQuery(TRASH_LIST_QUERY_TOKEN, null,
Notes.CONTENT_TRASH_URI, NoteItemData.PROJECTION, null, null, Notes.CONTENT_TRASH_URI, NoteItemData.PROJECTION, null, null,
NoteColumns.MODIFIED_DATE + " DESC"); NoteColumns.MODIFIED_DATE + " DESC");
} }
/**
*
* AsyncQueryHandler线
*/
private final class BackgroundQueryHandler extends AsyncQueryHandler { private final class BackgroundQueryHandler extends AsyncQueryHandler {
/**
*
* @param contentResolver
*/
public BackgroundQueryHandler(ContentResolver contentResolver) { public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver); super(contentResolver);
} }
/**
*
* 线UI
*
* @param token Token
* @param cookie Cookie
* @param cursor
*/
@Override @Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) { protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch (token) { switch (token) {
case TRASH_LIST_QUERY_TOKEN: case TRASH_LIST_QUERY_TOKEN:
// 更新列表适配器的游标,刷新列表显示
mTrashListAdapter.changeCursor(cursor); mTrashListAdapter.changeCursor(cursor);
break; break;
default: default:
@ -107,19 +171,42 @@ public class TrashActivity extends Activity implements OnClickListener {
} }
} }
/**
*
*
*/
private class OnTrashItemClickListener implements OnItemClickListener { private class OnTrashItemClickListener implements OnItemClickListener {
/**
*
*
* @param parent
* @param view
* @param position
* @param id ID
*/
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 检查视图是否为NotesListItem类型
if (view instanceof NotesListItem) { if (view instanceof NotesListItem) {
// 获取列表项数据
NoteItemData item = ((NotesListItem) view).getItemData(); NoteItemData item = ((NotesListItem) view).getItemData();
// 显示操作对话框
showTrashItemDialog(item); showTrashItemDialog(item);
} }
} }
} }
/**
* 便
*
*
* @param item 便
*/
private void showTrashItemDialog(final NoteItemData item) { private void showTrashItemDialog(final NoteItemData item) {
AlertDialog.Builder builder = new AlertDialog.Builder(this); AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 设置对话框标题为便签摘要
builder.setTitle(item.getSnippet()); builder.setTitle(item.getSnippet());
// 设置操作选项:删除和恢复
builder.setItems(new String[] { builder.setItems(new String[] {
getString(R.string.menu_delete), getString(R.string.menu_delete),
getString(R.string.button_recovery) getString(R.string.button_recovery)
@ -127,73 +214,120 @@ public class TrashActivity extends Activity implements OnClickListener {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
switch (which) { switch (which) {
case 0: // Delete - 彻底删除 case 0: // 彻底删除选项
permanentlyDeleteNote(item.getId()); permanentlyDeleteNote(item.getId());
break; break;
case 1: // Recovery - 恢复 case 1: // 恢复选项
recoverNote(item.getId()); recoverNote(item.getId());
break; break;
} }
} }
}); });
// 显示对话框
builder.show(); builder.show();
} }
/**
* 便
* 便
*
* @param noteId 便ID
*/
private void permanentlyDeleteNote(long noteId) { private void permanentlyDeleteNote(long noteId) {
// 调用工具类方法彻底删除便签
if (DataUtils.permanentlyDeleteFromTrash(mContentResolver, noteId, this)) { if (DataUtils.permanentlyDeleteFromTrash(mContentResolver, noteId, this)) {
// 删除成功,显示提示信息
Toast.makeText(this, getString(R.string.menu_delete) + " " + getString(R.string.menu_success), Toast.makeText(this, getString(R.string.menu_delete) + " " + getString(R.string.menu_success),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
startAsyncTrashListQuery(); // Refresh list // 刷新列表显示
startAsyncTrashListQuery();
} else { } else {
// 删除失败,显示错误提示
Toast.makeText(this, getString(R.string.menu_delete) + " " + getString(R.string.failed_sdcard_export), Toast.makeText(this, getString(R.string.menu_delete) + " " + getString(R.string.failed_sdcard_export),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} }
} }
/**
* 便
* 便
*
* @param noteId 便ID
*/
private void recoverNote(long noteId) { private void recoverNote(long noteId) {
// 调用工具类方法恢复便签
if (DataUtils.restoreNoteFromTrash(mContentResolver, noteId, this)) { if (DataUtils.restoreNoteFromTrash(mContentResolver, noteId, this)) {
// 恢复成功,显示提示信息
Toast.makeText(this, getString(R.string.button_recovery) + " " + getString(R.string.menu_success), Toast.makeText(this, getString(R.string.button_recovery) + " " + getString(R.string.menu_success),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
startAsyncTrashListQuery(); // Refresh list // 刷新列表显示
startAsyncTrashListQuery();
} else { } else {
// 恢复失败,显示错误提示
Toast.makeText(this, getString(R.string.button_recovery) + " " + getString(R.string.failed_sdcard_export), Toast.makeText(this, getString(R.string.button_recovery) + " " + getString(R.string.failed_sdcard_export),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} }
} }
/**
*
*
*/
private void showClearAllTrashDialog() { private void showClearAllTrashDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this); AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 设置对话框标题
builder.setTitle(getString(R.string.button_clean_all)); builder.setTitle(getString(R.string.button_clean_all));
// 设置对话框消息,提醒用户此操作不可恢复
builder.setMessage(getString(R.string.alert_message_clear_all_trash)); builder.setMessage(getString(R.string.alert_message_clear_all_trash));
// 设置确认按钮
builder.setPositiveButton(android.R.string.ok, builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
// 用户确认后执行清空操作
clearAllTrash(); clearAllTrash();
} }
}); });
// 设置取消按钮
builder.setNegativeButton(android.R.string.cancel, null); builder.setNegativeButton(android.R.string.cancel, null);
// 显示对话框
builder.show(); builder.show();
} }
/**
* 便
* 便
*/
private void clearAllTrash() { private void clearAllTrash() {
// 调用工具类方法清空所有回收站便签
if (DataUtils.clearAllTrash(mContentResolver, this)) { if (DataUtils.clearAllTrash(mContentResolver, this)) {
// 清空成功,显示提示信息
Toast.makeText(this, getString(R.string.button_clean_all) + " " + getString(R.string.menu_success), Toast.makeText(this, getString(R.string.button_clean_all) + " " + getString(R.string.menu_success),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
startAsyncTrashListQuery(); // Refresh list to clear UI // 刷新列表显示清空UI
startAsyncTrashListQuery();
} else { } else {
// 清空失败,显示错误提示
Toast.makeText(this, getString(R.string.button_clean_all) + " " + getString(R.string.failed_sdcard_export), Toast.makeText(this, getString(R.string.button_clean_all) + " " + getString(R.string.failed_sdcard_export),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
} }
} }
/**
*
*
*
* @param v
*/
@Override @Override
public void onClick(View v) { public void onClick(View v) {
switch (v.getId()) { switch (v.getId()) {
case R.id.btn_return: case R.id.btn_return:
// 返回按钮关闭当前Activity
finish(); finish();
break; break;
case R.id.btn_clean_all: case R.id.btn_clean_all:
// 清空所有按钮:显示确认对话框
showClearAllTrashDialog(); showClearAllTrashDialog();
break; break;
default: default:

Loading…
Cancel
Save