内容提供者的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wdx_1136346879/article/details/85643346

#内容提供者

#01_为什么需要内容提供者

内容提供者:提供了统一的访问数据库的方式,可以让其他应用程序来调用。

#02_编写内容提供者

步骤:
1、在工程中添加一个内容提供者的类,继承了ContentProvider类型,实现了增删改查的方法;
2、在清单文件中配置一个provider节点,指定authorities(相当于网站的域名,用来唯一标示一个内容提供者)、exported为true(从4.1开始,exported没有指定为true,表示其他应用程序不能访问这个内容提供者);

代码:

package com.itheima.accountdb;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class AccountContentProvider extends ContentProvider {

	private static final int INSERT = 0;
	private static final int DELETE = 1;
	private static final int QUERY = 2;
	private static final int UPDATE = 3;
	private AccountDBHelper helper;

	//mUriMatcher uri匹配,NO_MATCH 匹配uri时如果没有匹配成功返回NO_MATCH
	private static UriMatcher  mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	
	//mUriMatcher的岗前培训 content://com.itheima.accountdb.AccountContentProvider/insert
	static{
		//添加可以匹配到的uri
		//authority 内容提供者的主机名
		//path 访问的路径
		//code 匹配,当匹配成功时会返回这个匹配码
		mUriMatcher.addURI("com.itheima.accountdb.AccountContentProvider", "insert", INSERT);
		mUriMatcher.addURI("com.itheima.accountdb.AccountContentProvider", "delete", DELETE);
		mUriMatcher.addURI("com.itheima.accountdb.AccountContentProvider", "query", QUERY);
		mUriMatcher.addURI("com.itheima.accountdb.AccountContentProvider", "update", UPDATE);
	}
	
	/**
	 * 内容提供者一创建的时候会调用这个方法
	 * 初始化实例对象
	 */
	@Override
	public boolean onCreate() {
		helper = new AccountDBHelper(getContext());
		return false;
	}
	
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		if(mUriMatcher.match(uri) == INSERT){

			SQLiteDatabase db = helper.getWritableDatabase();
			db.insert("account", null, values);
			db.close();
		}else{
			System.out.println("口令不正确,请走开...");
		}
		return null;
	}

	@Override
	public int delete(Uri arg0, String arg1, String[] arg2) {
		return 0;
	}

	@Override
	public String getType(Uri uri) {
		return null;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		return null;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		return 0;
	}
}

配置文件:

 <!-- authorities:主机名,唯一标示内容提供者;exported,从4.1开始,exported没有指定为true,表示其他应用程序不能访问这个内容提供者 -->
    <provider
        android:name="com.itheima.accountdb.AccountContentProvider"    				android:authorities="com.itheima.accountdb.AccountContentProvider"
        android:exported="true" >
    </provider>

#03_内容提供者工作的原理

内容提供者解析器是通过uri匹配要访问的内容提供者和访问路径的;

#04_内容提供者的增删改查的实现

代码:

package com.itheima.accountdb;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class AccountContentProvider extends ContentProvider {

	private static final int INSERT = 0;
	private static final int DELETE = 1;
	private static final int QUERY = 2;
	private static final int UPDATE = 3;
	private AccountDBHelper helper;

	//mUriMatcher uri匹配,NO_MATCH 匹配uri时如果没有匹配成功返回NO_MATCH
	private static UriMatcher  mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	
	//mUriMatcher的岗前培训 content://com.itheima.accountdb.AccountContentProvider/insert
	static{
		//添加可以匹配到的uri
		//authority 内容提供者的主机名
		//path 访问的路径
		//code 匹配,当匹配成功时会返回这个匹配码
		mUriMatcher.addURI("com.itheima.accountdb.AccountContentProvider", "insert", INSERT);
		mUriMatcher.addURI("com.itheima.accountdb.AccountContentProvider", "delete", DELETE);
		mUriMatcher.addURI("com.itheima.accountdb.AccountContentProvider", "query", QUERY);
		mUriMatcher.addURI("com.itheima.accountdb.AccountContentProvider", "update", UPDATE);
	}
	
	/**
	 * 内容提供者一创建的时候会调用这个方法
	 * 初始化实例对象
	 */
	@Override
	public boolean onCreate() {
		helper = new AccountDBHelper(getContext());
		return false;
	}
	
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		if(mUriMatcher.match(uri) == INSERT){

			SQLiteDatabase db = helper.getWritableDatabase();
			db.insert("account", null, values);
			db.close();
		}else{
			System.out.println("口令不正确,请走开...");
		}
		return null;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		int n = 0;
		if(mUriMatcher.match(uri) == DELETE){

			SQLiteDatabase db = helper.getWritableDatabase();
			n  = db.delete("account", selection, selectionArgs);
			db.close();
		}else{
			System.out.println("口令不正确,请走开...");
		}
		
		return n ;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		
		if(mUriMatcher.match(uri) == QUERY){

			SQLiteDatabase db = helper.getWritableDatabase();
			Cursor cursor  = db.query("account",projection,selection , selectionArgs, null, null, null);
			return  cursor;
		}else{
			System.out.println("口令不正确,请走开...");
			return null;
		}
	
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		int n = 0;
		if(mUriMatcher.match(uri) == UPDATE){

			SQLiteDatabase db = helper.getWritableDatabase();
			n = db.update("account", values, selection, selectionArgs);
			db.close();
			
		}else{
			System.out.println("口令不正确,请走开...");
		}
		
		return n ;
	}
	
	@Override
	public String getType(Uri uri) {
		return null;
	}
	
}

#05_内容提供者的使用场景
使用场景:
当需要给其他应用程序提供访问数据的接口(内容提供者的增删改查的方法);
当需要访问其他应用程序的数据库中的数据时,需要使用内容提供者解析器来访问内容提供者;

#06_插入短信

uri:content://sms/

短信表中需要关心的几列:address、date、type、body

代码:

	ContentResolver resolver = getContentResolver();
	//调用短信内容提供者增删改查方法需要使用uri
	Uri uri = Uri.parse("content://sms/");
	ContentValues values = new ContentValues();
	
	values.put("address", "18910903535");
	values.put("date", System.currentTimeMillis());
	values.put("type", 1);
	values.put("body", "itheimasdfdsfdsfdsf");
	
	resolver.insert(uri,values);

#07_内容提供者uri的写法

content://com.itheima.accountdb.AccountContentProvider/insert
http://www.baidu.com/image/1.jpg
组成部分:
		scheme名称、主机名(唯一标示内容提供者的)、path路径(操作的类型)、访问的数据资源;

#08_短信的备份

步骤:
	1、知道查询短信数据库表的uri;
	2、通过内容提供者解析器查询短信数据;
	3、把查询出来的短信数据序列化到xml的文件上;

代码:

package com.itheima.copysms;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.xmlpull.v1.XmlSerializer;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Xml;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void backup(View v) {

		try {
			
			//1、知道查询短信数据库表的uri
			ContentResolver resolver = getContentResolver();
			Uri uri = Uri.parse("content://sms/");
			//2、通过内容提供者解析器查询短信数据;
			Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, "date desc");
			
			XmlSerializer s = Xml.newSerializer();
			
			FileOutputStream fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory()+"/sms_backup.xml"));
			s.setOutput(fos, "UTF-8");
			
			s.startDocument("UTF-8", true);
			s.startTag(null, "smss");
			
			while(cursor.moveToNext()){
				String address = cursor.getString(0);
				long date = cursor.getLong(1);
				int type = cursor.getInt(2);
				String body = cursor.getString(3);
				//3、把查询出来的短信数据序列化到xml的文件上;
				s.startTag(null, "sms");
				
				s.startTag(null, "address");
				s.text(address);
				s.endTag(null, "address");
				
				s.startTag(null, "date");
				s.text(date+"");
				s.endTag(null, "date");
				
				s.startTag(null, "type");
				s.text(type+"");
				s.endTag(null, "type");
				
				
				s.startTag(null, "body");
				s.text(body+"");
				s.endTag(null, "body");
				
				s.endTag(null, "sms");
			}
			
			s.endTag(null, "smss");
			s.endDocument();
			fos.close();
			cursor.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

#09_短信的还原操作

步骤:
1、读取已经备份的短信数据文件,使用pull解析xml格式的数据,读到list集合里面;
2、还原数据数据之前,先删除原来的短信数据;
3、通过内容提供者解析忘短信应用程序中插入短信数据;

代码:

package com.itheima.restoresms;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Xml;
import android.view.View;

import com.itheima.restoresms.domain.SMSInfo;

public class MainActivity extends Activity {

	private SMSInfo sms;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void restoresms(View view) {
		try {
			// 1、读取已经备份的短信数据文件,使用pull解析xml格式的数据,读到list集合里面;
			File file = new File(Environment.getExternalStorageDirectory()
					+ "/sms_backup.xml");
			FileInputStream fis = new FileInputStream(file);

			List<SMSInfo> list = getSMSList(fis);
			// 2、还原数据数据之前,先删除原来的短信数据;
			ContentResolver resolver = getContentResolver();
			Uri uri = Uri.parse("content://sms/");
			resolver.delete(uri, null, null);
			System.out.println("=====删除了原来的短信=======");
			// 3、通过内容提供者解析忘短信应用程序中插入短信数据;
			for(SMSInfo sms : list){
				ContentValues values = new ContentValues();
				
				values.put("address", sms.getAddress());
				values.put("date", sms.getDate());
				values.put("type", sms.getType());
				values.put("body", sms.getBody());
				resolver.insert(uri, values);
			}
			System.out.println("======还原短信成功=========");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private List<SMSInfo> getSMSList(FileInputStream fis) {


		try {
			XmlPullParser parser = Xml.newPullParser();
			parser.setInput(fis, "UTF-8");

			
			
			List<SMSInfo> list = new ArrayList<SMSInfo>();
			int type = parser.getEventType();
			while (type != XmlPullParser.END_DOCUMENT) {
				switch (type) {
				case XmlPullParser.START_TAG:// 标签的开始位置
					if ("sms".equals(parser.getName())) {
						sms = new SMSInfo();
					} else if ("address".equals(parser.getName())) {
						String address = parser.nextText();
						sms.setAddress(address);
					} else if ("date".equals(parser.getName())) {
						String date = parser.nextText();
						sms.setDate(date);
					} else if ("type".equals(parser.getName())) {
						String smsType = parser.nextText();
						sms.setType(smsType);
					} else if ("body".equals(parser.getName())) {
						String body = parser.nextText();
						sms.setBody(body);
					}
					break;

				case XmlPullParser.END_TAG:// 标签的结束位置
					if ("sms".equals(parser.getName())) {
						list.add(sms);
						System.out.println("---sms------" + sms);
						sms = null;
					}
					break;
				}
				//解析下一个事件类型
				type= parser.next();
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}

#10_联系人数据库的表结构

raw_contacts:_id 联系人的ID;
data:联系人的信息;
mimetypes:联系人信息字段的名称;

步骤:

1、知道使用内容提供者读取以上三张表时它们的uri;
	data:content://com.android.contacts/data/
	raw_contacts:content://com.android.contacts/raw_contacts/
2、通过内容提供者关联查询这三张表;

代码:

权限:

	 <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>

MainActivity.java:

	package com.itheima.readcontacts;

	import android.app.Activity;
	import android.content.ContentResolver;
	import android.database.Cursor;
	import android.net.Uri;
	import android.os.Bundle;
	import android.view.View;
	
	public class MainActivity extends Activity {
	
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
		}
	
		public void readContacts(View view) {
	
			ContentResolver resolver = getContentResolver();
			
			Uri uri = Uri.parse("content://com.android.contacts/raw_contacts/");
			
			Cursor cursor = resolver.query(uri, new String[]{"_id"}, null, null, null);
			
			while(cursor.moveToNext()){
				long contact_id = cursor.getLong(0);
				System.out.println("=========contact_id="+contact_id);
				
				Uri datauri = Uri.parse("content://com.android.contacts/data/");
				//mimetype 代表mimetypes表中一条记录,可以简单的理解为view_data视图
				Cursor dataCursor = resolver.query(datauri, new String[]{"mimetype","raw_contact_id","data1"}, "raw_contact_id=?", new String[]{contact_id+""}, null);
				
				while(dataCursor.moveToNext()){
					String mimetype = dataCursor.getString(0);
					long raw_contact_id = dataCursor.getLong(1);
					String data1 = dataCursor.getString(2);
					
					System.out.println("raw_contact_id="+raw_contact_id+"; mimetype="+mimetype+"; data1="+data1);
				}
			}
		}
	}

#11_联系人的还原

步骤:
1、在raw_contacts插入一条数据:contact_id=id=总记录数+1;
2、在data表中插入数据:mimetype_id,raw_contact_id,data1;

代码:

package com.itheima.insertcontact;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void insert(View view) {

		ContentResolver resolver = getContentResolver();

		Uri rawconturi = Uri
				.parse("content://com.android.contacts/raw_contacts/");
		Cursor rawcursor = resolver.query(rawconturi, null, null, null, null);
		int rows = rawcursor.getCount();

		ContentValues values = new ContentValues();
		values.put("contact_id", rows + 1);
		// 在raw_contacts表中插入一条数据
		resolver.insert(rawconturi, values);

		Uri datauri = Uri.parse("content://com.android.contacts/data/");

		ContentValues nameValues = new ContentValues();

		nameValues.put("mimetype", "vnd.android.cursor.item/name");
		nameValues.put("raw_contact_id", rows + 1);
		nameValues.put("data1", "wangwu");
		resolver.insert(datauri, nameValues);

		ContentValues phoneValues = new ContentValues();

		phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
		phoneValues.put("raw_contact_id", rows + 1);
		phoneValues.put("data1", "13900000099");
		resolver.insert(datauri, phoneValues);

		ContentValues emailValues = new ContentValues();

		emailValues.put("mimetype", "vnd.android.cursor.item/email_v2");
		emailValues.put("raw_contact_id", rows + 1);
		emailValues.put("data1", "[email protected]");
		resolver.insert(datauri, emailValues);
		
		
		rawcursor.close();

	}
}

#12_内容观察者

内容观察者:主要是用来观察内容提供者里面数据的变化情况;

#13_短信窃听器

代码:

package com.itheima.smslistener;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	
	//得到内容提供者的解析器
	ContentResolver resolver = getContentResolver();
	//指定目标提供者的uri
	Uri uri = Uri.parse("content://sms/");
	//给指定的内容提供者注册一个内容观察者
	resolver.registerContentObserver(uri, true, new SmsContentObserver(new Handler()));
}

private class SmsContentObserver extends ContentObserver{

	public SmsContentObserver(Handler handler) {
		super(handler);
	}

	/**
	 * 内容提供者中的数据发生变化时调用这个方法
	 */
	@Override
	public void onChange(boolean selfChange) {
		super.onChange(selfChange);
		
		ContentResolver resolver = getContentResolver();
		Uri uri = Uri.parse("content://sms/");
		
		Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, "date desc");
		cursor.moveToNext();	
		String address = cursor.getString(0);
		long date = cursor.getLong(1);
		int type = cursor.getInt(2);
		String body = cursor.getString(3);
		System.out.println("address="+address+"; date="+date+"; type="+type+"; body="+body);
	}
}

}

猜你喜欢

转载自blog.csdn.net/wdx_1136346879/article/details/85643346