package fkshl.activity.contentProvider;
/* Copyright (C) 2006 The Android Open Source Project
*
* 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.
*/
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import android.net.Uri;
public class UriMatcher
{
public static final int NO_MATCH = -1;
/***
*
* Creates the root node of the URI tree.
*
*
*
* @param code
* the code to match for the root URI
*/
public UriMatcher(int code){
mCode = code;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
}
private UriMatcher(){
mCode = NO_MATCH;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
}
/***
*
* Add a URI to match, and the code to return when this URI is
*
* matched. URI nodes may be exact match string, the token "*"
*
* that matches any text, or the token "#" that matches only
*
* numbers.
*
*
*
* @param authority
* the authority to match
*
* @param path
* the path to match. * may be used as a wild card for
*
* any text, and # may be used as a wild card for numbers.
*
* @param code
* the code that is returned when a URI is matched
*
* against the given components. Must be positive.
*/
public void addURI(String authority, String path, int code){
if (code < 0) {
throw new IllegalArgumentException("code " + code
+ " is invalid: it must be positive");
}
//以"/"分隔path
String[] tokens = path != null ? PATH_SPLIT_PATTERN.split(path) : null;
//判断分隔后的数组长度.并取其值
int numTokens = tokens != null ? tokens.length : 0;
//当前对象
UriMatcher node = this;
for (int i = -1; i < numTokens; i++) {
//当前循环变量小于0就取authority,否则就获取分隔后的数组的字符,并赋值给token
String token = i < 0 ? authority : tokens[i];
//把当前对象的集合赋值给children
ArrayList<UriMatcher> children = node.mChildren;
//获取其长度
int numChildren = children.size();
UriMatcher child;
int j;
for (j = 0; j < numChildren; j++) {
//获取children对象的孩子
child = children.get(j);
//判断当前的token和child对象中的mText是否相等
if (token.equals(child.mText)) {
//把child 赋值给 node;
node = child;
break;
}
}
//获取循环变量j并判断是否等于children对应的大小.也就是判断是否是最后一个
if (j == numChildren) {
// Child not found, create it
//没有发现孩子,并创建
child = new UriMatcher();
///判断当前的token是否等于"#"
if (token.equals("#")) {
//mWhich=1
child.mWhich = NUMBER;
} else if (token.equals("*")) {
//mWhich=2
child.mWhich = TEXT;
} else {
//mWhich=0
child.mWhich = EXACT;
}
//mText=当前的token
child.mText = token;
//添加到mChildren集合中
node.mChildren.add(child);
//node = child;
node = child;
}
}
//node.mCode = code;
node.mCode = code;
}
static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/");
/***
*
* Try to match against the path in a url.
*
*
*
* @param uri
* The url whose path we will match against.
*
*
*
* @return The code for the matched node (added using addURI),
*
* or -1 if there is no matched node.
*/
public int match(Uri uri){
final List<String> pathSegments = uri.getPathSegments();
final int li = pathSegments.size();
UriMatcher node = this;
if (li == 0 && uri.getAuthority() == null) {
return this.mCode;
}
for (int i = -1; i < li; i++) {
String u = i < 0 ? uri.getAuthority() : pathSegments.get(i);
ArrayList<UriMatcher> list = node.mChildren;
if (list == null) {
break;
}
node = null;
int lj = list.size();
for (int j = 0; j < lj; j++) {
UriMatcher n = list.get(j);
which_switch:
switch (n.mWhich) {
case EXACT:
if (n.mText.equals(u)) {
node = n;
}
break;
case NUMBER:
int lk = u.length();
for (int k = 0; k < lk; k++) {
char c = u.charAt(k);
if (c < '0' || c > '9') {
break which_switch;
}
}
node = n;
break;
case TEXT:
node = n;
break;
}
if (node != null) {
break;
}
}
if (node == null) {
return NO_MATCH;
}
}
return node.mCode;
}
private static final int EXACT = 0;
private static final int NUMBER = 1;
private static final int TEXT = 2;
private int mCode;
private int mWhich;
private String mText;
private final ArrayList<UriMatcher> mChildren;
}
这是android源码.
由于不懂所以就把它粘贴的项目中.所以包自然就改成自己项目的了..
package fkshl.activity.contentProvider;
import java.util.HashMap;
import java.util.Map;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import fkshl.activity.contentProviderMetaData.ContentProviderMetaData;
import fkshl.activity.contentProviderMetaData.ContentProviderMetaData.UserTableMetaData;
import fkshl.activity.dataBase.DBHelper;
public class FkshlContentProvider extends ContentProvider {
public static final UriMatcher URI_MATCHER;
public static final int FKSHL_TABLE = 1;
public static final int FKSHL_TABLE_COLUMN = 2;
public static final Map<String, String> COLUM_MAPPIGN;
public DBHelper dbHelper;
static {
/**
* uri验证
*/
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "users", 1);
URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "users/#", 2);
/**
* 列的映射
*/
COLUM_MAPPIGN = new HashMap<String, String>();
COLUM_MAPPIGN.put(UserTableMetaData._ID, UserTableMetaData._ID);
COLUM_MAPPIGN.put(UserTableMetaData.COLUMN_NAME, UserTableMetaData.COLUMN_NAME);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
switch (URI_MATCHER.match(uri)) {
case FKSHL_TABLE:
return UserTableMetaData.CONTENT_TYPE;
case FKSHL_TABLE_COLUMN:
return UserTableMetaData.CONTENT_TYPE_ITEM;
default:
throw new IllegalArgumentException("Unknown URI!!!!!" + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
SQLiteDatabase database = dbHelper.getWritableDatabase();
Long rowId = database.insert(ContentProviderMetaData.TABLE_NAME, null, values);
if (rowId > 0) {
Uri empuri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(empuri, null);
System.out.println("insert success!!!");
}
return null;
}
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
dbHelper = new DBHelper(getContext(), ContentProviderMetaData.DATABASE_NAME);
dbHelper.getReadableDatabase();
System.out.println("create database success!!");
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
// TODO Auto-generated method stub
switch (URI_MATCHER.match(uri)) {
case FKSHL_TABLE:
builder.setTables(UserTableMetaData.TABLE_NAME);
builder.setProjectionMap(COLUM_MAPPIGN);
break;
case FKSHL_TABLE_COLUMN:
builder.setTables(UserTableMetaData.TABLE_NAME);
builder.setProjectionMap(COLUM_MAPPIGN);
builder.appendWhere(UserTableMetaData.COLUMN_NAME + "="
+ uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("uri error !!!!" + uri);
}
String orderBy;
if (TextUtils.isEmpty(sortOrder)) {
orderBy = UserTableMetaData.ORDER_BY + " Desc";
} else {
orderBy = sortOrder;
}
SQLiteDatabase database = dbHelper.getReadableDatabase();
Cursor c = builder.query(database, projection, selection, selectionArgs, null, null, orderBy);
c.setNotificationUri(getContext().getContentResolver(), uri);
System.out.println("seach end!!!!");
return c;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
做的时间发现一个问题.
这是之前发现在按官方提示做的.
URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "/users", 1);
URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "/users/#", 2);
可是在getType中怎么都走default.都是抛异常.
05-22 09:39:23.449: ERROR/AndroidRuntime(581): java.lang.IllegalArgumentException: uri error !!!!content://fkshl.activity.contentProvider.FkshlContentProvider/users
最后看了源码,改成了.
URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "users", 1);
URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "users/#", 2);
这样就好.
原因是在add方法中它会以"/"分隔users/#,然后把分隔后的字符串像树型的一级一级保存在mChildren中.如果在users/#前面加"/",哪么就导致在"/"之前有一个空字符(content://fkshl.activity.contentProvider.FkshlContentProvider//users),而在我的项目中调用getType方法传过来时的uir中没有这样的一个空字符(content://fkshl.activity.contentProvider.FkshlContentProvider/users)
没有.