• Android ContentProvider 简介


    当在系统中部署一个又一个Android应用之后,系统里将会包含多个Android应用,有时候就需要在小同的应用之问芡亭数据,比如现在有一个短信接收应用,用户想把接收到的陌生短信的发信人添加到联系人管理应用中,就需要在小同应用之问共宁数据。对于这种需要在小同应用之问共亨数据的需求,当然可以让一个应用程序直接去操作另个应用程序所记录的数据,比如操作它所记录的SharedPreferences、文件或数据库等,这种方式显得太杂乱了:不同的应用程序记录数据的方式差别很大,这种力式不利于应用程序之问进行数据交换。
    为了在应用程序之问交换数据,Android提供了ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API,当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用科序就可以通过提供ContentProvider来实现;其他应用程序就可通过ContentResolver来操作ContentProvider暴露的数据。
    ContentProvider也是Android应刖的四大组件之一,与Activity、Service、BroadcastReceiver相似,它们都需要存AndroidManifest.xml文件中进行配置。
    一旦某个应用程序通过ContentProvider暴露了自己的数据操作接口,那么不管该应用程序是否启动,其他应用程序都可通过该接口来操作该应用程序的内部数据,包括增加数据、删除数据、修改数据、查询数据等。


    MyContentProvider

    MyUser.java

    package com.supermario.mycontentprovider;
    
    import android.net.Uri;
    import android.provider.BaseColumns;
    
    public class MyUser {
        public static final String AUTHORITY = "com.supermario.MyContentProvider";
    
        // BaseColumn类中已经包含了_id字段
        public static final class User implements BaseColumns {
            // 定义Uri
            public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
            // 定义数据表列
             public static final String USER_NAME = "USER_NAME";
        }
    }

    MyContentProvider.java

    package com.supermario.mycontentprovider;
    
    import android.content.ContentProvider;
    import android.content.ContentUris;
    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.SQLException;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.database.sqlite.SQLiteQueryBuilder;
    import android.net.Uri;
    
    /**
     * MyContentProvider继承ContentProvider类,实现其insert,update,delete,getType,
     * onCreate等方法
     */
    public class MyContentProvider extends ContentProvider {
        // 定义一个SQLiteDatabase变量
        private SQLiteDatabase sqlDB;
        // 定义一个DatabaseHelper变量
        private DatabaseHelper dbHelper;
        // 数据库名
        private static final String DATABASE_NAME = "Users.db";
        // 数据库版本
        private static final int DATABASE_VERSION = 1;
        // 表名
        private static final String TABLE_NAME = "User";
    
        /**
         * 定义一个内部类
         * 
         * 这个内部类继承SQLiteOpenHelper类,重写其方法
         */
        public static class DatabaseHelper extends SQLiteOpenHelper {
            // 构造方法
            public DatabaseHelper(Context context) {
                // 父类构造方法
                super(context, DATABASE_NAME, null, DATABASE_VERSION);
            }
    
            // 当第一次创建数据库的时候调用该方法,可以为数据库增加一些表,和初始化一些数据
            @Override
            public void onCreate(SQLiteDatabase db) {
                // 在数据库里生成一张表
                db.execSQL("Create table "
                        + TABLE_NAME
                        + "( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);");
            }
    
            // 当更新数据库版本的时候,调用该方法。可以删除,修改表的一些信息
            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
                onCreate(db);
            }
        }
    
        // 这是一个回调函数,当生成所在类的对象时,这个方法被调用,创建一个数据库
        @Override
        public boolean onCreate() {
            dbHelper = new DatabaseHelper(getContext());
            return (dbHelper == null) ? false : true;
        }
    
        // 查询
        @Override
        public Cursor query(Uri uri, String[] projection, String selection,    String[] selectionArgs, String sortOrder) {
            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
            SQLiteDatabase db = dbHelper.getReadableDatabase();
            qb.setTables(TABLE_NAME);
            Cursor c = qb.query(db, projection, selection, null, null, null,sortOrder);
            c.setNotificationUri(getContext().getContentResolver(), uri);
            return c;
        }
    
        // 取得类型
        @Override
        public String getType(Uri uri) {
            return null;
        }
    
        // 插入数据
        @Override
        public Uri insert(Uri uri, ContentValues contentvalues) {
            sqlDB = dbHelper.getWritableDatabase();
            long rowId = sqlDB.insert(TABLE_NAME, "", contentvalues);
            if (rowId > 0) {
                Uri rowUri = ContentUris.appendId(MyUser.User.CONTENT_URI.buildUpon(), rowId).build();
                getContext().getContentResolver().notifyChange(rowUri, null);
                return rowUri;
            }
            throw new SQLException("Failed to insert row into" + uri);
        }
    
        // 删除数据
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            return 0;
        }
    
        // 更新数据
        @Override
        public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {
            return 0;
        }
    }

    MyContentActivity.java

    package com.supermario.mycontentprovider;
    
    import android.app.Activity;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.widget.Toast;
    
    public class MyContentActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 插入两条记录
             insertRecord("Test");
            insertRecord("Guo");
            // 显示记录
             displayRecords();
        }
    
        // 插入记录
        private void insertRecord(String userName) {
            ContentValues values = new ContentValues();
            values.put(MyUser.User.USER_NAME, userName);
            getContentResolver().insert(MyUser.User.CONTENT_URI, values);
        }
    
        private void displayRecords() {
            // 构建一个字符串数组用于存放用户的记录
             String columns[] = new String[] { MyUser.User._ID,MyUser.User.USER_NAME };
            // 设定ContentProvider的Uri
            Uri myUri = MyUser.User.CONTENT_URI;
            Cursor cur = managedQuery(myUri, columns, null, null, null);
            if (cur.moveToFirst()) {
                String id = null;
                String userName = null;
                do {
                    id = cur.getString(cur.getColumnIndex(MyUser.User._ID));
                    userName = cur.getString(cur.getColumnIndex(MyUser.User.USER_NAME));
                    // 显示数据表中的数据
                    Toast.makeText(this, id + " " + userName, Toast.LENGTH_LONG).show();
                } while (cur.moveToNext());
            }
        }
    }

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.supermario.mycontentprovider"
        android:versionCode="1"
        android:versionName="1.0" >
        <uses-sdk android:minSdkVersion="10" />
        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <!-- 声明ContentProvider -->
            <provider android:name="MyContentProvider"
                android:authorities="com.supermario.MyContentProvider"></provider>
            <activity
                android:name=".MyContentActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>

    界面:

    PIC_20131119_160654_9A9


    MyContentClient

    MyConrentClientActivity.java

    package com.supermario.mycontentclient;
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    public class MyContentClientActivity extends Activity {
        public static final String AUTHORITY = "com.supermario.MyContentProvider";
        private Button insertButton = null;
        // 访问ContentProvider的Uri
        Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            TextView show=(TextView)findViewById(R.id.show);
            StringBuffer sb=new StringBuffer("");
            // 得到ContentProvider对于表的所有数据,以游标格式保存
            Cursor c = managedQuery(CONTENT_URI,
                    new String[] { "_id", "USER_NAME" }, null, null, null); 
            // 循环打印ContentProvider的数据
            if (c.moveToFirst()) {
                String _id = null;
                String user_name = null;
                do {
                    // 得到_id列,USER_NAME列
                    _id = c.getString(c.getColumnIndex("_id"));
                    user_name = c.getString(c.getColumnIndex("USER_NAME"));
     
                    sb.append("_id = " + _id + ", user_name = " + user_name+"
    ");
                } while (c.moveToNext());
            }
            show.setText(sb);
            // 根据Id得到控件对象
            insertButton = (Button) findViewById(R.id.insert);
            // 给按钮绑定事件监听器
            insertButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 得到EditText输入的数据
                    String username = ((EditText) findViewById(R.id.userName))
                            .getText().toString();
                    // 生成一个ContentResolver对象
                    ContentResolver cr = getContentResolver();
                    // 生成一个ContentValues对象
                    ContentValues values = new ContentValues();
                    // 将EditText输入的值,保存到ContentValues对象中
                    values.put("USER_NAME", username);
                    // 插入数据
                    cr.insert(CONTENT_URI, values);
                }
            });
        }
    }

    main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <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/show"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        <!-- 文本编辑框 ,用于输入信息-->
        <EditText
            android:id="@+id/userName"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        <!-- 输入按钮 -->
        <Button
            android:id="@+id/insert"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />
    </LinearLayout>

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.supermario.mycontentclient"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk android:minSdkVersion="10" />
    
        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <activity
                android:name=".MyContentClientActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    界面:

    PIC_20131119_160646_814

  • 相关阅读:
    MSClass (Class Of Marquee Scroll通用不间断滚动JS封装类)
    IE和FF下javascript获取网页宽高及窗口大小
    JSON View – JSON格式化查看工具
    查询功能所属的菜单
    会计科目API CCID
    应付的帐龄分析SQL
    采购到入库所经历的表
    金额大小写转换(2)
    oracle行列转换总结
    金额大小写转换(1)
  • 原文地址:https://www.cnblogs.com/AndyGe/p/3431664.html
Copyright © 2020-2023  润新知