You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
test123/NotesProvider.java

352 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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;
import android.content.ContentValues;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
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;
/**
* 笔记内容提供者,用于提供笔记数据
*/
public class NotesProvider extends ContentProvider {
// 用于匹配Uri的UriMatcher
private static final UriMatcher mMatcher;
// 数据库帮助类实例
private NotesDatabaseHelper mHelper;
// 日志标签
private static final String TAG = "NotesProvider";
// Uri匹配码常量
private static final int URI_NOTE = 1;// 匹配笔记列表
private static final int URI_NOTE_ITEM = 2;; // 匹配单个笔记
private static final int URI_DATA = 3;// 匹配数据列表
private static final int URI_DATA_ITEM = 4;// 匹配单个数据项
private static final int URI_SEARCH = 5; // 匹配搜索结果
private static final int URI_SEARCH_SUGGEST = 6;// 匹配搜索建议
static { // 初始化UriMatcher用于匹配Uri
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);// 匹配数据列表
mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM);// 匹配单个数据项
mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH);// 匹配搜索结果
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST);// 匹配搜索建议
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST); // 匹配带参数的搜索建议
}
/**
* 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 定义了搜索结果中显示的列。
* x'0A' 在sqlite中表示 '\n' 字符。为了在搜索结果中显示更多信息,
* 我们将标题和内容中的 '\n' 和空白字符进行修剪。
*/
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 定义了搜索笔记片段的查询语句。
* 该查询从笔记表中选取符合条件的记录,并排除垃圾文件夹中的笔记。
*/
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;
// 当ContentProvider被创建时调用
@Override
public boolean onCreate() {
// 获取NotesDatabaseHelper的单例实例
mHelper = NotesDatabaseHelper.getInstance(getContext());
// 返回true表示ContentProvider初始化成功
return true;
}
// 重写query方法以响应ContentProvider的查询请求
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
Cursor c = null;// 初始化Cursor对象
SQLiteDatabase db = mHelper.getReadableDatabase();// 获取可读数据库实例
String id = null; // 初始化id变量
// 根据Uri匹配结果执行不同的查询操作
switch (mMatcher.match(uri)) {
case URI_NOTE:// 匹配笔记列表
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder);// 执行查询操作
break;
case URI_NOTE_ITEM:// 匹配单个笔记
id = uri.getPathSegments().get(1);// 从Uri中获取笔记ID
c = db.query(TABLE.NOTE, projection, NoteColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs, null, null, sortOrder); // 执行查询操作
break;
case URI_DATA:// 匹配数据列表
c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null,
sortOrder);// 执行查询操作
break;
case URI_DATA_ITEM:// 匹配单个数据项
id = uri.getPathSegments().get(1); // 从Uri中获取数据项ID
c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs, null, null, sortOrder);// 执行查询操作
break;
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");
}
// 初始化搜索字符串
String searchString = null;
// 如果Uri匹配搜索建议
if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {
// 如果Uri的路径段数量大于1则获取搜索字符串
if (uri.getPathSegments().size() > 1) {
searchString = uri.getPathSegments().get(1);
}
} else {
// 否则从Uri的查询参数中获取搜索字符串
searchString = uri.getQueryParameter("pattern");
}
// 如果搜索字符串为空则返回null
if (TextUtils.isEmpty(searchString)) {
return null;
}
// 尝试执行搜索查询
try {
// 格式化搜索字符串以进行模糊匹配
searchString = String.format("%%%s%%", searchString);
// 执行原始查询,获取匹配的笔记片段
c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY,
new String[] { searchString });
} catch (IllegalStateException ex) {
// 如果发生异常,记录错误日志
Log.e(TAG, "got exception: " + ex.toString());
}// 结束switch语句的当前分支
break;
// 如果Uri不匹配已知情况则抛出异常
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}// 如果Cursor不为空设置通知Uri
if (c != null) {
c.setNotificationUri(getContext().getContentResolver(), uri);
}// 返回Cursor
return c;
}
// 重写insert方法以响应ContentProvider的插入请求
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = mHelper.getWritableDatabase();
// 获取可写数据库实例
long dataId = 0, noteId = 0, insertedId = 0; // 初始化ID变量
// 根据Uri匹配结果执行不同的插入操作
switch (mMatcher.match(uri)) {
case URI_NOTE: // 匹配笔记插入
insertedId = noteId = db.insert(TABLE.NOTE, null, values);// 插入笔记并获取ID
break;
case URI_DATA:// 匹配数据插入
// 检查ContentValues中是否包含笔记ID
if (values.containsKey(DataColumns.NOTE_ID)) {// 获取笔记ID
noteId = values.getAsLong(DataColumns.NOTE_ID);
} else {
// 如果没有笔记ID记录调试信息
Log.d(TAG, "Wrong data format without note id:" + values.toString());
}
insertedId = dataId = db.insert(TABLE.DATA, null, values);// 插入数据并获取ID
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);// 如果Uri不匹配已知情况则抛出异常
}
// Notify the note uri
// 如果插入的是笔记,则通知内容解析器变更
if (noteId > 0) {
// 使用ContentUris.withAppendedId构建具体的笔记Uri并通知变更
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);
}
// Notify the data uri
// 如果插入的是数据,则通知内容解析器变更
if (dataId > 0) {
// 使用ContentUris.withAppendedId构建具体的数据Uri并通知变更
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);
}
// 返回插入操作后带ID的Uri
return ContentUris.withAppendedId(uri, insertedId);
}
// 重写delete方法以响应ContentProvider的删除请求
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;// 初始化删除计数器
String id = null; // 初始化ID变量
SQLiteDatabase db = mHelper.getWritableDatabase();// 获取可写数据库实例
boolean deleteData = false; // 初始化是否删除数据的标志
// 根据Uri匹配结果执行不同的删除操作
switch (mMatcher.match(uri)) {
case URI_NOTE:// 匹配笔记删除
// 添加条件确保只删除ID大于0的笔记
selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 ";
count = db.delete(TABLE.NOTE, selection, selectionArgs);// 执行删除操作
break;
case URI_NOTE_ITEM:// 匹配特定笔记项删除
id = uri.getPathSegments().get(1); // 获取笔记ID
// ID小于等于0的是系统文件夹不允许删除到垃圾桶
/**
* ID that smaller than 0 is system folder which is not allowed to
* trash
*/
long noteId = Long.valueOf(id);
if (noteId <= 0) {
break;// 如果是系统文件夹,则跳出
}
count = db.delete(TABLE.NOTE,// 执行删除操作
NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
break;
case URI_DATA:// 匹配数据删除
count = db.delete(TABLE.DATA, selection, selectionArgs);// 执行删除操作
deleteData = true;// 设置删除数据标志
break;
case URI_DATA_ITEM:// 匹配特定数据项删除
id = uri.getPathSegments().get(1);// 获取数据ID
count = db.delete(TABLE.DATA,// 执行删除操作
DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
deleteData = true;// 设置删除数据标志
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri); // 如果Uri不匹配已知情况则抛出异常
} // 如果删除了记录,则通知内容解析器变更
if (count > 0) {
// 如果删除的是数据则通知笔记Uri变更
if (deleteData) {
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
}// 通知原始Uri变更
getContext().getContentResolver().notifyChange(uri, null);
}// 返回删除的记录数
return count;
}
// 重写update方法以响应ContentProvider的更新请求
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0;// 初始化更新计数器
String id = null;// 初始化ID变量
SQLiteDatabase db = mHelper.getWritableDatabase(); // 获取可写数据库实例
boolean updateData = false;// 初始化是否更新数据的标志
// 根据Uri匹配结果执行不同的更新操作
switch (mMatcher.match(uri)) {
case URI_NOTE:// 匹配笔记更新
increaseNoteVersion(-1, selection, selectionArgs); // 更新笔记版本
count = db.update(TABLE.NOTE, values, selection, selectionArgs);// 执行更新操作
break;
case URI_NOTE_ITEM:// 匹配特定笔记项更新
id = uri.getPathSegments().get(1); // 获取笔记ID
increaseNoteVersion(Long.valueOf(id), selection, selectionArgs);// 更新笔记版本
count = db.update(TABLE.NOTE, values, NoteColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs);// 执行更新操作
break;
case URI_DATA:// 匹配数据更新
count = db.update(TABLE.DATA, values, selection, selectionArgs); // 执行更新操作
updateData = true;// 设置更新数据标志
break;
case URI_DATA_ITEM:// 匹配特定数据项更新
id = uri.getPathSegments().get(1);// 获取数据ID
count = db.update(TABLE.DATA, values, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs); // 执行更新操作
updateData = true;// 设置更新数据标志
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);// 如果Uri不匹配已知情况则抛出异常
}
// 如果更新了记录,则通知内容解析器变更
if (count > 0) {
// 如果更新的是数据则通知笔记Uri变更
if (updateData) {
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
} // 通知原始Uri变更
getContext().getContentResolver().notifyChange(uri, null);
} // 返回更新的记录数
return count;
}
// 私有方法,用于解析选择条件
private String parseSelection(String selection) {
// 如果选择条件不为空则添加AND连接符否则返回空字符串
return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
}
// 私有方法,用于增加笔记的版本号
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
StringBuilder sql = new StringBuilder(120);
// 创建StringBuilder对象用于构建SQL语句
sql.append("UPDATE "); // 添加更新SQL语句的开始部分
sql.append(TABLE.NOTE);// 指定更新的表
sql.append(" SET ");// 添加设置字段的开始部分
sql.append(NoteColumns.VERSION);// 指定要更新的版本字段
sql.append("=" + NoteColumns.VERSION + "+1 "); // 将版本号加1
// 如果提供了特定的ID或者有选择条件则添加WHERE子句
if (id > 0 || !TextUtils.isEmpty(selection)) {
sql.append(" WHERE ");
}
if (id > 0) {
// 如果提供了特定的ID则将其作为更新条件
sql.append(NoteColumns.ID + "=" + String.valueOf(id));
}
if (!TextUtils.isEmpty(selection)) {
// 如果有选择条件,则处理选择条件和参数
String selectString = id > 0 ? parseSelection(selection) : selection;
// 替换选择条件中的占位符为实际的参数值
for (String args : selectionArgs) {
selectString = selectString.replaceFirst("\\?", args);
}
sql.append(selectString);
}
// 执行构建的SQL语句以更新笔记版本
mHelper.getWritableDatabase().execSQL(sql.toString());
}
// 重写getType方法以响应ContentProvider的getType请求
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
// TODO: 根据Uri返回相应的MIME类型此处需要实现具体的逻辑
return null;
}
}