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.
text123/NotesProvider_1.java

402 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;
// 表示单个笔记的Uri匹配码
private static final int URI_NOTE_ITEM = 2;
// 表示数据的Uri匹配码
private static final int URI_DATA = 3;
// 表示单个数据项的Uri匹配码
private static final int URI_DATA_ITEM = 4;
// 表示搜索的Uri匹配码
private static final int URI_SEARCH = 5;
// 表示搜索建议的Uri匹配码
private static final int URI_SEARCH_SUGGEST = 6;
// 静态代码块用于初始化UriMatcher
static {
// 创建一个UriMatcher对象初始匹配码为UriMatcher.NO_MATCH
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 添加一个匹配规则,匹配以"note"结尾的Uri匹配码为URI_NOTE
mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE);
// 添加一个匹配规则,匹配以"note/"开头并后跟一个数字的Uri匹配码为URI_NOTE_ITEM
mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM);
// 添加一个匹配规则,匹配以"data"结尾的Uri匹配码为URI_DATA
mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA);
// 添加一个匹配规则,匹配以"data/"开头并后跟一个数字的Uri匹配码为URI_DATA_ITEM
mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM);
// 添加一个匹配规则,匹配以"search"结尾的Uri匹配码为URI_SEARCH
mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH);
// 添加一个匹配规则匹配以SearchManager.SUGGEST_URI_PATH_QUERY结尾的Uri匹配码为URI_SEARCH_SUGGEST
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST);
// 添加一个匹配规则匹配以SearchManager.SUGGEST_URI_PATH_QUERY开头并后跟任意字符的Uri匹配码为URI_SEARCH_SUGGEST
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST);
}
/**
* 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;
// 定义搜索片段的查询语句
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;
// 当内容提供者创建时调用的方法
@Override
public boolean onCreate() {
// 获取数据库帮助类的单例实例
mHelper = NotesDatabaseHelper.getInstance(getContext());
// 返回true表示内容提供者创建成功
return true;
}
// 处理查询请求的方法
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// 用于存储查询结果的游标
Cursor c = null;
// 获取可读的数据库实例
SQLiteDatabase db = mHelper.getReadableDatabase();
// 用于存储从Uri中解析出的ID
String id = null;
// 根据Uri匹配结果进行不同的查询操作
switch (mMatcher.match(uri)) {
case URI_NOTE:
// 查询笔记表,返回所有符合条件的笔记
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder);
break;
case URI_NOTE_ITEM:
// 从Uri中获取笔记的ID
id = uri.getPathSegments().get(1);
// 查询笔记表返回指定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:
// 从Uri中获取数据的ID
id = uri.getPathSegments().get(1);
// 查询数据表返回指定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");
}
// 从Uri中获取搜索字符串
String searchString = null;
if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {
if (uri.getPathSegments().size() > 1) {
searchString = uri.getPathSegments().get(1);
}
} else {
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());
}
break;
default:
// 如果Uri不匹配任何已知模式抛出异常
throw new IllegalArgumentException("Unknown URI " + uri);
}
// 如果查询结果不为空设置通知Uri
if (c!= null) {
c.setNotificationUri(getContext().getContentResolver(), uri);
}
// 返回查询结果游标
return c;
}
// 插入数据的方法根据传入的Uri和ContentValues插入数据到相应的表中
@Override
public Uri insert(Uri uri, ContentValues values) {
// 获取可写的数据库实例
SQLiteDatabase db = mHelper.getWritableDatabase();
// 用于存储插入的数据ID、笔记ID和最终插入的ID
long dataId = 0, noteId = 0, insertedId = 0;
// 根据Uri匹配结果进行不同的插入操作
switch (mMatcher.match(uri)) {
case URI_NOTE:
// 向笔记表中插入数据返回插入的笔记ID
insertedId = noteId = db.insert(TABLE.NOTE, null, values);
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());
}
// 向数据表中插入数据返回插入的数据ID
insertedId = dataId = db.insert(TABLE.DATA, null, values);
break;
default:
// 如果Uri不匹配任何已知模式抛出异常
throw new IllegalArgumentException("Unknown URI " + uri);
}
// 如果插入了笔记ID通知内容解析器该笔记的Uri已改变
if (noteId > 0) {
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);
}
// 如果插入了数据ID通知内容解析器该数据的Uri已改变
if (dataId > 0) {
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);
}
// 返回包含插入ID的Uri
return ContentUris.withAppendedId(uri, insertedId);
}
// 删除数据的方法根据传入的Uri、条件和条件参数删除相应的数据
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// 用于记录删除的行数
int count = 0;
// 用于存储从Uri中解析出的ID
String id = null;
// 获取可写的数据库实例
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:
// 从Uri中获取笔记的ID
id = uri.getPathSegments().get(1);
// 将ID转换为long类型
long noteId = Long.valueOf(id);
// 如果ID小于等于0说明是系统文件夹不允许删除直接跳出
if (noteId <= 0) {
break;
}
// 构建删除条件删除指定ID的笔记
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:
// 从Uri中获取数据的ID
id = uri.getPathSegments().get(1);
// 构建删除条件删除指定ID的数据
count = db.delete(TABLE.DATA,
DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
// 标记为删除数据
deleteData = true;
break;
default:
// 如果Uri不匹配任何已知模式抛出异常
throw new IllegalArgumentException("Unknown URI " + uri);
}
// 如果删除了数据
if (count > 0) {
// 如果删除的是数据通知内容解析器笔记的Uri已改变
if (deleteData) {
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
}
// 通知内容解析器当前Uri已改变
getContext().getContentResolver().notifyChange(uri, null);
}
// 返回删除的行数
return count;
}
// 更新数据的方法根据传入的Uri、ContentValues、条件和条件参数更新相应的数据
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// 用于记录更新的行数
int count = 0;
// 用于存储从Uri中解析出的ID
String id = null;
// 获取可写的数据库实例
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:
// 从Uri中获取笔记的ID
id = uri.getPathSegments().get(1);
// 增加指定ID笔记的版本号
increaseNoteVersion(Long.valueOf(id), selection, selectionArgs);
// 更新指定ID的笔记
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:
// 从Uri中获取数据的ID
id = uri.getPathSegments().get(1);
// 更新指定ID的数据
count = db.update(TABLE.DATA, values, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs);
// 标记为更新数据
updateData = true;
break;
default:
// 如果Uri不匹配任何已知模式抛出异常
throw new IllegalArgumentException("Unknown 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 + ')' : "");
}
// 增加笔记版本号的方法根据传入的ID、条件和条件参数更新笔记的版本号
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
// 创建一个StringBuilder用于构建SQL语句
StringBuilder sql = new StringBuilder(120);
// 添加更新的表名
sql.append("UPDATE ");
sql.append(TABLE.NOTE);
// 添加更新的字段和操作将版本号加1
sql.append(" SET ");
sql.append(NoteColumns.VERSION);
sql.append("=" + NoteColumns.VERSION + "+1 ");
// 如果ID大于0或者选择条件不为空添加WHERE子句
if (id > 0 ||!TextUtils.isEmpty(selection)) {
sql.append(" WHERE ");
}
// 如果ID大于0添加ID条件
if (id > 0) {
sql.append(NoteColumns.ID + "=" + String.valueOf(id));
}
// 如果选择条件不为空
if (!TextUtils.isEmpty(selection)) {
// 根据ID是否大于0来格式化选择条件
String selectString = id > 0? parseSelection(selection) : selection;
// 替换选择条件中的占位符为实际参数
for (String args : selectionArgs) {
selectString = selectString.replaceFirst("\\?", args);
}
// 添加格式化后的选择条件到SQL语句中
sql.append(selectString);
}
// 执行构建好的SQL语句更新笔记的版本号
mHelper.getWritableDatabase().execSQL(sql.toString());
}
// 获取Uri对应的MIME类型的方法目前未实现返回null
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}