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封装。

  • 相关阅读:
    Nim or not Nim? hdu3032 SG值打表找规律
    Maximum 贪心
    The Super Powers
    LCM Cardinality 暴力
    Longge's problem poj2480 欧拉函数,gcd
    GCD hdu2588
    Perfect Pth Powers poj1730
    6656 Watching the Kangaroo
    yield 小用
    wpf DropDownButton 源码
  • 原文地址:https://www.cnblogs.com/engine1984/p/4138255.html
Copyright © 2011-2022 走看看