|
|
|
|
@ -0,0 +1,951 @@
|
|
|
|
|
AndroidManifest.xml
|
|
|
|
|
<?xml version="1.0" encoding="utf-8"?> <!-- 声明XML文件的版本和编码格式 -->
|
|
|
|
|
|
|
|
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
|
|
|
xmlns:tools="http://schemas.android.com/tools"> <!-- 声明manifest文件的根元素,包含android和tools两个命名空间 -->
|
|
|
|
|
|
|
|
|
|
<!-- 声明应用需要访问外部存储的权限 -->
|
|
|
|
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 允许应用创建快捷方式到主屏幕 -->
|
|
|
|
|
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> <!-- 声明应用需要访问网络的权限 -->
|
|
|
|
|
<uses-permission android:name="android.permission.INTERNET" /> <!-- 允许应用读取联系人信息 -->
|
|
|
|
|
<uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- 允许应用管理设备上的账户 -->
|
|
|
|
|
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <!-- 允许应用对设备上的账户进行身份验证 -->
|
|
|
|
|
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" /> <!-- 允许应用获取设备上的账户列表 -->
|
|
|
|
|
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <!-- 允许应用使用设备上存储的凭证(如密码) -->
|
|
|
|
|
<uses-permission android:name="android.permission.USE_CREDENTIALS" /> <!-- 允许应用在设备启动完成后接收通知 -->
|
|
|
|
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
|
|
|
<application
|
|
|
|
|
android:allowBackup="true" <!-- 允许应用数据备份到云端或其他存储位置 -->
|
|
|
|
|
android:dataExtractionRules="@xml/data_extraction_rules" <!-- 指定数据提取规则文件的路径,用于指导如何提取应用数据 -->
|
|
|
|
|
android:fullBackupContent="@xml/backup_rules" <!-- 指定完整备份内容的规则文件路径 -->
|
|
|
|
|
android:icon="@mipmap/ic_launcher" <!-- 应用图标资源文件的路径 -->
|
|
|
|
|
android:label="@string/app_name" <!-- 应用名称资源文件的引用 -->
|
|
|
|
|
android:roundIcon="@mipmap/ic_launcher_round" <!-- 圆形应用图标资源文件的路径,主要用于支持圆形图标显示的设备 -->
|
|
|
|
|
android:supportsRtl="true" <!-- 表明应用支持从右到左的布局,主要用于支持阿拉伯语、希伯来语等从右至左阅读的语言 -->
|
|
|
|
|
android:theme="@style/Theme.Notesmaster" <!-- 应用的主题样式 -->
|
|
|
|
|
tools:targetApi="31"> <!-- 指定该应用针对的Android API级别为31,即Android 12 -->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<activity <!-- 定义一个Activity组件 -->
|
|
|
|
|
android:name=".ui.NotesListActivity" <!-- Activity类的全限定名(包名+类名),指定这个Activity的Java/Kotlin类 -->
|
|
|
|
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
|
|
|
|
<!-- 指定Activity将直接处理而不是由系统处理的配置变更类型,这里包括键盘隐藏状态、屏幕方向和屏幕尺寸 -->
|
|
|
|
|
android:label="@string/app_name" <!-- Activity的标题资源文件的引用,通常用于启动器图标下的文本和任务管理器的标题 -->
|
|
|
|
|
android:launchMode="singleTop" <!-- Activity的启动模式,这里设置为singleTop,意味着如果Activity已经在任务栈的顶部,则不会创建新的实例 -->
|
|
|
|
|
android:theme="@style/NoteTheme" <!-- 为这个Activity指定一个不同于应用主题的主题样式 -->
|
|
|
|
|
android:uiOptions="splitActionBarWhenNarrow" <!-- 当屏幕空间狭窄时,将ActionBar分割为上下两部分 -->
|
|
|
|
|
android:windowSoftInputMode="adjustPan"
|
|
|
|
|
<!-- 当软键盘弹出时,Activity的布局调整方式,这里设置为调整窗口内容以留出空间给软键盘,而不是调整软键盘位置 -->
|
|
|
|
|
android:exported="true"> <!-- 表明这个Activity是否可以被其他应用组件(如Activity、Service等)启动或与之交互,true表示可以 --
|
|
|
|
|
<intent-filter> <!-- 定义一个Intent过滤器,用于指定这个Activity可以响应的Intent -->
|
|
|
|
|
<action android:name="android.intent.action.MAIN" /> <!-- 指定这个Activity是应用的入口点 -->
|
|
|
|
|
<category android:name="android.intent.category.LAUNCHER" /> <!-- 指定这个Activity应该出现在设备的启动器(即主屏幕的应用列表)中 -->
|
|
|
|
|
</intent-filter>
|
|
|
|
|
</activity>
|
|
|
|
|
<!-- 定义一个Activity组件,用于编辑笔记 -->
|
|
|
|
|
<activity
|
|
|
|
|
android:name=".ui.NoteEditActivity" <!-- 指定Activity类的全限定名 -->
|
|
|
|
|
android:configChanges="keyboardHidden|orientation|screenSize" <!-- 指定Activity将直接处理的配置变更类型 -->
|
|
|
|
|
android:launchMode="singleTop" <!-- Activity的启动模式 -->
|
|
|
|
|
android:theme="@style/NoteTheme" <!-- 为这个Activity指定主题样式 -->
|
|
|
|
|
android:exported="true"> <!-- 表明这个Activity可以被其他应用组件启动 -->
|
|
|
|
|
|
|
|
|
|
<!-- 定义一个Intent过滤器,用于响应查看特定MIME类型数据的请求 -->
|
|
|
|
|
<intent-filter>
|
|
|
|
|
<action android:name="android.intent.action.VIEW" /> <!-- 指定Action为查看 -->
|
|
|
|
|
<category android:name="android.intent.category.DEFAULT" /> <!-- 默认类别 -->
|
|
|
|
|
<data android:mimeType="vnd.android.cursor.item/text_note" /> <!-- 指定MIME类型为文本笔记 -->
|
|
|
|
|
<data android:mimeType="vnd.android.cursor.item/call_note" /> <!-- 指定MIME类型为通话笔记 -->
|
|
|
|
|
<!-- 注意:通常一个<intent-filter>中不会包含多个<data>元素,除非它们通过android:host, android:pathPrefix等属性来区分,
|
|
|
|
|
但在这里可能是为了示例目的而列出。在实际应用中,应该为每个MIME类型定义单独的<intent-filter>。 -->
|
|
|
|
|
</intent-filter>
|
|
|
|
|
|
|
|
|
|
<!-- 另一个Intent过滤器,用于响应插入或编辑特定MIME类型数据的请求 -->
|
|
|
|
|
<intent-filter>
|
|
|
|
|
<action android:name="android.intent.action.INSERT_OR_EDIT" /> <!-- 指定Action为插入或编辑 -->
|
|
|
|
|
<!-- 其余部分与上一个intent-filter相同 -->
|
|
|
|
|
</intent-filter>
|
|
|
|
|
|
|
|
|
|
<!-- 另一个Intent过滤器,用于响应搜索请求 -->
|
|
|
|
|
<intent-filter>
|
|
|
|
|
<action android:name="android.intent.action.SEARCH" /> <!-- 指定Action为搜索 -->
|
|
|
|
|
<!-- 默认类别 -->
|
|
|
|
|
</intent-filter>
|
|
|
|
|
|
|
|
|
|
<!-- 指定与搜索相关的元数据,通常用于全局搜索 -->
|
|
|
|
|
<meta-data
|
|
|
|
|
android:name="android.app.searchable"
|
|
|
|
|
android:resource="@xml/searchable" /> <!-- 指定搜索配置文件的路径 -->
|
|
|
|
|
</activity>
|
|
|
|
|
|
|
|
|
|
<!-- 定义一个Content Provider组件,用于提供笔记数据的访问 -->
|
|
|
|
|
<provider
|
|
|
|
|
android:name="net.micode.notes.data.NotesProvider" <!-- 指定Provider类的全限定名 -->
|
|
|
|
|
android:authorities="micode_notes" <!-- 指定Provider的唯一标识符 -->
|
|
|
|
|
android:multiprocess="true" <!-- 允许Provider在多进程中运行 -->
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<!-- 定义一个Broadcast Receiver组件,用于接收小部件更新等事件 -->
|
|
|
|
|
<receiver
|
|
|
|
|
android:name=".widget.NoteWidgetProvider_2x" <!-- 指定Receiver类的全限定名 -->
|
|
|
|
|
android:label="@string/app_widget2x2" <!-- 指定Receiver的标签,通常用于在设置界面显示 -->
|
|
|
|
|
android:exported="true"> <!-- 表明这个Receiver可以被其他应用触发 -->
|
|
|
|
|
<intent-filter>
|
|
|
|
|
<!-- 指定Receiver可以响应的Intent类型 -->
|
|
|
|
|
</intent-filter>
|
|
|
|
|
<!-- 指定与小部件相关的元数据 -->
|
|
|
|
|
<meta-data
|
|
|
|
|
android:name="android.appwidget.provider"
|
|
|
|
|
android:resource="@xml/widget_2x_info" /> <!-- 指定小部件配置文件的路径 -->
|
|
|
|
|
</receiver>
|
|
|
|
|
|
|
|
|
|
<!-- 另一个Broadcast Receiver组件,用于4x4大小的小部件 -->
|
|
|
|
|
<receiver <!-- 其余部分与上一个receiver相同,但类名和元数据文件不同 -->
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<!-- 定义一个Broadcast Receiver组件,用于接收系统启动完成的广播 -->
|
|
|
|
|
<receiver
|
|
|
|
|
android:name=".ui.AlarmInitReceiver"
|
|
|
|
|
android:exported="true">
|
|
|
|
|
<intent-filter>
|
|
|
|
|
<action android:name="android.intent.action.BOOT_COMPLETED" /> <!-- 指定Action为系统启动完成 -->
|
|
|
|
|
</intent-filter>
|
|
|
|
|
</receiver> <!-- 另一个Broadcast Receiver组件,可能用于处理闹钟相关的广播 -->
|
|
|
|
|
<receiver
|
|
|
|
|
android:name="net.micode.notes.ui.AlarmReceiver"
|
|
|
|
|
android:process=":remote"> <!-- 指定Receiver在远程进程中运行 -->
|
|
|
|
|
</receiver>
|
|
|
|
|
<activity <!-- 定义一个Activity组件,用于显示闹钟提醒 -->
|
|
|
|
|
android:name=".ui.AlarmAlertActivity"
|
|
|
|
|
android:label="@string/app_name" <!-- 指定Activity的标签 -->
|
|
|
|
|
android:launchMode="singleInstance" <!-- Activity的启动模式 -->
|
|
|
|
|
android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> <!-- 为这个Activity指定主题样式 -->
|
|
|
|
|
</activity>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<activity <!-- 定义一个Activity组件,用于显示应用偏好设置 -->
|
|
|
|
|
|
|
|
|
|
android:name="net.micode.notes.ui.NotesPreferenceActivity"
|
|
|
|
|
android:label="@string/preferences_title" <!-- 指定Activity的标签 -->
|
|
|
|
|
android:launchMode="singleTop" <!-- Activity的启动模式 -->
|
|
|
|
|
android:theme="@android:style/Theme.Holo.Light"> <!-- 为这个Activity指定主题样式 -->
|
|
|
|
|
</activity>
|
|
|
|
|
|
|
|
|
|
<!-- 定义一个Service组件,用于同步Google任务(可能是指Google Tasks服务) -->
|
|
|
|
|
<service
|
|
|
|
|
android:name="net.micode.notes.gtask.remote.GTaskSyncService"
|
|
|
|
|
android:exported="false"> <!-- 表明这个Service不能被其他应用启动 -->
|
|
|
|
|
</service>
|
|
|
|
|
|
|
|
|
|
<!-- 指定应用的默认搜索Activity -->
|
|
|
|
|
<meta-data
|
|
|
|
|
android:name="android.app.default_searchable"
|
|
|
|
|
android:value=".ui.NoteEditActivity" /> <!-- 指定默认搜索Activity的全限定名 -->
|
|
|
|
|
|
|
|
|
|
<!-- 注释掉的代码,表示原本有一个MainActivity的声明,但现在被注释掉了 -->
|
|
|
|
|
<!--
|
|
|
|
|
<activity
|
|
|
|
|
...
|
|
|
|
|
</activity>
|
|
|
|
|
|
|
|
|
|
<!-- </application> 标签未在提供的代码段中明确给出,但它是所有上述组件声明的父容器 -->
|
|
|
|
|
</manifest>
|
|
|
|
|
java/net.micode.nates/data/contact
|
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
|
|
|
|
|
*
|
|
|
|
|
* 版权信息,表明这段代码是由MiCode开源社区在2010-2011年间开发的。
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
*
|
|
|
|
|
* 声明这段代码遵循Apache License 2.0版本。
|
|
|
|
|
*
|
|
|
|
|
* 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; // 声明包名,表示这个类属于net.micode.notes.data这个包。
|
|
|
|
|
|
|
|
|
|
import android.content.Context; // 导入Android的Context类,用于访问应用的特定资源和类,以及调用应用级别的操作。
|
|
|
|
|
|
|
|
|
|
import android.database.Cursor; // 导入Android的Cursor类,用于遍历数据库查询结果。
|
|
|
|
|
|
|
|
|
|
import android.provider.ContactsContract.CommonDataKinds.Phone; // 导入Android的Phone类,用于访问联系人数据库中的电话号码信息。
|
|
|
|
|
|
|
|
|
|
import android.provider.ContactsContract.Data; // 导入Android的Data类,用于访问联系人数据库中的数据。
|
|
|
|
|
|
|
|
|
|
import android.telephony.PhoneNumberUtils; // 导入Android的PhoneNumberUtils类,提供了一些实用的电话号码处理功能。
|
|
|
|
|
|
|
|
|
|
import android.util.Log; // 导入Android的Log类,用于打印日志信息。
|
|
|
|
|
|
|
|
|
|
import java.util.HashMap; // 导入Java的HashMap类,用于存储键值对。
|
|
|
|
|
|
|
|
|
|
public class Contact { // 声明一个名为Contact的公开类。
|
|
|
|
|
|
|
|
|
|
private static HashMap<String, String> sContactCache; // 声明一个静态的HashMap,用于缓存电话号码和联系人名称的对应关系。
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "Contact"; // 声明一个静态常量TAG,用于日志打印时标识来源。
|
|
|
|
|
|
|
|
|
|
private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER
|
|
|
|
|
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"
|
|
|
|
|
+ " AND " + Data.RAW_CONTACT_ID + " IN "
|
|
|
|
|
+ "(SELECT raw_contact_id "
|
|
|
|
|
+ " FROM phone_lookup"
|
|
|
|
|
+ " WHERE min_match = '+')"; // 声明一个静态常量CALLER_ID_SELECTION,用于构建查询联系人数据库时的选择条件。
|
|
|
|
|
|
|
|
|
|
public static String getContact(Context context, String phoneNumber) { // 声明一个公开静态方法getContact,用于根据电话号码获取联系人名称。
|
|
|
|
|
|
|
|
|
|
if(sContactCache == null) {
|
|
|
|
|
sContactCache = new HashMap<String, String>();
|
|
|
|
|
} // 如果缓存为空,则初始化缓存。
|
|
|
|
|
|
|
|
|
|
if(sContactCache.containsKey(phoneNumber)) {
|
|
|
|
|
return sContactCache.get(phoneNumber); // 如果缓存中已经包含该电话号码,则直接返回缓存中的联系人名称。
|
|
|
|
|
|
|
|
|
|
String selection = CALLER_ID_SELECTION.replace("+",
|
|
|
|
|
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); // 根据电话号码生成查询条件。
|
|
|
|
|
|
|
|
|
|
Cursor cursor = context.getContentResolver().query(
|
|
|
|
|
Data.CONTENT_URI,
|
|
|
|
|
new String [] { Phone.DISPLAY_NAME },
|
|
|
|
|
selection,
|
|
|
|
|
new String[] { phoneNumber },
|
|
|
|
|
null);// 使用ContentResolver查询联系人数据库,获取电话号码对应的联系人名称。
|
|
|
|
|
|
|
|
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
|
|
|
try {
|
|
|
|
|
String name = cursor.getString(0);
|
|
|
|
|
sContactCache.put(phoneNumber, name);
|
|
|
|
|
return name;
|
|
|
|
|
} catch (IndexOutOfBoundsException e) {
|
|
|
|
|
Log.e(TAG, " Cursor get string error " + e.toString());
|
|
|
|
|
return null;
|
|
|
|
|
} finally {
|
|
|
|
|
cursor.close();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Log.d(TAG, "No contact matched with number:" + phoneNumber);
|
|
|
|
|
return null;
|
|
|
|
|
} // 处理查询结果,如果找到对应的联系人名称,则将其加入缓存并返回;否则打印日志并返回null。
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
java/net.micode.notes/data/Notes
|
|
|
|
|
package net.micode.notes.data; // 声明这个类所在的包
|
|
|
|
|
|
|
|
|
|
import android.net.Uri; // 导入Uri类,用于处理统一资源标识符
|
|
|
|
|
|
|
|
|
|
public class Notes { // 定义Notes类
|
|
|
|
|
public static final String AUTHORITY = "micode_notes"; // 定义内容提供者的授权名
|
|
|
|
|
public static final String TAG = "Notes"; // 定义一个日志标签,用于日志输出
|
|
|
|
|
public static final int TYPE_NOTE = 0; // 定义笔记的类型常量
|
|
|
|
|
public static final int TYPE_FOLDER = 1; // 定义文件夹的类型常量
|
|
|
|
|
public static final int TYPE_SYSTEM = 2; // 定义系统级的类型常量
|
|
|
|
|
|
|
|
|
|
// 以下是系统文件夹的标识符常量
|
|
|
|
|
public static final int ID_ROOT_FOLDER = 0; // 根文件夹的ID
|
|
|
|
|
public static final int ID_TEMPARAY_FOLDER = -1; // 临时文件夹的ID,用于不属于任何文件夹的笔记
|
|
|
|
|
public static final int ID_CALL_RECORD_FOLDER = -2; // 通话记录文件夹的ID
|
|
|
|
|
public static final int ID_TRASH_FOLER = -3; // 垃圾文件夹的ID(注意这里有个拼写错误,应该是ID_TRASH_FOLDER)
|
|
|
|
|
|
|
|
|
|
// 定义Intent中使用的额外数据键
|
|
|
|
|
public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date"; // 提醒日期
|
|
|
|
|
public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id"; // 背景颜色ID
|
|
|
|
|
public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id"; // 小部件ID
|
|
|
|
|
public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type"; // 小部件类型
|
|
|
|
|
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id"; // 文件夹ID
|
|
|
|
|
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date"; // 通话日期
|
|
|
|
|
|
|
|
|
|
// 定义小部件类型的常量
|
|
|
|
|
public static final int TYPE_WIDGET_INVALIDE = -1; // 无效的小部件类型
|
|
|
|
|
public static final int TYPE_WIDGET_2X = 0; // 2倍大小的小部件类型
|
|
|
|
|
public static final int TYPE_WIDGET_4X = 1; // 4倍大小的小部件类型
|
|
|
|
|
|
|
|
|
|
// 定义内部类DataConstants,包含笔记和通话笔记的内容类型
|
|
|
|
|
public static class DataConstants {
|
|
|
|
|
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; // 文本笔记的内容类型
|
|
|
|
|
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; // 通话笔记的内容类型
|
|
|
|
|
} // 定义查询所有笔记和文件夹的Uri
|
|
|
|
|
public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note"); // 定义查询数据的Uri
|
|
|
|
|
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); // 定义接口NoteColumns,包含笔记和文件夹的列名
|
|
|
|
|
public interface NoteColumns {
|
|
|
|
|
// 行的唯一ID
|
|
|
|
|
public static final String ID = "_id";
|
|
|
|
|
|
|
|
|
|
// 笔记或文件夹的父ID
|
|
|
|
|
public static final String PARENT_ID = "parent_id";
|
|
|
|
|
|
|
|
|
|
// 笔记或文件夹的创建日期
|
|
|
|
|
public static final String CREATED_DATE = "created_date";
|
|
|
|
|
|
|
|
|
|
// 笔记或文件夹的最新修改日期
|
|
|
|
|
public static final String MODIFIED_DATE = "modified_date";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 定义一个包含多个静态常量的接口,这些常量代表数据库中的列名和数据类型
|
|
|
|
|
public interface NoteColumns {
|
|
|
|
|
// 告警日期
|
|
|
|
|
/**
|
|
|
|
|
* Alert date
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String ALERTED_DATE = "alert_date";
|
|
|
|
|
|
|
|
|
|
// 文件夹名称或笔记的文本内容
|
|
|
|
|
/**
|
|
|
|
|
* Folder's name or text content of note
|
|
|
|
|
* <P> 类型:TEXT </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String SNIPPET = "snippet";
|
|
|
|
|
|
|
|
|
|
// 笔记的widget id
|
|
|
|
|
/**
|
|
|
|
|
* Note's widget id
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String WIDGET_ID = "widget_id";
|
|
|
|
|
|
|
|
|
|
// 笔记的widget类型
|
|
|
|
|
/**
|
|
|
|
|
* Note's widget type
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String WIDGET_TYPE = "widget_type";
|
|
|
|
|
|
|
|
|
|
// 笔记背景颜色的id
|
|
|
|
|
/**
|
|
|
|
|
* Note's background color's id
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
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
|
|
|
|
|
* <P> 类型:INTEGER </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String HAS_ATTACHMENT = "has_attachment";
|
|
|
|
|
|
|
|
|
|
// 文件夹中的笔记数量
|
|
|
|
|
/**
|
|
|
|
|
* Folder's count of notes
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String NOTES_COUNT = "notes_count";
|
|
|
|
|
|
|
|
|
|
// 文件类型:文件夹或笔记
|
|
|
|
|
/**
|
|
|
|
|
* The file type: folder or note
|
|
|
|
|
* <P> 类型:INTEGER </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String TYPE = "type";
|
|
|
|
|
|
|
|
|
|
// 最后一次同步的id
|
|
|
|
|
/**
|
|
|
|
|
* The last sync id
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String SYNC_ID = "sync_id";
|
|
|
|
|
|
|
|
|
|
// 标记指示是否在本地修改过
|
|
|
|
|
/**
|
|
|
|
|
* Sign to indicate local modified or not
|
|
|
|
|
* <P> 类型:INTEGER </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String LOCAL_MODIFIED = "local_modified";
|
|
|
|
|
|
|
|
|
|
// 移动到临时文件夹之前的原始父id
|
|
|
|
|
/**
|
|
|
|
|
* Original parent id before moving into temporary folder
|
|
|
|
|
* <P> 类型 : INTEGER </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String ORIGIN_PARENT_ID = "origin_parent_id";
|
|
|
|
|
|
|
|
|
|
// gtask的id
|
|
|
|
|
/**
|
|
|
|
|
* The gtask id
|
|
|
|
|
* <P> 类型 : TEXT </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String GTASK_ID = "gtask_id";
|
|
|
|
|
|
|
|
|
|
// 版本代码
|
|
|
|
|
/**
|
|
|
|
|
* The version code
|
|
|
|
|
* <P> 类型 : INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String VERSION = "version";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 定义一个接口,包含数据表的通用列名和数据类型
|
|
|
|
|
public interface DataColumns {
|
|
|
|
|
// 行的唯一ID
|
|
|
|
|
/**
|
|
|
|
|
* The unique ID for a row
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String ID = "_id";
|
|
|
|
|
|
|
|
|
|
// 项的MIME类型
|
|
|
|
|
/**
|
|
|
|
|
* The MIME type of the item represented by this row.
|
|
|
|
|
* <P> 类型:Text </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String MIME_TYPE = "mime_type";
|
|
|
|
|
|
|
|
|
|
// 这条数据所属的笔记的引用id
|
|
|
|
|
/**
|
|
|
|
|
* The reference id to note that this data belongs to
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String NOTE_ID = "note_id";
|
|
|
|
|
|
|
|
|
|
// 笔记或文件夹的创建日期
|
|
|
|
|
/**
|
|
|
|
|
* Created data for note or folder
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String CREATED_DATE = "created_date";
|
|
|
|
|
|
|
|
|
|
// 最新修改日期
|
|
|
|
|
/**
|
|
|
|
|
* Latest modified date
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String MODIFIED_DATE = "modified_date";
|
|
|
|
|
|
|
|
|
|
// 数据的内容
|
|
|
|
|
/**
|
|
|
|
|
* Data's content
|
|
|
|
|
* <P> 类型:TEXT </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String CONTENT = "content";
|
|
|
|
|
|
|
|
|
|
// 通用数据列,含义根据MIME类型决定,用于整数数据类型
|
|
|
|
|
/**
|
|
|
|
|
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
|
|
|
|
|
* integer data type
|
|
|
|
|
* <P> 类型:INTEGER </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String DATA1 = "data1";
|
|
|
|
|
|
|
|
|
|
// 同上,用于第二个整数数据列
|
|
|
|
|
/**
|
|
|
|
|
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
|
|
|
|
|
* integer data type
|
|
|
|
|
* <P> 类型:INTEGER </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String DATA2 = "data2";
|
|
|
|
|
|
|
|
|
|
// 同上,用于文本数据类型的第一列
|
|
|
|
|
/**
|
|
|
|
|
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
|
|
|
|
|
* TEXT data type
|
|
|
|
|
* <P> 类型:TEXT </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String DATA3 = "data3";
|
|
|
|
|
|
|
|
|
|
// 同上,用于文本数据类型的第二列
|
|
|
|
|
/**
|
|
|
|
|
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
|
|
|
|
|
* TEXT data type
|
|
|
|
|
* <P> 类型:TEXT </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String DATA4 = "data4";
|
|
|
|
|
|
|
|
|
|
// 同上,用于文本数据类型的第三列
|
|
|
|
|
/**
|
|
|
|
|
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
|
|
|
|
|
* TEXT data type
|
|
|
|
|
* <P> 类型:TEXT </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String DATA5 = "data5";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 定义一个静态内部类,代表文本笔记,并实现DataColumns接口
|
|
|
|
|
public static final class TextNote implements DataColumns {
|
|
|
|
|
// 指示文本是否为检查列表模式的标志
|
|
|
|
|
/**
|
|
|
|
|
* Mode to indicate the text in check list mode or not
|
|
|
|
|
* <P> 类型:Integer 1:check list mode 0: normal mode </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String MODE = DATA1;
|
|
|
|
|
|
|
|
|
|
// 检查列表模式的常量值
|
|
|
|
|
public static final int MODE_CHECK_LIST = 1;
|
|
|
|
|
|
|
|
|
|
// 文本笔记的内容类型(目录)
|
|
|
|
|
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note";
|
|
|
|
|
|
|
|
|
|
// 文本笔记的内容类型(单个项)
|
|
|
|
|
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";
|
|
|
|
|
|
|
|
|
|
// 文本笔记的内容URI
|
|
|
|
|
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 定义一个静态内部类,代表电话笔记,并实现DataColumns接口
|
|
|
|
|
public static final class CallNote implements DataColumns {
|
|
|
|
|
// 该记录的通话日期
|
|
|
|
|
/**
|
|
|
|
|
* Call date for this record
|
|
|
|
|
* <P> 类型:INTEGER (long) </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String CALL_DATE = DATA1;
|
|
|
|
|
|
|
|
|
|
// 该记录的电话号码
|
|
|
|
|
/**
|
|
|
|
|
* Phone number for this record
|
|
|
|
|
* <P> 类型:TEXT </P>
|
|
|
|
|
*/
|
|
|
|
|
public static final String PHONE_NUMBER = DATA3;
|
|
|
|
|
|
|
|
|
|
// 电话笔记的内容类型(目录)
|
|
|
|
|
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";
|
|
|
|
|
|
|
|
|
|
// 电话笔记的内容类型(单个项)
|
|
|
|
|
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";
|
|
|
|
|
|
|
|
|
|
// 电话笔记的内容URI
|
|
|
|
|
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");
|
|
|
|
|
}
|
|
|
|
|
java/net,micode.notes/NotesDatabaseHelper
|
|
|
|
|
// 定义创建note表的SQL语句
|
|
|
|
|
private static final String CREATE_NOTE_TABLE_SQL =
|
|
|
|
|
"CREATE TABLE " + TABLE.NOTE + "(" + // 创建一个名为TABLE.NOTE(即"note")的表
|
|
|
|
|
NoteColumns.ID + " INTEGER PRIMARY KEY," + // 定义一个名为ID的列,数据类型为INTEGER,并设置为主键
|
|
|
|
|
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为PARENT_ID的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为ALERTED_DATE的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为BG_COLOR_ID的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 定义一个名为CREATED_DATE的列,数据类型为INTEGER,不允许为空,默认值为当前时间的毫秒数
|
|
|
|
|
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为HAS_ATTACHMENT的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 定义一个名为MODIFIED_DATE的列,数据类型为INTEGER,不允许为空,默认值为当前时间的毫秒数
|
|
|
|
|
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为NOTES_COUNT的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + // 定义一个名为SNIPPET的列,数据类型为TEXT,不允许为空,默认值为空字符串
|
|
|
|
|
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为TYPE的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为WIDGET_ID的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + // 定义一个名为WIDGET_TYPE的列,数据类型为INTEGER,不允许为空,默认值为-1
|
|
|
|
|
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为SYNC_ID的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为LOCAL_MODIFIED的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为ORIGIN_PARENT_ID的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + // 定义一个名为GTASK_ID的列,数据类型为TEXT,不允许为空,默认值为空字符串
|
|
|
|
|
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + // 定义一个名为VERSION的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
")"; // SQL语句结束
|
|
|
|
|
// 定义创建数据表的SQL语句
|
|
|
|
|
private static final String CREATE_DATA_TABLE_SQL =
|
|
|
|
|
"CREATE TABLE " + TABLE.DATA + "(" + // 创建一个名为TABLE.DATA的表
|
|
|
|
|
DataColumns.ID + " INTEGER PRIMARY KEY," + // 定义一个名为ID的列,数据类型为INTEGER,并设置为主键
|
|
|
|
|
DataColumns.MIME_TYPE + " TEXT NOT NULL," + // 定义一个名为MIME_TYPE的列,数据类型为TEXT,不允许为空
|
|
|
|
|
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + // 定义一个名为NOTE_ID的列,数据类型为INTEGER,不允许为空,默认值为0
|
|
|
|
|
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 定义一个名为CREATED_DATE的列,数据类型为INTEGER,不允许为空,默认值为当前时间的毫秒数(这里似乎是一个错误,因为应该使用DataColumns的前缀来保持一致性,但这里用了NoteColumns)
|
|
|
|
|
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 定义一个名为MODIFIED_DATE的列,数据类型为INTEGER,不允许为空,默认值为当前时间的毫秒数(同样,这里应该使用DataColumns前缀)
|
|
|
|
|
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," + // 定义一个名为CONTENT的列,数据类型为TEXT,不允许为空,默认值为空字符串
|
|
|
|
|
DataColumns.DATA1 + " INTEGER," + // 定义一个名为DATA1的列,数据类型为INTEGER
|
|
|
|
|
DataColumns.DATA2 + " INTEGER," + // 定义一个名为DATA2的列,数据类型为INTEGER
|
|
|
|
|
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," + // 定义一个名为DATA3的列,数据类型为TEXT,不允许为空,默认值为空字符串
|
|
|
|
|
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + // 定义一个名为DATA4的列,数据类型为TEXT,不允许为空,默认值为空字符串
|
|
|
|
|
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + // 定义一个名为DATA5的列,数据类型为TEXT,不允许为空,默认值为空字符串
|
|
|
|
|
")"; // SQL语句结束
|
|
|
|
|
// 定义创建索引的SQL语句,如果索引不存在则创建
|
|
|
|
|
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
|
|
|
|
|
"CREATE INDEX IF NOT EXISTS note_id_index ON " + // 创建一个名为note_id_index的索引,如果它不存在
|
|
|
|
|
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");"; // 在TABLE.DATA表的NOTE_ID列上创建索引
|
|
|
|
|
// 定义一个触发器,当更新TABLE.NOTE表的PARENT_ID列后,增加对应文件夹的笔记数
|
|
|
|
|
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
|
|
|
|
|
"CREATE TRIGGER increase_folder_count_on_update "+ // 创建一个名为increase_folder_count_on_update的触发器
|
|
|
|
|
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + // 在TABLE.NOTE表的PARENT_ID列更新后触发
|
|
|
|
|
" BEGIN " +
|
|
|
|
|
" UPDATE " + TABLE.NOTE + // 更新TABLE.NOTE表
|
|
|
|
|
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" + // 将NOTES_COUNT列的值增加1
|
|
|
|
|
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + // 更新条件为ID等于新的PARENT_ID
|
|
|
|
|
" END"; // 触发器结束
|
|
|
|
|
// 定义一个触发器,当更新TABLE.NOTE表的PARENT_ID列后,减少对应文件夹的笔记数(如果笔记数大于0)
|
|
|
|
|
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
|
|
|
|
|
// ...(与上面的触发器类似,但操作是减少笔记数,并且有条件判断NOTES_COUNT > 0)
|
|
|
|
|
// 定义一个触发器,当向TABLE.NOTE表插入新记录后,增加对应文件夹的笔记数
|
|
|
|
|
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
|
|
|
|
|
// ...(与第一个更新触发器类似,但触发条件是插入操作)
|
|
|
|
|
// 定义一个静态常量字符串,用于创建当删除笔记时减少文件夹计数量的触发器
|
|
|
|
|
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
|
|
|
|
|
"CREATE TRIGGER decrease_folder_count_on_delete " + // 创建名为decrease_folder_count_on_delete的触发器
|
|
|
|
|
" AFTER DELETE ON " + TABLE.NOTE + // 当在NOTE表上执行删除操作后
|
|
|
|
|
" BEGIN " + // 开始触发器主体
|
|
|
|
|
" UPDATE " + TABLE.NOTE + // 更新NOTE表
|
|
|
|
|
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" + // 将NOTES_COUNT字段的值减1
|
|
|
|
|
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID + // 在满足ID等于被删除记录的PARENT_ID的条件下
|
|
|
|
|
" AND " + NoteColumns.NOTES_COUNT + ">0;" + // 并且NOTES_COUNT大于0时
|
|
|
|
|
" END"; // 结束触发器主体
|
|
|
|
|
|
|
|
|
|
// 定义一个静态常量字符串,用于创建当插入类型为NOTE的数据时更新笔记内容的触发器
|
|
|
|
|
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
|
|
|
|
|
// 省略具体创建触发器的SQL语句,与上面类似,但用于插入操作后更新笔记内容
|
|
|
|
|
|
|
|
|
|
// 定义一个静态常量字符串,用于创建当类型为NOTE的数据更新时更新笔记内容的触发器
|
|
|
|
|
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
|
|
|
|
|
// 省略具体创建触发器的SQL语句,与上面类似,但用于更新操作后更新笔记内容
|
|
|
|
|
|
|
|
|
|
// 定义一个静态常量字符串,用于创建当类型为NOTE的数据删除时更新笔记内容的触发器
|
|
|
|
|
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
|
|
|
|
|
// 省略具体创建触发器的SQL语句,与上面类似,但用于删除操作后更新笔记内容为空
|
|
|
|
|
|
|
|
|
|
// 定义一个静态常量字符串,用于创建当删除笔记时删除相关数据的触发器
|
|
|
|
|
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
|
|
|
|
|
// 省略具体创建触发器的SQL语句,用于删除与被删除笔记相关的数据
|
|
|
|
|
|
|
|
|
|
// 定义一个静态常量字符串,用于创建当删除文件夹时删除相关笔记的触发器
|
|
|
|
|
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
|
|
|
|
|
// 省略具体创建触发器的SQL语句,用于删除与被删除文件夹相关的笔记
|
|
|
|
|
|
|
|
|
|
// 定义一个静态常量字符串,用于创建当文件夹被移动到回收站时移动相关笔记的触发器
|
|
|
|
|
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
|
|
|
|
|
// 省略具体创建触发器的SQL语句,用于将被移动到回收站的文件夹下的笔记也移动到回收站
|
|
|
|
|
|
|
|
|
|
// NotesDatabaseHelper类的构造函数,用于初始化数据库帮助类
|
|
|
|
|
public NotesDatabaseHelper(Context context) {
|
|
|
|
|
super(context, DB_NAME, null, DB_VERSION); // 调用父类构造函数初始化数据库
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建笔记表的方法
|
|
|
|
|
public void createNoteTable(SQLiteDatabase db) {
|
|
|
|
|
db.execSQL(CREATE_NOTE_TABLE_SQL); // 执行创建笔记表的SQL语句
|
|
|
|
|
reCreateNoteTableTriggers(db); // 重新创建笔记表相关的触发器
|
|
|
|
|
createSystemFolder(db); // 创建系统文件夹(此方法的具体实现在代码段之外)
|
|
|
|
|
Log.d(TAG, "note table has been created"); // 打印日志,表示笔记表已创建
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重新创建笔记表相关触发器的方法
|
|
|
|
|
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
|
|
|
|
|
// 依次删除已存在的触发器,然后重新创建它们
|
|
|
|
|
// 这里省略了具体的删除和创建触发器的SQL语句,但基本逻辑是:先删除,再创建
|
|
|
|
|
}/*
|
|
|
|
|
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
|
|
|
*
|
|
|
|
|
* 这段注释声明了文件的版权信息,包括版权年份、版权所有者和使用许可。
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package java.lang;
|
|
|
|
|
|
|
|
|
|
/** The CharacterData class encapsulates the large tables found in
|
|
|
|
|
Java.lang.Character. */
|
|
|
|
|
|
|
|
|
|
// 这是一个类注释,说明CharacterData类封装了Java.lang.Character中的大型表。
|
|
|
|
|
// 但注意,这里的注释可能有些误导,因为CharacterDataUndefined实际上是CharacterData的一个子类。
|
|
|
|
|
|
|
|
|
|
class CharacterDataUndefined extends CharacterData {
|
|
|
|
|
|
|
|
|
|
// CharacterDataUndefined类继承自CharacterData类。
|
|
|
|
|
|
|
|
|
|
int getProperties(int ch) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
// 返回字符ch的属性,这里总是返回0,表示没有定义任何属性。
|
|
|
|
|
|
|
|
|
|
int getType(int ch) {
|
|
|
|
|
return Character.UNASSIGNED;
|
|
|
|
|
}
|
|
|
|
|
// 返回字符ch的类型,这里总是返回Character.UNASSIGNED,表示字符未分配。
|
|
|
|
|
|
|
|
|
|
boolean isJavaIdentifierStart(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否可以作为Java标识符的起始字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isJavaIdentifierPart(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否可以作为Java标识符的一部分,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isUnicodeIdentifierStart(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否可以作为Unicode标识符的起始字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isUnicodeIdentifierPart(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否可以作为Unicode标识符的一部分,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isIdentifierIgnorable(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是一个可忽略的标识符字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isEmoji(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是一个emoji,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isEmojiPresentation(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否以emoji形式呈现,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isEmojiModifier(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是一个emoji修饰符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isEmojiModifierBase(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是一个emoji修饰符基础字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isEmojiComponent(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是一个emoji组件,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isExtendedPictographic(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是一个扩展的象形文字,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
int toLowerCase(int ch) {
|
|
|
|
|
return ch;
|
|
|
|
|
}
|
|
|
|
|
// 将字符ch转换为小写形式,这里总是返回原字符,表示没有转换。
|
|
|
|
|
|
|
|
|
|
int toUpperCase(int ch) {
|
|
|
|
|
return ch;
|
|
|
|
|
}
|
|
|
|
|
// 将字符ch转换为大写形式,这里总是返回原字符,表示没有转换。
|
|
|
|
|
|
|
|
|
|
int toTitleCase(int ch) {
|
|
|
|
|
return ch;
|
|
|
|
|
}
|
|
|
|
|
// 将字符ch转换为标题形式(通常是大写),这里总是返回原字符,表示没有转换。
|
|
|
|
|
|
|
|
|
|
int digit(int ch, int radix) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
// 返回字符ch在指定基数radix下的数字值,这里总是返回-1,表示不是有效的数字。
|
|
|
|
|
|
|
|
|
|
int getNumericValue(int ch) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
// 返回字符ch的数值,这里总是返回-1,表示没有定义数值。
|
|
|
|
|
|
|
|
|
|
boolean isDigit(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是一个数字字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isLowerCase(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是小写字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isUpperCase(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是大写字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
boolean isWhitespace(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是空白字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
byte getDirectionality(int ch) {
|
|
|
|
|
return Character.DIRECTIONALITY_UNDEFINED;
|
|
|
|
|
}
|
|
|
|
|
// 返回字符ch的方向性,这里总是返回Character.DIRECTIONALITY_UNDEFINED,表示方向性未定义。
|
|
|
|
|
|
|
|
|
|
boolean isMirrored(int ch) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 判断字符ch是否是镜像字符,这里总是返回false。
|
|
|
|
|
|
|
|
|
|
static final CharacterData instance = new CharacterDataUndefined();
|
|
|
|
|
// 创建一个CharacterDataUndefined的实例,作为这个类的唯一实例。
|
|
|
|
|
|
|
|
|
|
private CharacterDataUndefined() {};
|
|
|
|
|
// 私有构造函数,防止外部创建CharacterDataUndefined的实例。
|
|
|
|
|
}<!DOCTYPE html>
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>小米便签示例</title>
|
|
|
|
|
<link rel="stylesheet" href="styles.css">
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div id="app">
|
|
|
|
|
<h1>小米便签</h1>
|
|
|
|
|
|
|
|
|
|
<!-- 便签列表的容器 -->
|
|
|
|
|
<div id="note-list">
|
|
|
|
|
<!-- 便签项将通过JavaScript动态生成并插入到这里 -->
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 新建便签的表单 -->
|
|
|
|
|
<form id="new-note-form">
|
|
|
|
|
<input type="text" id="note-title" placeholder="输入标题">
|
|
|
|
|
<textarea id="note-content" placeholder="输入内容"></textarea>
|
|
|
|
|
<button type="submit">添加便签</button>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script src="scripts.js"></script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
/* 基本样式重置 */
|
|
|
|
|
body, html {
|
|
|
|
|
margin: 0;
|
|
|
|
|
padding: 0;
|
|
|
|
|
font-family: Arial, sans-serif;
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 应用容器的样式 */
|
|
|
|
|
#app {
|
|
|
|
|
width: 80%;
|
|
|
|
|
max-width: 600px;
|
|
|
|
|
margin: 20px auto;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 标题样式 */
|
|
|
|
|
h1 {
|
|
|
|
|
text-align: center;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 便签列表的样式 */
|
|
|
|
|
#note-list {
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 单个便签项的样式 */
|
|
|
|
|
.note {
|
|
|
|
|
border-bottom: 1px solid #ddd;
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
position: relative;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.note:last-child {
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 便签标题的样式 */
|
|
|
|
|
.note-title {
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
color: #333;
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 便签内容的样式 */
|
|
|
|
|
.note-content {
|
|
|
|
|
color: #666;
|
|
|
|
|
word-wrap: break-word; /* 防止长单词或URL破坏布局 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 删除按钮的样式 */
|
|
|
|
|
.delete-button {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 10px;
|
|
|
|
|
right: 10px;
|
|
|
|
|
background-color: #ff5722;
|
|
|
|
|
color: #fff;
|
|
|
|
|
border: none;
|
|
|
|
|
padding: 5px 10px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.delete-button:hover {
|
|
|
|
|
background-color: #e64a19;
|
|
|
|
|
}// 获取页面元素
|
|
|
|
|
const noteList = document.getElementById('note-list');
|
|
|
|
|
const newNoteForm = document.getElementById('new-note-form');
|
|
|
|
|
const noteTitleInput = document.getElementById('note-title');
|
|
|
|
|
const noteContentInput = document.getElementById('note-content');
|
|
|
|
|
|
|
|
|
|
// 存储便签数据的数组
|
|
|
|
|
let notes = [];
|
|
|
|
|
|
|
|
|
|
// 渲染便签列表到页面
|
|
|
|
|
function renderNotes() {
|
|
|
|
|
noteList.innerHTML = ''; // 清空现有便签
|
|
|
|
|
notes.forEach((note, index) => {
|
|
|
|
|
// 创建一个新的便签项div
|
|
|
|
|
const noteElement = document.createElement('div');
|
|
|
|
|
noteElement.className = 'note';
|
|
|
|
|
|
|
|
|
|
// 创建标题元素并添加到便签项中
|
|
|
|
|
const titleElement = document.createElement('div');
|
|
|
|
|
titleElement.className = 'note-title';
|
|
|
|
|
titleElement.textContent = note.title;
|
|
|
|
|
noteElement.appendChild(titleElement);
|
|
|
|
|
|
|
|
|
|
// 创建内容元素并添加到便签项中
|
|
|
|
|
const contentElement = document.createElement('div');
|
|
|
|
|
contentElement.className = 'note-content';
|
|
|
|
|
contentElement.textContent = note.content;
|
|
|
|
|
noteElement.appendChild(contentElement);
|
|
|
|
|
|
|
|
|
|
// 创建删除按钮并添加到便签项中
|
|
|
|
|
const deleteButton = document.createElement('button');
|
|
|
|
|
deleteButton.className = 'delete-button';
|
|
|
|
|
deleteButton.textContent = '删除';
|
|
|
|
|
deleteButton.addEventListener('click', () => {
|
|
|
|
|
// 从数组中移除便签并重新渲染列表
|
|
|
|
|
notes.splice(index, 1);
|
|
|
|
|
renderNotes();
|
|
|
|
|
});
|
|
|
|
|
noteElement.appendChild(deleteButton);
|
|
|
|
|
|
|
|
|
|
// 将便签项添加到列表中
|
|
|
|
|
noteList.appendChild(noteElement);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 提交新便签的表单事件监听器
|
|
|
|
|
newNoteForm.addEventListener('submit', (event) => {
|
|
|
|
|
event.preventDefault(); // 阻止表单的默认提交行为
|
|
|
|
|
|
|
|
|
|
// 获取表单输入的值
|
|
|
|
|
const title = noteTitleInput.value.trim();
|
|
|
|
|
const content = noteContentInput.value.trim();
|
|
|
|
|
|
|
|
|
|
// 检查标题和内容是否为空
|
|
|
|
|
if (title && content) {
|
|
|
|
|
// 创建一个新的便签对象并添加到数组中
|
|
|
|
|
const newNote = { title, content };
|
|
|
|
|
notes.push(newNote);
|
|
|
|
|
|
|
|
|
|
// 清空表单输入
|
|
|
|
|
noteTitleInput.value = '';
|
|
|
|
|
noteContentInput.value = '';
|
|
|
|
|
|
|
|
|
|
// 重新渲染便签列表
|
|
|
|
|
renderNotes();
|
|
|
|
|
} else {
|
|
|
|
|
alert('标题和内容都不能为空!');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 初始化渲染便签列表(在加载页面时调用)
|
|
|
|
|
renderNotes();
|