zoukankan      html  css  js  c++  java
  • Android ContentProvider 内容提供者

         ContentProvider 内容提供者,是Android四大组件之一。

    一、简述

         可以理解为一个特殊的存储数据的类型,它提供了一套标准的接口来获取和操作数据。可以把数据封装到ContentProvider 中,从而是这些数据可以被其他的应用程序所共享。搭建起了所有应用程序之间数据交换的桥梁!
       1. 内容提供者可以将应用中的数据对外进行共享

     2.内容提供者将数据的访问方式统一,不必针对不同数据类型采取不同的访问策略

     3.内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据

     4.内容提供者中数据更改可被监听

    二、创建内容提供者

       定义类继承ContentProvider,根据需要重写内部方法

         在清单文件的<application>节点下进行配置,<provider>标签中需要指定name和authorities属性

        name为类名,包名从程序Package开始,以“.”开始

        authorities:是访问Provider时的路径,要唯一

           URI代表要操作的数据,由scheme、authorites、path三部分组成

        content://com.bruce.contentprovider.demo/student

        scheme:固定为content,代表访问内容提供者

        authorites:<provider>节点中的authorites属性

        path:程序定义的路径,可根据业务逻辑定义

    --------------------------------------------------------------------------------------------------

     <provider
                android:name="com.bruce.contentprovider.demo.MyContentProvider"
                android:authorities="com.bruce.contentprovider.demo"
                ></provider>

    --------------------------------------------------------------------------------------------------

    getType方法中:

    Ÿ   如果返回数据是单条数据:vnd.android.cursor.item

    Ÿ   如果返回数据是多条数据:vnd.android.cursor.dir

    三、完成CRUD方法

    Ÿ   当程序调用CRUD方法时会传入Uri, 我们通过Uri判断调用者要操作的数据,可以使用工具类UriMatcher来判断Uri,addURI方法可以添加Uri,match方法可以匹配一个Uri判断其类型;根据业务逻辑操作数据。

      1.onCreate() :初始化该ContentProvider
          2.query(Uri,String[],String,Sring[],String) :通过Uri进行查询,返回Uri
          3.intert(Uri,ContentValues):将数据插入到Uri所指定的位置
          4.update(Uri,ContentValues,String,String []):更新uri指定位置的数据
          5.delete(Uri,String,String[]):删除uri指定位置的数据
          6.getType(Uri):返回数据的类型
    四、建立contentprovider工程,添加单元测试(http://www.cnblogs.com/kingshow123/p/sqlitecreate.html 中有介绍)
     

    注意:创建的内容提供者MyContentProvider,必须放在应用包(com.bruce.contentprovider),或者放在应用包的子包(com.bruce.contentprovider.demo)下。因为它是应用组件之一

    五、创建DbOpenHelper类

    package com.bruce.contentprovider.db;
    
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteDatabase.CursorFactory;
    import android.database.sqlite.SQLiteOpenHelper;
    
    public class DbOpenHelper extends SQLiteOpenHelper {
        
        private static String name = "mycont.db";
        private static int version = 1;
        public DbOpenHelper(Context context) {
            super(context, name, null, version);
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            String sql = "create table student( id integer primary key autoincrement,name varchar(64),address varchar(64))";
            db.execSQL(sql);
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
            // TODO Auto-generated method stub
    
        }
    
    }
    View Code

    六、创建MyContentProvider类

    package com.bruce.contentprovider.demo;
    
    import com.bruce.contentprovider.db.DbOpenHelper;
    
    import android.content.ContentProvider;
    import android.content.ContentUris;
    import android.content.ContentValues;
    import android.content.UriMatcher;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.net.Uri;
    
    public class MyContentProvider extends ContentProvider {
        
        private DbOpenHelper helper;
        private final static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
        private final static int STUDENT = 0;
        private final static int STUDENTS = 1;
        static{
            matcher.addURI("com.bruce.contentprovider.demo", "student/#", STUDENT); //单条记录
            matcher.addURI("com.bruce.contentprovider.demo", "student", STUDENTS);  //多条记录
        }
        
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            int count = -1;
            SQLiteDatabase database = helper.getWritableDatabase();
            switch (matcher.match(uri)) {
            case STUDENT:
                long id = ContentUris.parseId(uri);
                selection = (selection == null ? " id = " + id : " id = " + id + " and " + selection);
                count = database.delete("student", selection, selectionArgs);
                break;
            case STUDENTS:
                count = database.delete("student", selection, selectionArgs);
                break;
            default:
                throw new IllegalArgumentException("No match uri:" + uri);
            }
            return count;
        }
    
        @Override
        public String getType(Uri uri) {
            
            switch (matcher.match(uri)) {
            case STUDENT:
                return "vnd.android.cursor.item/student";
            case STUDENTS:
                return "vnd.android.cursor.dir/student";
            default:
                throw new IllegalArgumentException("No match uri:" + uri);
            }
        }
    
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            Uri resultUri = null;
            switch (matcher.match(uri)) {
            case STUDENTS:
                SQLiteDatabase database = helper.getWritableDatabase();
                long id = database.insert("student", null,values);
                resultUri = ContentUris.withAppendedId(uri, id);
                break;
    
            default:
                throw new IllegalArgumentException("No match uri:" + uri);
            }
            
            return resultUri;
        }
    
        @Override
        public boolean onCreate() {
            helper = new DbOpenHelper(getContext());
            return false;
        }
    
        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
            Cursor cursor = null;
            switch (matcher.match(uri)) {
            case STUDENT:
                long id = ContentUris.parseId(uri);
                selection = selection == null ? " id = " + id : " id = " + id + " and " + selection;
            case STUDENTS:
                SQLiteDatabase database = helper.getWritableDatabase();
                cursor = database.query("student", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            default:
                throw new IllegalArgumentException("No match uri:" + uri);
            }
            return cursor;
        }
    
        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
            switch (matcher.match(uri)) {
            case STUDENT:
                long id = ContentUris.parseId(uri);
                selection = (selection == null ? " id = " + id : " id = " + id + " and " + selection);
            case STUDENTS:
                SQLiteDatabase database = helper.getWritableDatabase();
                return database.update("student", values, selection, selectionArgs); //directly return the number of rows affected
            default:
                throw new IllegalArgumentException("No match uri:" + uri);
            }
        }
    
    }
    View Code

    七、创建MyTestProvider类

    package com.bruce.contentprovider.test;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import android.content.ContentResolver;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.net.Uri;
    import android.test.AndroidTestCase;
    import android.util.Log;
    
    public class MyTestProvider extends AndroidTestCase {
        
        private String TAG = "MyTestProvider";
        
        public void insertStudent(){
            ContentResolver resolver = getContext().getContentResolver();
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
            ContentValues values = new ContentValues();
            values.put("name", "姚明");
            values.put("address", "上海");
            Uri reUri = resolver.insert(uri, values);
            
            Cursor cursor = resolver.query(reUri, null, null, null, null);
            if(cursor.moveToNext()){
                int id = cursor.getInt(0);
                String name = cursor.getString(1);
                String address = cursor.getString(2);
                Log.i(TAG, "-->test insert id:" + id + ",name:" + name + ",address:" + address);
            }
            
        }
        
        public void deleteStudent(){
            ContentResolver resolver = getContext().getContentResolver();
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student/5");
            //String  selection = " name = ? ";
            //String[]  selectionArgs = {"姚明"};
            //int count = resolver.delete(uri, selection, selectionArgs);
            int count = resolver.delete(uri, null, null);
            Log.i(TAG, "-->test delete count=" + count);
            
        }
        
        public void updateStudent(){
            ContentResolver resolver = getContext().getContentResolver();
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student/1");
            ContentValues values = new ContentValues();
            values.put("name", "邹市明");
            values.put("address","遵义");
            //String selection = " name = ? ";
            //String[] selectionArgs = {"老毛"};
            //int count = resolver.update(uri, values, selection, selectionArgs);
            int count = resolver.update(uri, values, null, null);
            Log.i(TAG, "-->test update count = " + count);
        }
        
        public void queryById(){
            ContentResolver resolver = getContext().getContentResolver();
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student/1");
            Cursor cursor = resolver.query(uri, null, null, null, null);
            while(cursor.moveToNext()){
                int id = cursor.getInt(0);
                String name = cursor.getString(1);
                String address = cursor.getString(2);
                Log.i(TAG, "--> test queryById id = " + id + ",name = " + name + ",address= " + address);
            }
        }
        
        public void queryByName(){
            Map<String, String> map = new HashMap<String, String>();
            ContentResolver resolver = getContext().getContentResolver();
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
            String selection = " name = ? ";
            String[] selectionArgs = {"姚明"};
            Cursor cursor = resolver.query(uri, null, selection, selectionArgs, null);
            int count = cursor.getColumnCount();
            while(cursor.moveToNext()){
                for(int i=0; i<count; i++){
                    String cols_name = cursor.getColumnName(i);
                    String cols_value = cursor.getString(cursor.getColumnIndex(cols_name));
                    map.put(cols_name, cols_value);
                }
            }
            Log.i(TAG, "-->test queryByName:" + map.toString());
        }
        
        public void queryListStudent(){
            List<Map<String, String>> list = new ArrayList<Map<String,String>>();
            ContentResolver resolver = getContext().getContentResolver();
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
            Cursor cursor = resolver.query(uri, null, null, null, null);
            int count = cursor.getColumnCount();
            while(cursor.moveToNext()){
                Map<String, String> map = new HashMap<String, String>();
                for(int i=0; i<count; i++){
                    String cols_name = cursor.getColumnName(i);
                    String cols_value = cursor.getString(cursor.getColumnIndex(cols_name));
                    map.put(cols_name, cols_value);
                }
                list.add(map);
            }
            Log.i(TAG, "-->test queryListStudent:" + list.toString());
        }
        
        public void testGetType(){
            ContentResolver resolver = getContext().getContentResolver();
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student/1");
            Log.i(TAG, "-->testGetType plus id:" + resolver.getType(uri));
            
            uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
            Log.i(TAG, "-->testGetType:" + resolver.getType(uri));
        }
    }
    View Code

    八、监听内容提供者数据变化

    Ÿ   在内容提供者中可以通知其他程序数据发生变化,通过Context的getContentResolver()方法获取ContentResolver,调用其notifyChange()方法发送数据修改通知;

    Ÿ   在其他程序中可以通过ContentObserver监听数据变化

         通过Context的getContentResolver()方法获取ContentResolver

         调用其registerContentObserver()方法指定对某个Uri注册ContentObserver

         自定义ContentObserver,重写onChange()方法获取数据

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    1.需要被监听的对象(例如)下面放入代码

    首先需要调用一下 getContext.getcontentResolver().notifyChange(uri,null);  放在删除添加 或者其他的方法后面

      

    2.然后在Activity中继承ContentObserver类 自己实现oncreate方法在方法中写具体的业务代码 比如是

    Private class MyContentObserver  extends contentObserver(){

        Public MyContentObserver(Handle handle){

        Super(handle)

       }

       Public void onChange(){// 具体的业务代码 

         //可以用toast类去实现一些显示的功能

      }

    }

    3. 在主类中注册uri

    GetcontentResolver().registerContentObserver(“需要注册的uri”,ture,new MyContentObserver(new handle() ))   方法

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    发送修改通知:

    public Uri insert(Uri uri, ContentValues values) {
            Uri resultUri = null;
            switch (matcher.match(uri)) {
            case STUDENTS:
                SQLiteDatabase database = helper.getWritableDatabase();
                long id = database.insert("student", null,values);
                
                // Notify registered observers that a row was updated. 注册 observer 
                // @param observer The observer that originated the change, may be null            
                // 产生改变的Observer. 此处为Provider带来的改变,传 null
                this.getContext().getContentResolver().notifyChange(uri, null);// 发送修改通知
                
                //resultUri = Uri.parse("content://com.bruce.contentprovider.demo/student" + id);
                resultUri = ContentUris.withAppendedId(uri, id);
                break;
    
            default:
                throw new IllegalArgumentException("No match uri:" + uri);
            }
            
            return resultUri;
        }
    View Code

    也可以在其他应用中定义一个ContentObserver,监听Uri所对应的内容提供者的变化

    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            //定义一个ContentObserver
            ContentObserver observer = new ContentObserver(new Handler()) {
            
                 /**            
                  * Returns true if this observer is interested in notifications for
                  * changes made through the cursor the observer is registered with.            
                  */           
                // 是否传递自己的改变
                @Override
                public boolean deliverSelfNotifications() {
                    return super.deliverSelfNotifications();
                }
    
                // 当被监听的内容发生了改变时,调用该方法
                @Override
                public void onChange(boolean selfChange) {
                    Log.i("MainActivity", "监听到了变化!!");
                    //打印最后插入的信息
                    ContentResolver resolver = getContentResolver();
                    Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
                    //select * from student order by id desc limit 1
                    Cursor c = resolver.query(uri, null, null, null, " id desc limit 1");
                    if(c.moveToNext()){
                        String string = "id="+ c.getInt(0) + ",name=" + c.getString(1) + ",address=" + c.getString(2);
                        Log.i("MainActivity", string);
                        Toast.makeText(MainActivity.this, string, 1).show();
                    }
                    //父类未做任何操作
                    super.onChange(selfChange);
                }
                
            };
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
            getContentResolver().registerContentObserver(uri, true, observer);
        }
    View Code

     九、监听内容提供者实例,三个应用来完成,注意:测试这个监听数据变化不能用单元测试来完成,因为但点击单元测试完成后,应用自动关闭了。

       内容提供者,就用contentprovider工程,另外在创建aprovidertest和bprovidertest工程。如图:

    1.aprovidertest中的代码

    activity_app.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".AppActivity" >
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="test provider A" />
    
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:onClick="insert"
            android:text="Button" />
    
    </RelativeLayout>
    View Code

    AppActivity.java

    package com.bruce.eoe.provider;
    
    import android.net.Uri;
    import android.os.Bundle;
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.content.ContentValues;
    import android.util.Log;
    import android.view.Menu;
    import android.view.View;
    
    public class AppActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_app);
        }
        
        public void insert(View v){
            ContentResolver resolver = this.getContentResolver();
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
            ContentValues values = new ContentValues();
            values.put("name", "发哥");
            values.put("address", "香港");
            resolver.insert(uri, values);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.app, menu);
            return true;
        }
    
    }
    View Code

    2.bprovidertest中的代码

    MainActivity.java

    package com.bruce.bprovidertest;
    
    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;
    import android.util.Log;
    import android.view.Menu;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");
            ContentResolver resolver = this.getContentResolver();
            resolver.registerContentObserver(uri, true, new MyContentObserver(new Handler()));
        }
        
        private class MyContentObserver extends ContentObserver{
    
            public MyContentObserver(Handler handler) {
                super(handler);
            }
            
             // 得到数据的变化通知,该方法只能粗略知道数据的改变,并不能判断是哪个业务操作进行的改变   
            @Override  
            public void onChange(boolean selfChange)  
            {  
                // select * from person order by id desc limit 1 // 取得最近插入的值(序号大——>小并取第一个)   
                Uri uri = Uri.parse("content://com.bruce.contentprovider.demo/student");  
                ContentResolver resolver = MainActivity.this.getContentResolver();  
                Cursor cursor = resolver.query(uri, null, null, null, "id desc limit 1");  
                if(cursor.moveToFirst())  
                {  
                    String string = "id=" + cursor.getInt(0) + ",name=" + cursor.getString(1) + ",address=" + cursor.getString(2);  
                    Log.i("MyTest", string);  
                }  
            }  
    
        }
    
        
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
    }
    View Code

    首先运行contentprovider工程,在运行bprovidertest工程,然后再运行aprovidertest工程,点击Button按钮,就可以向contentprovider工程中插入数据,然后bprovidertest中可以监听到数据变化。

    测试时,或许会提示:java.lang.SecurityException: Permission Denial: opening provider  异常,在AndroidManifest.xml文件中的provider节点中加入 android:exproted = "true"  即可解决。

     <provider
                android:name="com.bruce.contentprovider.demo.MyContentProvider"
                android:authorities="com.bruce.contentprovider.demo"
                android:exported="true"
                ></provider>

     

  • 相关阅读:
    扩展的局域网
    参数估计
    以太网的 MAC 层
    poj 1523Tarjan算法的含义——求取割点可以分出的连通分量的个数
    tarjan算法--求解无向图的割点和桥
    spfa负环判断
    codeforce 489d bfs分层处理
    并查集优化——压缩路径——秩优化
    SPFA_queue_链式前向星最短路 & HDU2433
    POJ3046选蚂蚁创建集合_线性DP
  • 原文地址:https://www.cnblogs.com/kingshow123/p/contentprovider.html
Copyright © 2011-2022 走看看