Android四大组件——ContentProvider

ContentProvider作为Android四大组件之一,看起来十分牛逼,但在真正的项目中,其实我们很少用到。除非像在腾讯、阿里这样的大公司里,由于本公司旗下的几个APP之间需要进行一些数据共享,例如微信需要调用QQ的一些数据库,此时就需要使用ContentProvider了。它是Android中专门用于不同应用之间进行数据共享的方式,ContentProvider的底层实现了Binder,但系统已经为我们进行了封装,我们无需关心底层即可轻松实现IPC(Inter-Process Communication跨进程通信)。
不同应用之间的通信,这里我主要讲两点:

  • 第一:android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等),许多社交类APP中都需要导入系统得联系人,此处我们先介绍怎样在APP中导入系统得通讯录。

  • 第二:自定一个ContentProvider,再通过另外一个APP访问其中数据。

源码地址

http://download.csdn.net/download/sinat_35615296/9618249

-

ContentResolver访问通讯录数据库

通讯录中的一个Item中主要有两个重要信息,姓名与电话号码,它们都是储存在手机的data/data/com.android.provider.contacts数据库中,但是姓名与电话号码并不是储存在同一张表中
- 表raw_contacts 储存 编号 _id 姓名display_name
- 表data 储存 编号raw_contact_id 号码data1
两者通过编号连接在一起

以下是代码,主要思路是

  1. 先从表raw_contacts取出编号和姓名
  2. 再通过编号在表data中取出对应的电话号码
  3. 放入一个list集合
  4. 通过一LIstView显示出来
public class MainActivity extends Activity {
    //声明访问通话记录的Uri字符串
    //data/data/com.android.providers.contacts/databases
    private String callLogs = "content://call_log/calls";
    //声明访问raw_contacts表格的uri字符串
    private String raw_contacts_string = "content://com.android.contacts/raw_contacts";
    //声明访问data表格的uri字符串
    private String data_string = "content://com.android.contacts/data/phones";
    /**
     * 表raw_contacts   _id        display_name
     * 表data           raw_contact_id       data1
     * 联系人姓名保存在表raw_contacts中的列名display_name中
     * 电话号码保存在表data的列名data1中
     * 两者通过一个共同的id和raw_contact_id联系在一起
     */
    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.list_main);

        List<Map<String, String>> list = new ArrayList<Map<String,String>>();

        list = getContacts();

        SimpleAdapter adapter = new SimpleAdapter(this, list,
                android.R.layout.simple_list_item_2,
                new String[]{"name", "num"},
                new int[]{android.R.id.text1,android.R.id.text2});
        listView.setAdapter(adapter);
    }
    /**
     * 访问raw_contact和data两个表格,分别获取联系人名称和联系人电话号码
     * @return 返回联系人名称和电话的集合
     */
    private List<Map<String, String>> getContacts() {
        List<Map<String, String>> newList = new ArrayList<Map<String,String>>();
        //查询raw_contact联系人名称
        ContentResolver resolver = getContentResolver();
        Uri rawUri = Uri.parse(raw_contacts_string);
        //获取raw_contact的Cursor数据
        Cursor cursor = resolver.query(rawUri, null, null, null, null);
        while(cursor.moveToNext()){
            //获取联系人的名字
            String name = cursor.getString(cursor.getColumnIndex("display_name"));

            String id = cursor.getString(cursor.getColumnIndex("_id"));
            Map<String, String> map = new HashMap<String, String>();
            //将联系人名称保存到Map中
            map.put("name", name);

            Uri dataUri = Uri.parse(data_string);
            //获取data表格的Cursor数据
            Cursor dataCursor = resolver.query(dataUri, null, "raw_contact_id=?",
                    new String[]{id}, null);
            if (dataCursor.moveToNext()) {
                String num = dataCursor.getString(dataCursor.getColumnIndex("data1"));
                map.put("num", num);
            }
            newList.add(map);
        }
        return newList;
    }
}

使用ContentProvider的步骤:

1 自定义类继承系统ContentProvider类
2 实现抽象方法,依次实现相关的数据库操作
3 在AndroidManifest.xml文件中注册CP
- name 指定自定义CP的类名
- authorities 指定访问此CP的IP地址
- exported 指定其他三方APP是否可以访问此CP所封装的数据

public class MyContentProvider extends ContentProvider{

    private SQLiteDatabase database;

    /**
     * 当CP被创建时被回调--APK被安装时,此CP就会被创建出一个实例,保存在Framework层
     * 一般此方法中,需要创建数据库的连接对象
     * 返回true说明创建成功
     */
    @Override
    public boolean onCreate() {
        /**
         * 在ContentProvider中可以通过getContext获取上下文对象
         */
        MySqliteOpenHelper helper = new MySqliteOpenHelper(getContext(),
                "my_db", null, 1);
        database = helper.getReadableDatabase();
        Log.d("amanda","onCreate" );
        return true;
    }

    /**
     * 当外部APP调用ContentResolver.query方法访问此CP时,
     * 此方法会被回调,传入参数就是ContentResolver所传递的参数
     * 一般调用SQLiteDatabase查询数据库,并返回Cursor对象
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        Log.d("amanda","query" );
        Cursor cursor = database.query("person", projection, selection, selectionArgs,
                null, null, sortOrder);
        return cursor;
    }

    /**
     * 返回Uri的类型
     */
    @Override
    public String getType(Uri uri) {
        Log.d("amanda","getType" );
        return null;
    }

    /**
     * 当外部APP调用ContentResolver.insert方法访问此CP时,
     * 此方法会被回调,传入参数就是ContentResolver所传递的参数
     * 一般调用SQLiteDatabase查询数据库,并返回Cursor对象
     */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        Log.d("amanda","insert" );
        database.insert("person", null, values);
        return null;
    }

    /**
     * 当外部APP调用ContentResolver.delete方法访问此CP时,
     * 此方法会被回调,传入参数就是ContentResolver所传递的参数
     * 一般调用SQLiteDatabase查询数据库,并返回Cursor对象
     *
     * 通过数据库操作所影响的个数
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        Log.d("amanda","delete" );
        int affectNum = database.delete("person", selection, selectionArgs);
        return affectNum;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        Log.d("amanda","onCreate" );
        database.update("person", values, selection, selectionArgs);
        return 0;
    }

}

注册Provider

<!--
      使用provider标签注册ContentProvider组件
            android:name               指定ContentProvider的类名
            android:authorities        指定访问此ContentProvider所需要的IP地址中的Authorities部分
                                       完整的Uri路径,content://Authorities
            android:exported           指定其他三方app是否可以访问此ContentProvider,默认true
-->
        <provider

            android:name=".MyContentProvider"
            android:authorities="com.amanda.day13_contentproviderapk.MyContentProvider"
            android:exported="true">

        </provider>

源码地址
http://download.csdn.net/download/sinat_35615296/9618249

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码充电宝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值