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>

     

  • 相关阅读:
    FJNU 1151 Fat Brother And Geometry(胖哥与几何)
    FJNU 1157 Fat Brother’s ruozhi magic(胖哥的弱智术)
    FJNU 1159 Fat Brother’s new way(胖哥的新姿势)
    HDU 3549 Flow Problem(最大流)
    HDU 1005 Number Sequence(数列)
    Tickets(基础DP)
    免费馅饼(基础DP)
    Super Jumping! Jumping! Jumping!(基础DP)
    Ignatius and the Princess IV(基础DP)
    Keywords Search(AC自动机)
  • 原文地址:https://www.cnblogs.com/kingshow123/p/contentprovider.html
Copyright © 2011-2022 走看看