天气说变就变,马上又变冷了,还好空气不错,阳光也不错,早起上班的车上的人也不多,公司来的同事和昨天一样一样的,可能明天会多一些吧,那就再来学习android吧。学了两个android的组件,这里学习下第三个android的组件,Content Provider内容提供器。

Content Provider向我们提供了在不同应用程序之间的数据共享,比如微信啊,支付宝啊,想要获取手机联系人的信息,而手机联系人是另一个应用程序,那么这时候就需要用到Content Provider了。Content Provider为存储和获取数据提供了统一的接口,对数据进行了封装,我们不用关心数据存储的细节,使用表的形式来组织数据。Android提供了一些默认的ContentProvider,比如音频,视频,图片和通讯录等。

类似于文件,SharedPreferences或者SQLiteDataBase都有一个路径,那么ContentProvider也是有路径的,它的路径由Uri表示,Uri主要包含了两部分的信息,一个是需要操作的ContentProvider,另一个就是对ContentProvider中的什么数据进行操作。一个简单的Uri:

content://com.example.contentprovidertest.provider/person/2

scheme:content://表示,这个是android定义好的,不能改变的

主机名或者authority:com.example.contentprovidertest.provider表示,唯一的,一般指的是包名,

路径:person,表示的是person这个表,2表示id为2。

如果要把上面的字符串转变为uri,那么就要使用Uri类中的parse()方法,如下:

    Uri uri=Uri.parse("content://com.example.contentprovidertest.provider/person/2");
这里先来写个例子,用来获取通讯录中的信息吧。新建ContentProviderTest工程,因为模拟器的联系人还没有创建,这里先添加几个好友:


接着我们继续编写代码,先在layout中添加listview,因为通讯录一般都是用listview来实现的。代码如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout    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:orientation="vertical"    tools:context="com.example.jared.contentprovidertest.MainActivity">    <ListView        android:id="@+id/contacts"        android:layout_height="match_parent"        android:layout_width="match_parent"/></LinearLayout>

这里就简单地加了一个listview,接着修改MainAcitivity代码:

package com.example.jared.contentprovidertest;import android.database.Cursor;import android.os.Bundle;import android.provider.ContactsContract;import android.support.v7.app.AppCompatActivity;import android.widget.ArrayAdapter;import android.widget.ListView;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    private ListView contactViews;    ArrayAdapter<String> adapter;    List<String> contactList = new ArrayList<String>();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        contactViews = (ListView)findViewById(R.id.contacts);        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, contactList);        contactViews.setAdapter(adapter);        readContacts();    }    public void readContacts() {        Cursor cursor = null;        try {            cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,                    null, null, null, null);            while(cursor.moveToNext()) {                String ContactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));                String ContactPhoneNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));                contactList.add(ContactName+'\n'+ContactPhoneNum);            }        } catch (Exception e) {            e.printStackTrace();        } finally {            if(cursor != null){                cursor.close();            }        }    }}

这里用了string类型的适配器,然后通过cursor来获取联系人名字和电话号码,其中的名字和电话的定义最终也是字符串。

String DISPLAY_NAME = "display_name";
String NUMBER = "number";
这个和数据库的存取很类似,接着在AndroidManifest中添加权限:

    <uses-permission android:name="android.permission.READ_CONTACTS"/>
然后运行app,效果如下:



由上可知,获得了三个联系人的信息,也就是我们刚保存的信息。

接着学习自定义的ContentProvider,这里借用了dbtest中的MyDBHelper类,新建myContenProvider类,代码如下:

package com.example.jared.contentprovidertest;import android.content.ContentProvider;import android.content.ContentValues;import android.content.UriMatcher;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.net.Uri;import android.support.annotation.Nullable;/** * Created by jared on 16/2/15. */public class myContentProvider extends ContentProvider {    public static final int PERSON_DIR = 0;    public static final int PERSON_ITEM = 1;    public static final int TEACHER_DIR = 2;    public static final int TEACHER_ITEM = 3;    private static UriMatcher uriMatcher;    private static final String AUTHORITY = "com.example.jared.contentprovidertest.provider";    private MyDBHelper myDBHelper;    static {        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);        uriMatcher.addURI(AUTHORITY, "person", PERSON_DIR);        uriMatcher.addURI(AUTHORITY, "person/#", PERSON_ITEM);        uriMatcher.addURI(AUTHORITY, "teacher", TEACHER_DIR);        uriMatcher.addURI(AUTHORITY, "teacher/#", TEACHER_DIR);    }    @Override    public boolean onCreate() {        myDBHelper = new MyDBHelper(getContext(), "PersonStore.db", null, 2);        return true;    }    @Override    public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {        SQLiteDatabase db = myDBHelper.getWritableDatabase();        int updateRows = 0;        switch (uriMatcher.match(uri)) {            case PERSON_DIR:                updateRows = db.update("person", contentValues, s, strings);                break;            case PERSON_ITEM:                String personId = uri.getPathSegments().get(1);                updateRows = db.update("person", contentValues, "id = ?", new String[]{personId});                break;            case TEACHER_DIR:                updateRows = db.update("teacher", contentValues, s, strings);                break;            case TEACHER_ITEM:                String teacherId = uri.getPathSegments().get(1);                updateRows = db.update("teacher", contentValues, "id = ?", new String[]{teacherId});                break;            default:                break;        }        return updateRows;    }    @Override    public int delete(Uri uri, String s, String[] strings) {        SQLiteDatabase db = myDBHelper.getWritableDatabase();        int deleteRows = 0;        switch (uriMatcher.match(uri)) {            case PERSON_DIR:                deleteRows = db.delete("person", s, strings);                break;            case PERSON_ITEM:                String personId = uri.getPathSegments().get(1);                deleteRows = db.delete("person", "id = ?", new String[]{personId});                break;            case TEACHER_DIR:                deleteRows = db.delete("teacher", s, strings);                break;            case TEACHER_ITEM:                String teacherId = uri.getPathSegments().get(1);                deleteRows = db.delete("teacher", "id = ?", new String[]{teacherId});                break;            default:                break;        }        return deleteRows;    }    @Nullable    @Override    public String getType(Uri uri) {        switch (uriMatcher.match(uri)) {            case PERSON_DIR:                return "vnd.android.cursor.dir/vnd."+AUTHORITY+".person";                //break;            case TEACHER_DIR:                return "vnd.android.cursor.dir/vnd."+AUTHORITY+".teacher";                //break;            case PERSON_ITEM:                return "vnd.android.cursor.item/vnd."+AUTHORITY+".person";                //break;            case TEACHER_ITEM:                return "vnd.android.cursor.item/vnd."+AUTHORITY+".teacher";                //break;            default:                break;        }        return null;    }    @Nullable    @Override    public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {        SQLiteDatabase db = myDBHelper.getWritableDatabase();        Cursor cursor = null;        switch (uriMatcher.match(uri)) {            case PERSON_DIR:                cursor = db.query("person", strings, s, strings1, null, null, s1);                break;            case PERSON_ITEM:                String personId = uri.getPathSegments().get(1);                cursor = db.query("person", strings, "id = ?", new String[]{personId}, null, null, s1);                break;            case TEACHER_DIR:                cursor = db.query("teacher", strings, s, strings1, null, null, s1);                break;            case TEACHER_ITEM:                String teacherId = uri.getPathSegments().get(1);                cursor = db.query("teacher", strings, "id = ?", new String[]{teacherId}, null, null, s1);                break;            default:                break;        }        return cursor;    }    @Nullable    @Override    public Uri insert(Uri uri, ContentValues contentValues) {        SQLiteDatabase db = myDBHelper.getWritableDatabase();        Uri uriReturn = null;        switch (uriMatcher.match(uri)) {            case PERSON_DIR:            case PERSON_ITEM:                long newPersonId = db.insert("person", null, contentValues);                uriReturn = Uri.parse("content://"+AUTHORITY+"/person/"+newPersonId);                break;            case TEACHER_DIR:            case TEACHER_ITEM:                long newTeacherId = db.insert("teacher", null, contentValues);                uriReturn = Uri.parse("content://"+AUTHORITY+"teacher"+newTeacherId);                break;            default:                break;        }        return uriReturn;    }}

这里基本上和数据库的操作没什么不同,就是需要注意AUTHORITY需要在AndroidManifest中注册。

通过UriMatcher来匹配uri,然后通过Uri.parse解析uri。此外这里又重写了onCreate方法,update方法,delete方法。getType方法,query方法,insert方法。其中onCreate方法主要是创建数据库,update为更新数据,delete是删除数据,query是查询数据,insert为插入数据,基本和数据库的操作很类似。

getType方法主要是获取Uri对象的MIME类型

如果以路径结尾的话,那么就是:vnd.android.cursor.dir/vnd.+authoriry+.path;

如果以id结尾的话,那么就是:vnd.android.cursor.item/vnd.+authoriry+.path;

接着就是AndroidManifest了,代码如下:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.jared.contentprovidertest" >    <uses-permission android:name="android.permission.READ_CONTACTS"/>    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme" >        <activity android:name=".MainActivity" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <provider            android:name=".myContentProvider"            android:exported="true"            android:authorities="com.example.jared.contentprovidertest.provider">        </provider>    </application></manifest>

这里需要添加provider,其中android:name属性是类名。android:exported属性表示对外暴露,所以需要为true。android:authorities属性表示的是authority,也就是上面代码的那个authority,必须一致。这样基本上就ok了。

接着我们创建一个ContentProviderTest2工程,用来获取,操作ContentProviderTest的内容。layout就参考了dbtest的工程的代码:

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <Button        android:id="@+id/createDB"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="创建数据库" />    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content">        <Button            android:id="@+id/addData"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="添加数据"/>        <Button            android:id="@+id/updateData"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="更新数据"/>        <Button            android:id="@+id/delData"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="删除数据"/>        <Button            android:id="@+id/queryData"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="查询数据"/>    </LinearLayout></LinearLayout>

接着编写代码实现各个按钮的功能:

package com.example.jared.contentprovidertest2;import android.content.ContentValues;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity {    private static final String TAB = "MainActivity";    private Button addDataBtn;    private Button deleteDataBtn;    private Button updateDataBtn;    private Button queryDataBtn;    public String id1, id2;    private static final String PERSON_URI = "content://com.example.jared.contentprovidertest.provider/person";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        addDataBtn = (Button)findViewById(R.id.addData);        addDataBtn.setOnClickListener(new myOnClickListener());        deleteDataBtn = (Button)findViewById(R.id.delData);        deleteDataBtn.setOnClickListener(new myOnClickListener());        updateDataBtn = (Button)findViewById(R.id.updateData);        updateDataBtn.setOnClickListener(new myOnClickListener());        queryDataBtn = (Button)findViewById(R.id.queryData);        queryDataBtn.setOnClickListener(new myOnClickListener());    }    private class myOnClickListener implements View.OnClickListener {        @Override        public void onClick(View view) {            switch (view.getId()) {                case R.id.addData:                    id1 = setAddDataBtn("xiao ming", 20, 172.5, "man");                    id2 = setAddDataBtn("xiao hong", 22, 162.5, "woman");                    break;                case R.id.delData:                    setDeleteDataBtn(id1);                    break;                case R.id.updateData:                    setUpdateDataBtn(id1, 175.0);                    break;                case R.id.queryData:                    setQueryDataBtn();                    break;                default:                    break;            }        }    }    public void setQueryDataBtn() {        Uri uri = Uri.parse(PERSON_URI);        Cursor cursor = getContentResolver().query(uri, null, null, null, null);        if(cursor != null) {            while (cursor.moveToNext()) {                String personName = cursor.getString(cursor.getColumnIndex("name"));                int personAge = cursor.getInt(cursor.getColumnIndex("age"));                double personHeight = cursor.getDouble(cursor.getColumnIndex("height"));                String personSex = cursor.getString(cursor.getColumnIndex("sex"));                Log.d(TAB, "name:"+personName + " |age:"+personAge + " |height:"                        +personHeight + " |sex:"+personSex);            }            cursor.close();        }    }    public void setUpdateDataBtn(String id, double height) {        Uri uri = Uri.parse(PERSON_URI+"/"+id);        ContentValues values = new ContentValues();        values.put("height", height);        getContentResolver().update(uri, values, null, null);    }    public void setDeleteDataBtn(String id) {        Uri uri = Uri.parse(PERSON_URI+"/"+id);        getContentResolver().delete(uri, null, null);    }    public String setAddDataBtn(String name, int age, double height, String sex) {        Uri uri = Uri.parse(PERSON_URI);        ContentValues values = new ContentValues();        values.put("name", name);        values.put("age", age);        values.put("height", height);        values.put("sex", sex);        Uri newUri = getContentResolver().insert(uri, values);        return newUri.getPathSegments().get(1);    }}

这里基本上都是先把字符串转换为Uri,然后通过getContentResolver()类的方法来实现各个功能,准备好代码后,我们继续运行看下效果:

首先是添加功能:按添加按钮再按查询,查看log信息如下:

02-15 03:47:53.730 17319-17319/com.example.jared.contentprovidertest2 D/MainActivity: name:xiao ming |age:20 |height:172.5 |sex:man02-15 03:47:53.780 17319-17319/com.example.jared.contentprovidertest2 D/MainActivity: name:xiao hong |age:22 |height:162.5 |sex:woman
已经添加了数据,然后是更新功能:按更新按钮再按查询,查看log信息如下:

02-15 03:49:33.210 17319-17319/com.example.jared.contentprovidertest2 D/MainActivity: name:xiao ming |age:20 |height:175.0 |sex:man02-15 03:49:33.210 17319-17319/com.example.jared.contentprovidertest2 D/MainActivity: name:xiao hong |age:22 |height:162.5 |sex:woman
已经更新身高为175.0了,然后是删除功能:按删除按钮再按查询,查看log信息如下:

02-15 03:50:46.650 17319-17319/com.example.jared.contentprovidertest2 D/MainActivity: name:xiao hong |age:22 |height:162.5 |sex:woman

查询功能已经在上面的多次操作中用过了,基本上访问另外一个app数据的功能也实现了。ContentProvider就先学到这里了,继续学习别的内容!



更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  3. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  4. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  5. Android数据存储之SQLite
  6. Kotlin从入门到沉迷
  7. 【android】ImageView的src和background的区别以及两者的妙用
  8. android listview的适配器------baseadapter
  9. Android本地化开发技巧

随机推荐

  1. Android应用开发相关下载资源(2014/10/19
  2. 从零开始 WIN8.1 下Android(安卓)开发环
  3. 如何在android画分析图(例如 柱状图、趋势
  4. Android使用贝塞尔线高仿QQ聊天消息气泡
  5. Will android (java) UUID.randomUUID()
  6. android:configChanges="orientation|key
  7. Android(安卓)Intent
  8. android中返回键事件
  9. Android开机自启APK应用
  10. android linearlayout imageview置顶摆放