标签:android开发
内容提供者:提供了统一的访问数据库的方式,可以让其他应用程序来调用。
步骤:
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>
内容提供者解析器是通过uri匹配要访问的内容提供者和访问路径的;
代码:
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;
}
}
使用场景:
当需要给其他应用程序提供访问数据的接口(内容提供者的增删改查的方法);
当需要访问其他应用程序的数据库中的数据时,需要使用内容提供者解析器来访问内容提供者;
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);
content://com.itheima.accountdb.AccountContentProvider/insert
http://www.baidu.com/image/1.jpg
组成部分:
scheme名称、主机名(唯一标示内容提供者的)、path路径(操作的类型)、访问的数据资源;
步骤:
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();
}
}
}
步骤:
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;
}
}
}
raw_contacts:contact_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);
}
}
}
}
步骤:
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", "wangwu@itcast.cn");
resolver.insert(datauri, emailValues);
rawcursor.close();
}
}
内容观察者:主要是用来观察内容提供者里面数据的变化情况;
代码:
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);
}
}
标签:android开发
原文地址:http://blog.csdn.net/faith_yee/article/details/44853623