`

android的UriMatcher类

阅读更多
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)
没有.
分享到:
评论

相关推荐

    Android Uri

    Android 系统提供了两个用于操作 Uri 的工具类,分别为 UriMatcher 和 ContentUris 。 1. UriMatcher UriMatcher 类主要用于匹配 Uri。使用方法如下: 首先,初始化 UriMatcher 对象:`UriMatcher matcher = new ...

    Android部分源码——content包

    `UriMatcher`是一个辅助类,用于解析和匹配URI,帮助确定调用哪个`ContentProvider`的方法。它可以通过添加模式来预先配置,然后在处理URI时返回匹配的代码,这样可以提高效率并减少错误。 此外,`Cursor`是`...

    android系统函数大全.rar_android_android系统_安卓函数大全_安卓系统函数_系统函数

    9. **SQLite数据库**:Android系统自带SQLite数据库,`SQLiteOpenHelper`类用于数据库的创建和版本管理,`SQLiteDatabase`类提供CRUD(创建、读取、更新、删除)操作。 10. **SharedPreferences**:...

    Android中ContentProvider的示例

    1. **定义UriMatcher**: UriMatcher是一个工具类,用于解析输入的Uri并返回匹配的代码。在ContentProvider中,我们需要为每种类型的操作(例如查询、插入、更新和删除)以及每个数据表定义一个唯一的代码。例如,...

    Android版俄罗斯方块

    ContentProvider是Android中数据共享的桥梁,虽然在俄罗斯方块这类单机游戏中,ContentProvider的应用不常见,但在需要存储和读取游戏进度、高分记录时,可以利用ContentProvider与其他应用分享数据。开发者需要实现...

    android开发培训课件ppt

    开发者需要实现ContentProvider类,定义 UriMatcher、query()、insert()、update()和delete()等方法。 此外,PPT还可能涉及了SQLite数据库的使用。SQLite是Android内置的关系型数据库,适用于存储结构化的数据。...

    android登录系统Demo

    2. ContentProvider的实现:一个继承自ContentProvider的类,其中定义了对数据库操作的方法,并通过UriMatcher进行Uri匹配,以便正确处理不同的请求。 3. 登录界面(Activity):可能包含一个XML布局文件和对应的...

    android测试

    2. **定义UriMatcher**: UriMatcher用于匹配传入的URI,决定调用哪个方法进行处理。通过添加模式和相应的代码,可以确保ContentProvider能够正确解析请求。 3. **注册ContentProvider**: 在AndroidManifest.xml文件...

    Android应用开发使用ContentProvider以及SQLite实现对数据库的相关操作

    在ContentProvider中,通常会定义一个UriMatcher对象来处理不同的URI请求,以及一个SQLiteOpenHelper实例来操作数据库。 为了使其他组件能够通过ContentResolver访问ContentProvider,我们需要在AndroidManifest....

    android 自定义 ContentProvider 以及 ContentResolver

    5. **处理UriMatcher**:使用UriMatcher工具类,设置URI匹配规则,以便在ContentProvider的查询方法中正确地处理请求。 接下来,我们谈谈ContentResolver。ContentResolver是应用程序用来与ContentProvider交互的...

    Android四大组件之一ContentProvider自定义Sqlite共享,实现增删查改基本功能

    3. **UriMatcher类**:用于解析传入的URI,确定应该调用哪个方法来处理请求。通过添加匹配规则,我们可以指定不同的URI执行不同的操作。 4. **SQLiteOpenHelper类**:用于创建和升级SQLite数据库。在这个类中,我们...

    Android数据库ContentProvider封装原理.pdf

    Android操作系统中的数据库管理是通过ContentProvider来实现的,而ContentProvider是一个抽象类,提供了标准化的接口来访问和管理应用程序的数据。ContentProvider可以提供对数据的CRUD(Create、Read、Update、...

    Android学习之手机通讯录

    ContentProvider是一个抽象类,它为其他应用程序提供访问应用程序私有数据的方式。Android系统中,包括通讯录、媒体文件等系统数据都是通过ContentProvider进行访问的。开发者可以通过自定义ContentProvider来暴露...

    Android数据持久化

    - 创建一个继承自`android.content.ContentProvider`的类。 - 实现`onCreate()`方法,初始化数据存储,比如SQLite数据库。 - 实现`query()`, `insert()`, `update()`, `delete()`方法,分别对应数据查询、插入、...

    android contentprovider的使用

    2. **Uri匹配**:定义UriMatcher类来匹配不同的Uri请求,这将使代码更清晰。例如: ```java private static final int MATCH_ITEM = 1; private static final int MATCH_ALL = 2; private static UriMatcher ...

    android应用开发详解 源码 全

    源码中会涉及Provider的实现、UriMatcher的使用以及如何通过ContentResolver进行数据操作。 Intent是Android中组件间通信的重要工具,它包含了组件启动的请求信息。通过源码,我们可以看到如何创建Intent、传递数据...

    Android面试demo

    Uri匹配器(UriMatcher)用于识别不同的数据请求,而ContentResolver是应用程序与ContentProvider交互的接口,通常用来执行CRUD操作。此外,理解如何通过ContentProvider安全地共享数据,尤其是在涉及到隐私和权限...

    android provider

    在Android系统中,Content Provider是四大组件之一,它扮演着数据共享和交换的重要角色。Content Provider使得应用程序可以将自己的数据暴露给其他应用,同时也能够访问其他应用公开的数据。在这个"android provider...

    android中Content Provider

    在Android系统中,Content Provider是四大组件之一,它是应用程序间数据共享的核心机制。Content Provider允许一个应用暴露其数据,使得其他应用可以读取或者写入这些数据,甚至跨应用程序进行数据交换。这篇博客...

    Android基础 Content Provider

    - 实现UriMatcher:用于解析不同的URI请求并调用对应的方法。 ### 3、通过内容提供者完成CRUD操作 - **Create**(创建):使用insert()方法插入新数据,通过ContentValues对象传递要插入的数据。 - **Read**(读取...

Global site tag (gtag.js) - Google Analytics