码迷,mamicode.com
首页 > 移动开发 > 详细

Android基础-09

时间:2015-04-03 15:30:29      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:android开发

Android基础-09 内容提供者

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: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);
            }
        }
    }

}

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", "wangwu@itcast.cn");
        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);
    }
}

Android基础-09

标签:android开发

原文地址:http://blog.csdn.net/faith_yee/article/details/44853623

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!