content provider 的使用

  android有一个独特之处就是,数据库只能被它的创建者所使用,其他的应用是不能访问到的,所以如果你想实现不同应用之间的数据共享,就不得不用content provider了。   

在Android中,content provider是一个特殊的存储数据的类型,它提供了一套标准的接口用来获取以及操作数据。并且,android自身也提供了几个现成的content provider:Contacts, Browser, CallLog, Settings, MediaStore. 例如访问通讯录使用People.CONTENT_URI。

要实现应用程序之间的数据共享,需要在数据提供方实现一个ContentProvider的继承类,重写query() , insert() , update() , delete()等方法,然后创建一个Uri,并在Manifest.xml中声明provider,设置android:exported = true;在另一个应用程序中通过使用Content Resolver和该Uri来实现查询等等操作,如查询:getContentResolver.query(Uri , projection , selection , selectionArgs , orderBy)。

什么是URI?

将其分为A,B,C,D 4个部分:

A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"
B:URI的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的 类名。这个标识在 元素  的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称 ;"content://hx.android.text.myprovider"
C:路径,不知道是不是路径,通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就ok了;"content://hx.android.text.myprovider/tablename"
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://hx.android.text.myprovider/tablename/#" #表示数据id

UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路径全部给注册上,如下: //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。 UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); //如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1 uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码 //如果match()方法匹配 content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2 uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);//#号为通配符

2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用 addURI()方法传入的第三个参数,假设匹配 content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。

ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
· withAppendedId(uri, id)用于为路径加上ID部分
· parseId(uri)方法用于从路径中获取ID部分

下面看一个例子:

这个例子是这样的:NotePad提供Uri,NotePadProvider是一个ContentProvider的子类,这是数据提供方,提供了一些访问私有数据的访问接口;AccessProviderActivity是另一个程序,是数据访问端。注意权限问题。

public final class NotePad {
    public static final String AUTHORITY = "com.wen.pad.notepad";

    // This class cannot be instantiated
    private NotePad() {
    }
    public static final class Notes implements BaseColumns {

        // This class cannot be instantiated
        private Notes() {}

        public static final Uri CONTENT_URI =  Uri.parse("content://" + AUTHORITY + "/notes");

        /**
         * The MIME type of {@link #CONTENT_URI} providing a directory of notes.
         */
        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";

        /**
         * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
         * note.
         */
        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.note";

        /**
         * The default sort order for this table
         */
        public static final String DEFAULT_SORT_ORDER = "modified DESC";

        /**
         * Column name for the title of the note
         * <P>Type: TEXT</P>
         */
        public static final String TITLE = "title";

        /**
         * Column name of the note content
         * <P>Type: TEXT</P>
         */
        public static final String NOTE = "note";

        /**
         * Column name for the creation timestamp
         * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
         */
        public static final String CREATEDDATE = "created";

        /**
         * Column name for the modification timestamp
         * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
         */
        public static final String MODIFIEDDATE = "modified";
    }
}


 

public class NotePadProvider extends ContentProvider {
	private static final String TAG = "NotePadProvider";
	private static final String DATABASE_NAME = "note_pad.db";
	private static final int DATABASE_VERSION = 1;
	private static final String NOTES_TABLE_NAME = "notes";
	private static HashMap<String, String> sNotesProjectionMap;
	private static final int NOTES = 1;
	private static final int NOTE_ID =2;
	private static final UriMatcher sUriMatcher ;
	private DatabaseHelper mOpenHelper;
	private static final String CREATE_TABLE = "CREATE TABLE "+NOTES_TABLE_NAME
			                                 + "(" + Notes._ID
			                                 + " INTEGER PRIMARY KEY AUTOINCREMENT,"
			                                 + Notes.TITLE
			                                 + " TEXT,"
			                                 + Notes.NOTE
			                                 + " TEXT,"
			                                 + Notes.CREATEDDATE
			                                 + " INTEGER,"
			                                 + NotePad.Notes.MODIFIEDDATE
			                                 + " INTEGER" + ")";
	static{
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);
		sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);
		
		sNotesProjectionMap = new HashMap<String,String>();
		sNotesProjectionMap.put(Notes._ID, Notes._ID);
		sNotesProjectionMap.put(Notes.TITLE, Notes.TITLE);
		sNotesProjectionMap.put(Notes.NOTE, Notes.NOTE);
		sNotesProjectionMap.put(Notes.CREATEDDATE, Notes.CREATEDDATE);
		sNotesProjectionMap.put(Notes.MODIFIEDDATE, Notes.MODIFIEDDATE);
	}
	@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
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		if(sUriMatcher.match(uri)!=NOTES){
			throw new IllegalArgumentException("Unknown URI "+uri);
		}
		ContentValues cv;
		if(values != null)
		{
			cv = new ContentValues(values);
		}
		else
		{
			cv = new ContentValues();
		}
		Long now = Long.valueOf(System.currentTimeMillis());
		if(cv.containsKey(NotePad.Notes.CREATEDDATE) == false)
		{
			cv.put(NotePad.Notes.CREATEDDATE,now);
		}
		if(cv.containsKey(NotePad.Notes.MODIFIEDDATE) == false)
		{
			cv.put(NotePad.Notes.MODIFIEDDATE, now);
		}
		if(cv.containsKey(NotePad.Notes.TITLE) == false)
		{
			Resources r = Resources.getSystem();
			cv.put(NotePad.Notes.TITLE, r.getString(android.R.string.untitled));
		}
		if(cv.containsKey(NotePad.Notes.NOTE) == false)
		{
			cv.put(NotePad.Notes.NOTE, "");
		}
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		long rowId = db.insert(NOTES_TABLE_NAME, Notes.NOTE, cv);
		if(rowId > 0)
		{
			Uri noteUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);
			return noteUri;
		}
		throw new SQLException("Failed to insert row into " + uri);
	}

	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		mOpenHelper = new DatabaseHelper(this.getContext());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		// TODO Auto-generated method stub
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		switch(sUriMatcher.match(uri)){
		case NOTES:
			qb.setTables(NOTES_TABLE_NAME);
			qb.setProjectionMap(sNotesProjectionMap);
			break;
		case NOTE_ID:
			qb.setTables(NOTES_TABLE_NAME);
			qb.setProjectionMap(sNotesProjectionMap);
			qb.appendWhere(Notes._ID+"="+uri.getPathSegments().get(1));
			default:
				throw new IllegalArgumentException("Unknown URI"+uri);
		}
		String orderBy;
		if(TextUtils.isEmpty(sortOrder)){
			orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;
		}
		else{
			orderBy = sortOrder;
		}
		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		Cursor cursor = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
		cursor.setNotificationUri(getContext().getContentResolver(), uri);
		return cursor;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		
		return 0;
	}
    private static class DatabaseHelper extends SQLiteOpenHelper
    {

		public DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
			// TODO Auto-generated constructor stub
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			// TODO Auto-generated method stub
			db.execSQL(CREATE_TABLE);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			// TODO Auto-generated method stub
			
		}
    	
    }
}


manifest.xml中要添加provider

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wen.pad"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <permission android:name="com.wen.pad.NOTEPAD_READ_PERMISSION"/>  <!-- 自定义的permission需先在这里声明 -->
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <provider android:name=".NotePadProvider"
            android:authorities="com.wen.pad.notepad"
            android:exported="true"                                        <!-- 设置成true才能访问 -->
            android:readPermission="com.wen.pad.NOTEPAD_READ_PERMISSION"/>  <!-- 设置读permission,其他程序要用这个provider,必须先use这个permission -->
        <activity
            android:name=".NotePadActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <data android:mimeType="vnd.android.cursor.dir/vnd.google.note"/>
            </intent-filter>
            <intent-filter >
                <data android:mimeType="vnd.android.cursor.item/vnd.google.note"/>
            </intent-filter>
        </activity>
    </application>

</manifest>


访问程序(另一程序):读取数据,然后在Toast中显示

public class AccessProviderActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        displayNote();
    }
    private void displayNote()
    {
    	String columns[] = new String[]{"_id",
    			                        "title",
    			                        "note",
    			                        "created",
    			                        "modified"
    	};
        Uri myUri = Uri.parse("content://com.wen.pad.notepad/notes");
    	Cursor cur = this.getContentResolver().query(myUri, columns, null, null, null);
//    	Cursor cur = this.managedQuery(myUri, columns, null, null, null);
    	if(cur.moveToFirst()){
    		String id = null;
    		String title = null;
    		do{
    			id = cur.getString(cur.getColumnIndex("_id"));
    			title = cur.getString(cur.getColumnIndex("title"));
    			Toast.makeText(this, "TITLE: "+id+" NOTE: "+title, Toast.LENGTH_LONG).show();
    		}while(cur.moveToNext());
    	}
    }
}


Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wen.access"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <uses-permission android:name="com.wen.pad.NOTEPAD_READ_PERMISSION"/> <!--这里声明使用这个permission才能有权限访问NotePadProvider-->
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AccessProviderActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值