android基础之五——内容提供者

内容提供者

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

为了能够让其他应用程序访问本地应用程序中数据库,使用内容提供者对外开放几个接口,让其他应用程
序调用这些接口。

02_编写内容提供者(重点)

步骤:

1、在工程中添加一个内容提供者的类,继承ContentProvider,重写其中的方法;
2、在配置文件中配置一个provider,指定主机名唯一标示内容提供者(android4.1.2之后的版本中,需要指定exported=true,否则其他应程序没有权限访问该内容提供者);
3、在内容提供者类里面,创建一个uriMather(柜员),然后做岗前培训,添加增删改查的uri;
4、在内容提供者的增删改查的方法判断uri是否匹配正确,再调用数据库的增删改查的方法访问数据库;

03_内容提供者工作的原理(重点)

在其他应用程序中,通过内容提供者的解析器,操作内容提供者。
通过一个uri唯一的匹配内容提供者,在uri中指定了操作的路径(内容提供者已经匹配过的路径),内容提供者接收到这个uri后就可以做相应的操作;

uri url
http://www.baidu.com:80/i.html
content
ftp://


uri组成:schemel,主机名、端口、路径
http://www.baidu.com/i.html
content://com.itheima.dbapp.accountcontentprovider/delete

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

代码:

package com.itheima.dbapp;
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 AccountDBHelper helper;
    private static String INSERT = "insert";
    private static String DELETE = "delete";
    private static String UPDATE = "update";
    private static String QUERY = "query";

    //创建一个银行的柜员
    private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    //柜员的岗前培训
    static{
//      content://com.itheima.dbapp.accountcontentprovider/insert
//      content://com.itheima.dbapp.accountcontentprovider/delete
        mUriMatcher.addURI("com.itheima.dbapp.accountcontentprovider", INSERT, 1);
        mUriMatcher.addURI("com.itheima.dbapp.accountcontentprovider", DELETE, 2);**
        mUriMatcher.addURI("com.itheima.dbapp.accountcontentprovider", UPDATE, 3);
        mUriMatcher.addURI("com.itheima.dbapp.accountcontentprovider", QUERY, 4);
    }

    /**
     * 初始化实例对象
     * 通常是创建一个数据库帮助类的对象
     */
    @Override
    public boolean onCreate(){
        helper = new AccountDBHelper(getContext());
        return false;
    }


    @Override
    public Uri insert(Uri uri, ContentValues values) {
        //匹配用户的相应操作,匹配码与柜员培训的匹配吗一致
        if(mUriMatcher.match(uri) == 1){
            SQLiteDatabase db = helper.getWritableDatabase();
            db.insert("account", null, values);
        }
        return null;
    }


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

        if(mUriMatcher.match(uri) == 4){
            SQLiteDatabase db = helper.getWritableDatabase();
            return db.query("account", projection, selection, selectionArgs, null, null, sortOrder);
        }else{
            return null;
        }
    }

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


        if(mUriMatcher.match(uri) == 3){
            SQLiteDatabase db = helper.getWritableDatabase();
             db.update("account", values, selection, selectionArgs);
        }
        return 0;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        if(mUriMatcher.match(uri) == 2){
            SQLiteDatabase db = helper.getWritableDatabase();
             db.delete("account", selection, selectionArgs);
        }
        return 0;
    }

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

05_内容提供者的使用场景

场景:

写内容提供者的场景:让其他应用程序访问自己应用程序数据库中的数据;
写内容提供者的解析器场景:访问别的应用程序中的内容提供者时;

06_插入短信(重点)

在自己的工程里访问手机上短信应用程序里面短信列表。
1、需要访问短信应用提供的内容提供者;
2、需要知道uri:content://sms/;   
3、分析数据库表:sms;address,date,type,body;

代码:

package com.itheima.insertsms;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
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 insert(View view){
    //得到内容提供者的解析器
    ContentResolver resolver = getContentResolver();
    Uri uri = Uri.parse("content://sms/");

    ContentValues values = new ContentValues();
    values.put("address", "18910903535");
    values.put("date",System.currentTimeMillis());

    values.put("type", 1);//type为表示接收到短信

    values.put("body", "上次从我这里借的500万还没还我呢");
    resolver.insert(uri, values);
    Toast.makeText(this, "插入完成", 0).show();
}
}

07_内容提供者uri的写法

content://sms/;
1、需要访问短信应用提供的内容提供者;
2、需要知道uri:content://sms/;   
3、分析数据库表:sms;address,date,type,body;

08_短信的备份(重点)

第一步:通过内容提供者查询短信列表:

1、需要访问短信应用提供的内容提供者;
2、需要知道uri:content://sms/;   
3、分析数据库表:sms;address,date,type,body;

第二步:把短信列表序列化到xml的文件上:

4、把备份的文件写到SD卡上;
5、使用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;
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 backup(View view){
    try {
        //1、访问短信应用的内容提供者
        ContentResolver resolver = getContentResolver();

        Uri uri = Uri.parse("content://sms/");
        Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, "date desc");
        //得到xml序列化器
        XmlSerializer s = Xml.newSerializer();

        FileOutputStream os = new FileOutputStream(new File(Environment.getExternalStorageDirectory()+"/backup.xml"));
        //初始化序列器
        s.setOutput(os, "UTF-8");

        s.startDocument("UTF-8", true);
        s.startTag(null, "info");
        while(cursor.moveToNext()){
            String address = cursor.getString(0);
            long date = cursor.getLong(1);
            int type = cursor.getInt(2);
            String body = cursor.getString(3);

            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, "info");
        s.endDocument();
        cursor.close();
        os.close();
        Toast.makeText(this, "备份成功", 0).show();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

09_短信的还原操作(重点)

把已经备份的xml短信数据插入到短信应用的数据库表中。

1、解析xml的短信数据:
2、通过短信应用程序的内容提供者把数据插入到数据库表中:

代码:

package com.itheima.restoresms;

import java.io.File;
import java.io.FileInputStream;

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;

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 restore(View view) {

        // 创建一个对话框的构造器
        AlertDialog.Builder builder = new Builder(this);

        builder.setTitle("提醒");
        builder.setMessage("是否删除所有短信并重新还原?");
        builder.setPositiveButton("是", new OnClickListener() {

            /**
             * 单击按钮时调用这个方法
             */
            @Override
            public void onClick(DialogInterface dialog, int which) {
                //删除短信
                deleteSms();
                //还原短信
                insertSms();
            }
        });

        builder.setNegativeButton("否", new OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        // 使用构造器创建出一个对话框对象
        AlertDialog ad = builder.create();

        ad.show();

    }

    public void insertSms() {
        try {

            ContentResolver resolver = getContentResolver();
            Uri uri = Uri.parse("content://sms/");

            resolver.delete(uri, null, null);

            // 解析xml文件
            XmlPullParser parser = Xml.newPullParser();
            FileInputStream fis = new FileInputStream(new File(
                    Environment.getExternalStorageDirectory() + "/backup.xml"));
            parser.setInput(fis, "UTF-8");

            // 得到解析的事件类型
            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())) {
                        // 把短信还原到数据库

                        // address,date,type,body;
                        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);
                        sms = null;
                    }
                    break;
                }
                // 解析到下一个标签
                parser.next();
                type = parser.getEventType();
            }
            fis.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void deleteSms(){
        ContentResolver resolver = getContentResolver();

        Uri uri = Uri.parse("content://sms/");
        resolver.delete(uri, null, null);
    }

}

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

联系人相关的表:
1、raw_contacts:存储了联系人的contact_id;
2、data:存储了联系人信息字段的值;
3、mimetypes:存储了联系人信息字段的类型;

读取联系的信息的逻辑:
1、查询raw_contacts:得到contact_id;
2、根据contact_id查询data表;

content://com.android.contacts/raw_contacts
content://com.android.contacts/data

代码:

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){
    System.out.println("=======");
    ContentResolver resolver = getContentResolver();
    Uri uri = Uri.parse("content://com.android.contacts/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);
        Uri dataUri = Uri.parse("content://com.android.contacts/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("mimetype===="+mimetype);
            System.out.println("data1===="+data1);
        }
        dataCursor.close();
        System.out.println("=========================================");
    }
    cursor.close();
}
}

11_联系人的还原(重点)

联系人相关的表:
1、raw_contacts:存储了联系人的contact_id :记录数加1;
2、data:存储了联系人信息字段的值;
3、mimetypes:存储了联系人信息字段的类型;

content://com.android.contacts/raw_contacts
content://com.android.contacts/data

代码:

package com.itheima.readcontacts;

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 restoreContacts(View view) {

    ContentResolver resolver = getContentResolver();

    Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
    Cursor cursor = resolver.query(uri, null, null, null, null);
    int rownum = cursor.getCount();
    cursor.close();
    int contact_id = rownum + 1;
    // 在raw_contacts表中加入一点条数据
    ContentValues values = new ContentValues();
    values.put("contact_id", contact_id);
    resolver.insert(uri, 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", contact_id);
    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", contact_id);
    phoneValues.put("data1", "18910903535");
    resolver.insert(dataUri, phoneValues);

    // email
    ContentValues emailValues = new ContentValues();
    emailValues.put("mimetype", "vnd.android.cursor.item/email_v2");
    emailValues.put("raw_contact_id", contact_id);
    emailValues.put("data1", "wangwu@itcat.cn");
    resolver.insert(dataUri, emailValues);
}
}

12_内容观察者

内容观察者(ContentObserver):可以监听到内容提供者中数据变化的情况;

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.parse("content://sms/");
    //注册一个内容观察者
    resolver.registerContentObserver(uri, true, new MyObserver(new Handler()));
}

private class MyObserver extends ContentObserver{

    public MyObserver(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);
        long type = cursor.getLong(2);

        String body = cursor.getString(3);
        System.out.println("address==="+address);
        System.out.println("date==="+date);
        System.out.println("type==="+type);
        System.out.println("body==="+body);
    }
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值