1.編寫內容提供者
步驟:
1.在工程里創建一個類,繼承ContentProvider,重寫了onCreate和增刪改查的方法;
2.在清單文件中配置一個provider,需要這個數據authorities,用來唯一標識內容者的,在android4.1版本之后需要exported="true"的屬性,否則其他應用程序沒有權限訪問這個內容提供者;
3.在onCreate方法里得到數據庫的幫助類;
2.內容提供者工作的原理
模版代碼:
//uri匹配正時返回的匹配碼
int code = mUriMatcher.match(uri);
if(code == INSERT){
System.out.println("你好,你添加多少都可以");
SQLiteDatabase db = helper.getWritableDatabase();
db.insert("account", null, values);
db.close();
}else
{
System.out.println("密碼不正確!");
}
3.內容提供者的增刪改查的實現
內容提供者:
package com.qaa.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 = 1;
private static final int DELETE = 2;
private static final int UPDATE = 3;
private static final int QUERY = 4;
private AccountDBHelper helper;
//添加一個管理者,用來檢查應用程序提供的uri路徑是否正確
public static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//管理者培訓,認識指定的口令
static{
mUriMatcher.addURI("com.qaa.accountdb", "insert", INSERT);
mUriMatcher.addURI("com.qaa.accountdb", "delete", DELETE);
mUriMatcher.addURI("com.qaa.accountdb", "update", UPDATE);
mUriMatcher.addURI("com.qaa.accountdb", "query", QUERY); }
@Override
public boolean onCreate() {
helper = new AccountDBHelper(getContext()); return false; }
@Override
public Uri insert(Uri uri, ContentValues values) {
//uri匹配正時返回的匹配碼
int code = mUriMatcher.match(uri);
if(code == INSERT){
System.out.println("你好,你添加多少都可以");
SQLiteDatabase db = helper.getWritableDatabase();
db.insert("account", null, values);
db.close();
}else{
System.out.println("密碼不正確!");
}
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
//uri匹配正時返回的匹配碼
int code = mUriMatcher.match(uri);
if(code == QUERY){
System.out.println("你好,你查詢多少都可以");
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 code = mUriMatcher.match(uri);
if(code == UPDATE){
System.out.println("你好,你修改多少都可以");
SQLiteDatabase db = helper.getWritableDatabase();
int n = db.update("account", values, selection, selectionArgs);
db.close();
return n;
}else{
System.out.println("密碼不正確!");
return 0;
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int code = mUriMatcher.match(uri);
if(code == DELETE){
System.out.println("你好,你刪除多少都可以");
SQLiteDatabase db = helper.getWritableDatabase();
int n = db.delete("account", selection, selectionArgs);
db.close();
return n;
}else{
System.out.println("密碼不正確!");
return 0;
}
}
@Override
public String getType(Uri uri) {
return null;
}
}
在清單文件中配置內容提供者:
<!-- 在android4.1版本之后需要exported="true"的屬性,否則其他應用程序沒有權限訪問這個內容提供者 -->
<provider android:name="com.qaa.accountdb.AccountContentProvider"
android:authorities="com.qaa.accountdb"
android:exported="true">
</provider>
其他應用程序訪問內容提供者:
package com.qaa.bankboss;
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 uri = Uri.parse("content://com.qaa.accountdb/insert");
ContentValues values = new ContentValues();
values.put("name", "王");
values.put("money", "10000000");
//調用內容提供者,在數據庫中添加一條數據
resolver.insert(uri, values);
}
public void update(View view){
//得到內容提供者的解析器,用來匹配內容提供者
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.qaa.accountdb/update");
ContentValues values = new ContentValues();
values.put("money", "20000000");
//調用內容提供者,在數據庫中添加一條數據
resolver.update(uri, values, "name=?", new String[]{"王"});
}
public void query(View view){
//得到內容提供者的解析器,用來匹配內容提供者
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.qaa.accountdb/query");
//調用內容提供者,
Cursor cursor = resolver.query(uri, new String[]{"name","money"}, "name=?", new String[]{"王"}, null);
while(cursor.moveToNext()){
String name = cursor.getString(0);
String money = cursor.getString(1);
System.out.println("name="+name+"; money="+money);
}
cursor.close();
}
public void delete(View view){
//得到內容提供者的解析器,用來匹配內容提供者
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.qaa.accountdb/delete");
resolver.delete(uri, "name=?", new String[]{"行長"});
}
}
4.內容提供者的使用場景
內容提供者:主要是在自己的應用程序中提供訪問數據庫的接口(內容提供者);
內容提供者的解析器:主要是在別的應用程序中訪問其他應用程序的內容提供者;
5.插入短信
address:電話號碼
date:時間
type:1表示接收的短信,2發送出去的短信
body:短信內容
代碼:
public void insert(View view){
String phone = et_phone.getText().toString().trim();
String content = et_content.getText().toString().trim();
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms/");
ContentValues values = new ContentValues();
values.put("address", phone);
values.put("date", System.currentTimeMillis());
values.put("type", 1);
values.put("body", content);
resolver.insert(uri, values);
}
6.內容提供者uri的寫法
uri:content://sms/ 查詢手機上所有的短信列表;
7.短信的備份
1.得到內容提供者的解析器,訪問短信應用的內容提供者,查詢手機上短信的列表:
(1)得到內容提供者的解析器
(2)訪問短信應用的內容提供者,查詢手機上短信的列表
2.把短信列表序列化到xml格式的文件上:
(1)得到一個xml的序列化器:
(2)初始化:
(3)把短信數據一條一條的序列化到xml格式的文件:
代碼:
package cn.itcast.smsbackup;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
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;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// 點擊按鈕,備份手機系統里面的所有的短信
public void click(View view) {
try {
//得到內容提供者的解析器
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms/");
//得到一個xml的序列化器
XmlSerializer serializer = Xml.newSerializer();
//初始化
File file = new File(Environment.getExternalStorageDirectory(),"backup.xml");
FileOutputStream os = new FileOutputStream(file);
serializer.setOutput(os, "utf-8");
//寫備份文件的xml頭
serializer.startDocument("utf-8", true);
serializer.startTag(null, "info");
//訪問短信應用的內容提供者,查詢手機上短信的列表
Cursor cursor = resolver.query(uri, new String[] { "address", "date", "type", "body" }, null, null, null);
while (cursor.moveToNext()) {
serializer.startTag(null, "sms");
String address = cursor.getString(0);
String date = cursor.getString(1);
String type = cursor.getString(2);
String body = cursor.getString(3);
serializer.startTag(null, "address");
serializer.text(address);
serializer.endTag(null, "address");
serializer.startTag(null, "date");
serializer.text(date);
serializer.endTag(null, "date");
serializer.startTag(null, "type");
serializer.text(type);
serializer.endTag(null, "type");
serializer.startTag(null, "body");
serializer.text(body);
serializer.endTag(null, "body");
serializer.endTag(null, "sms");
System.out.println("---------------");
}
cursor.close();
serializer.endTag(null, "info");
serializer.endDocument();
os.close();
Toast.makeText(this, "備份成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
8.短信的還原操作
代碼:
package cn.qaa.smsrestore;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Xml;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View view) {
final ContentResolver resolver = getContentResolver();
final Uri uri = Uri.parse("content://sms/");
// 還原短信, 把短信的內容插入到數據庫.
// 為了避免短信的重復,在還原短信之前,提示用戶是否刪除舊的短信.
AlertDialog.Builder builder = new Builder(this);
builder.setTitle("提醒");
builder.setMessage("是否刪除舊的短信?");
builder.setPositiveButton("刪除", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
resolver.delete(uri, null, null);
// 還原短信
restoreSms();
} });
builder.setNegativeButton("不刪除", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 還原短信
restoreSms();
}
});
builder.show();
}
/**
* 還原短信
*/
private void restoreSms() {
try {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms");
// 讀取sd卡的備份文件 xml文件.
File file = new File(Environment.getExternalStorageDirectory(),
"backup.xml");
FileInputStream fis = new FileInputStream(file);
// 解析xml文件.
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, "utf-8");
int type = parser.getEventType();
SmsInfo smsInfo = null;
while (type != XmlPullParser.END_DOCUMENT) {
switch (type) {
case XmlPullParser.START_TAG:
if("sms".equals(parser.getName())){
smsInfo = new SmsInfo();
}else if("address".equals(parser.getName())){
smsInfo.address = parser.nextText();
}else if("date".equals(parser.getName())){
smsInfo.date = parser.nextText();
}else if("type".equals(parser.getName())){
smsInfo.type = parser.nextText();
}else if("body".equals(parser.getName())){
smsInfo.body = parser.nextText();
}
break;
case XmlPullParser.END_TAG:
if("sms".equals(parser.getName())){//一條短信結束.
ContentValues values = new ContentValues();
values.put("address", smsInfo.address);
values.put("date", smsInfo.date);
values.put("type", smsInfo.type);
values.put("body", smsInfo.body);
resolver.insert(uri, values);
}
break;
}
type = parser.next();
}
Toast.makeText(this, "還原短信成功", 0).show();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
class SmsInfo{
String body;
String address;
String type;
String date;
}
}
9.聯系人數據庫的表結構
raw_contacts:聯系人的表 可以得到聯系人的ID:contact_id
data:聯系人的數據的表,每一天記錄表示聯系人的一個信息字段
mimetypes:聯系人信息字段的類型
1.查看聯系人應用提供的內容提供者,得到一個uri:
content://com.android.contacts/contacts
2.訪問聯系人應用的內容提供者,得到聯系人列表:
代碼:
package com.qaa.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 v) {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
// 1、通過內容提供者去讀raw_contacts中的數據
Cursor cursor = resolver.query(uri, new String[] { "contact_id" }, null, null, null);
while (cursor.moveToNext()) {
long contact_id = cursor.getLong(0);
System.out.println("contact_id==" + contact_id);
// 2、通過內容提供者去讀data中的數據
Uri dataUri = Uri.parse("content://com.android.contacts/data/#"+contact_id);
Cursor dataCursor = resolver.query(dataUri, new String[] { "raw_contact_id", "mimetype", "data1" }, null, null, null);
while(dataCursor.moveToNext()){
long raw_contact_id = dataCursor.getLong(0);
String mimetype = dataCursor.getString(1);
String data = dataCursor.getString(2);
System.out.println("raw_contact_id=="+raw_contact_id);
System.out.println("mimetype=="+mimetype);
System.out.println("data=="+data);
}
dataCursor.close();
System.out.println("----------------------------------");
}
cursor.close();
}
}
10.聯系人的還原
向raw_contacts、data
11.內容觀察者&短信listener
內容觀察者可以看到內容提供者中數據變化;
12.內容觀察者
package com.qaa.contentobserver;
import java.util.Date;
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 {
private ContentResolver resolver;
private Uri uri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
resolver = getContentResolver();
uri = Uri.parse("content://sms/");
resolver.registerContentObserver(uri, true, new MyContentObserver(
new Handler())); }
private class MyContentObserver extends ContentObserver {
public MyContentObserver(Handler handler) {
super(handler);
}
/**
* 內容提供者中數據發生變后調用這個方法
*/
@Override
public void onChange(boolean selfChange) {
Cursor cursor = resolver.query(uri, new String[] { "address",
"date", "type", "body" }, null, null, "date desc");
cursor.moveToNext();
String phone = cursor.getString(0);
long date = cursor.getLong(1);
String type = cursor.getString(2);
String body = cursor.getString(3);
System.out.println("phone==="+phone);
System.out.println("date==="+new Date(date).toLocaleString());
System.out.println("type==="+type);
System.out.println("body==="+body);
cursor.close();
super.onChange(selfChange);
}
}
}