zoukankan      html  css  js  c++  java
  • 第八章:四大组件之Content Provider

    前言

    Content Provider——Android四大组件之一。

    本文要点

    1.Content Provider简介

    2.URI简介

    3.如何访问Content Provider中数据

    一、Content Provider简介

    Content Provider,Android四大组件之一。它是Android系统提供的在多个应用之间共享数据的一种机制。一个Content Provider类实现了一组标准的方法接口,从而能够让其他的应用保存或读取此Content Provider的各种数据类型。有几点说明:

    (1)每个ContentProvider都会对外提供一个公共的URI(包装成Uri对象),如果应用程序有数据需要共享,就需要使用ContentProvider为这些数据定义一个URI,然后其他应用程序就可以通过ContentProvider传入这个URI来对数据进行操作。

    (2)我们的APP可以通过实现一个Content Provider的抽象接口将自己的数据暴露出去,也可以通过ContentResolver接口访问Content Provider提供的数据;

    (3)ContentResolver支持CRUD(create, retrieve, update, and delete)操作;

    (4)Android系统提供了诸如:音频、视频、图片、通讯录等主要数据类型的Content Provider。我们也可以创建自己的Content Provider。

    首先,Android是一个很重视安全性的系统(貌似Android系统的漏洞最多~~~),一个应用的数据对于其他应用来说私有的,除非你把数据存储在SD卡上。但很多时候我们需要在程序之间共享数据,比如我们想获取联系人的信息之类的。这时Content Provider就提供了一个很好的解决方案,将数据的存储、读取细节隐藏,提供一个统一的接口供其它应用访问,并且还可以做到权限控制,在一定程度上保证数据的安全性。

    其次就是进程间通信(inter-process communication IPC)的问题,如果让开发者自己来处理这些细节无疑会加大开发的难度。而Content Provider提供了类似于b/s结构的模式,b与c之间是以一种什么方式去实现我们并不关心,就像我们大部分时候不用去关心网络到底是怎么连接的。开发者应该关心的是怎么去实现一个Content Provider或去调用一个Content Provider。

    二、URI简介

    URI唯一标识了Provider中的数据,当应用程序访问Content Provider中的数据时,URI将会是其中一个重要参数。URI包含了两部分内容:(1)要操作的Content Provider对象(2)要操作的Content Provider中数据的类型。

    URI由以下几个部分组成:

    (1)Scheme:在Android中URI的Scheme是不变的,即:Content://

    (2)Authority:用于标识ContentProvider(API原文:A string that identifies the entire content provider.);

    (3)Path:用来标识我们要操作的数据。零个或多个段,用正斜杠(/)分割;

    (4)ID:指定ID后,将操作指定ID的数据(ID也可以看成是path的一部分),ID在URI中是可选的(API原文:A unique numeric identifier for a single row in the subset of data identified by the preceding path part.)。

    URI示例:

    (1)content://media/internal/images   返回设备上存储的所有图片;

    (2)content://media/internal/images /10 返回设备上存储的ID为10的图片 

    操作URI经常会使用到UriMatcher和ContentUris两个类。

    UriMatcher:用于匹配Uri;

    ContentUris:用于操作Uri路径后面的ID部分,如提供了方法withAppendedId()向URI中追加ID。

    三、访问Content Provider中数据

    应用程序访问Content Provider的内容需要用到ContentResolver对象,这里以操作Android通讯录提供的Content Provider为例来说明如何访问Content Provider中的数据。

    1.创建一个project:HelloContentProvider,MainActivity的Layout文件命名为main.xml;

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.helloandroid"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="21" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity
                android:name=".SecondActivity"
                android:label="@string/title_activity_second" >
            </activity>
            <activity
                android:name=".ServiceActivity"
                android:label="@string/title_activity_service" >
            </activity>
    
            <service android:name=".MyService" >
                <intent-filter>
                    <action android:name="android.guo.service.playmusic.MyService" />
                </intent-filter>
            </service>
    
            <activity
                android:name=".ContentProviderActivity"
                android:label="@string/title_activity_content_provider" >
            </activity> 
        </application>
        <uses-permission android:name="android.permission.READ_CONTACTS" />
        <uses-permission android:name="android.permission.WRITE_CONTACTS" /> 
    
    </manifest>
    View Code

    2.在文件:AndroidManifest.xml中添加Contact的读写权限;

    3.在main.xml中添加几个button:Insert,Query,Update,Delete,并绑定onClick事件:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:layout_width="fill_parent" 
                  android:layout_height="fill_parent" 
                  android:orientation="vertical" >
        <TextView android:id="@+id/text"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:text="Hello Content Provider" />
        <Button android:id="@+id/btnInsert"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:width="100dp"
                android:text="Insert" 
                android:onClick="insertContact"/>
        <Button android:id="@+id/btnQuery"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:width="100dp"
                android:text="Query" 
                android:onClick="queryContacts"/>
    
        <Button android:id="@+id/btnUpdate"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:width="100dp"
                android:text="Update" 
                android:onClick="updateContact"/>
           <Button android:id="@+id/btnDelete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:width="100dp"
                android:text="Delete" 
                android:onClick="deleteContact"/>
    </LinearLayout>
    View Code

    添加记录:
    要增加记录,我们可以调用ContentResolver.insert()方法,该方法接受一个要增加的记录的目标URI,以及一个包含了新记录值的Map对象,调用后的返回值是新记录的URI,包含记录号。
    上面的例子中我们都是基于联系人信息簿这个标准的Content Provider,现在我们继续来创建一个insertRecord() 方法以对联系人信息簿中进行数据的添加:

    private void insertRecords(String name, String phoneNo) {
        ContentValues values = new ContentValues();
        values.put(People.NAME, name);
        Uri uri = getContentResolver().insert(People.CONTENT_URI, values);
        Log.d(”ANDROID”, uri.toString());
        Uri numberUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY);
        values.clear();
        values.put(Contacts.Phones.TYPE, People.Phones.TYPE_MOBILE);
        values.put(People.NUMBER, phoneNo);
        getContentResolver().insert(numberUri, values);
    }
    View Code

    删除记录:
    Content Provider中的getContextResolver.delete()方法可以用来删除记录,下面的记录用来删除设备上所有的联系人信息:

    private void deleteRecords() {
        Uri uri = People.CONTENT_URI;
        getContentResolver().delete(uri, null, null);
    }
    View Code

    修改记录:
    我们可以使用ContentResolver.update()方法来修改数据,我们来写一个修改数据的方法:

    private void updateRecord(int recNo, String name) {
        Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, recNo);
        ContentValues values = new ContentValues();
        values.put(People.NAME, name);
        getContentResolver().update(uri, values, null, null);
    }
    View Code

    查询记录

    Cursor cur = managedQuery(person, null, null, null);

    这个查询返回一个包含所有数据字段的游标,我们可以通过迭代这个游标来获取所有的数据:

    package com.wissen.testApp;
    public class ContentProviderDemo extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
           displayRecords();
        }
    
        private void displayRecords() {
            //该数组中包含了所有要返回的字段
         String columns[] = new String[] { People.NAME, People.NUMBER };
           Uri mContacts = People.CONTENT_URI;
           Cursor cur = managedQuery(
              mContacts,
              columns,  // 要返回的数据字段
             null,          // WHERE子句
             null,         // WHERE 子句的参数
             null         // Order-by子句
         );
           if (cur.moveToFirst()) {
               String name = null;
               String phoneNo = null;
               do {
                  // 获取字段的值
                name = cur.getString(cur.getColumnIndex(People.NAME));
                 phoneNo = cur.getString(cur.getColumnIndex(People.NUMBER));
                 Toast.makeText(this, name + ” ” + phoneNo, Toast.LENGTH_LONG).show();
              } while (cur.moveToNext());
           }
        }
    }
    View Code

    从上面的实例我们可以得到以下几点:

    (1)访问Content Provider需要一定的操作权限;

    (2)访问Content Prvider需要使用到ContentResolver对象;

    (3)ContentResolver支持query,insert,delete,update操作;

    (4)由URI确定Content Provider中要操作的具体数据;

    (5)insert时,要添加的数据可以使用ContentValues封装。

  • 相关阅读:
    学习Bitmap,处理“海量”数据
    学习Trie树,处理“海量”数据
    学习KMP算法
    学习堆与栈内存分配方式
    学习继承和虚析构函数
    学习处理数组子集和的算法
    学习类中的const和static类型
    学习利用动态规划解决若干问题
    【MySQL】MySQL忘记root密码解决方案
    【API】短信通106端口验证短信的实现
  • 原文地址:https://www.cnblogs.com/engine1984/p/4138255.html
Copyright © 2011-2022 走看看