android基础---->ContentProvider的使用
内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。目前,使用内容提供器是Android 实现跨程序共享数据的标准方式。不同于文件存储和SharedPreferences 存储中的两种全局可读写操作模式,内容提供器可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险。接下来,我们开始内容提供器的学习。content provider的原理说明,参见另外一篇博客(android高级---->ContentProvider的源码分析)
目录导航:
内容提供器简单说明
一、 内容提供器的用法:
- 使用现有的内容提供器来读取和操作相应程序中的数据
- 创建自己的内容提供器给我们程序的数据提供外部访问接口,需要继承ContentProvider类
二、 ContentResolver的基本用法:
- 得到实例: 可以通过Context 中的getContentResolver()方法获取到该类的实例
- 基本方法: 提供了一系列的方法用于对数据进行CRUD 操作
- 使用注意: ContentResolver中的增删改查方法都是不接收表名参数的,而是使用一个Uri 参数代替,这个参数被称为Content URI。
三、 内容URI的基本介绍:
- 重要用作: 内容URI 给内容提供器中的数据建立了唯一标识符
- 组成部分: 权限(authority)和路径(path)。
- 权限路径: 权限是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名;路径则是用于对同一应用程序中不同的表做区分的,通常都会添加到权限的后面。
访问其它的Content Provider
创建一个简单项目,结构如下:
一、 在activity_main.xml文件中创建一个ListView的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
二、 在MainActivity.java中:
package com.example.linux.getcontact; 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 listView; ArrayAdapter<String> adapter; List<String> contactsList = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView); adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList); listView.setAdapter(adapter); readContacts(); } private void readContacts() { Cursor cursor = null; try { // 查询联系人数据 cursor = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); while (cursor.moveToNext()) { // 获取联系人姓名 String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); // 获取联系人手机号 String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); contactsList.add(displayName + "\n" + number); } } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) { cursor.close(); } } } }
三、 读取系统联系人是需要声明权限的,在AndroidManifest.xml中增加权限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
创建自己的Content Provider
上一个自己的程序中访问其他应用程序的数据。总体来说思路还是非常简单的,只需要获取到该应用程序的内容URI,然后借助ContentResolver进行CRUD 操作就可以了。以下我们创建自己的内容提供器。
创建内容提供器--Server
项目结构:
一、 创建一个与数据库表对应的Bean:Person.java:
package com.example.linux.contentproviderserver.model; /** * Created by Linux on 2016/3/4. */ public class Person { private Integer _id; private String name; private String age; public Integer get_id() { return _id; } public void set_id(Integer _id) { this._id = _id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
二、 接着建立一个关于数据库的工具类:DBOpenHelper.java
package com.example.linux.contentproviderserver.util; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; /** * Created by Linux on 2016/3/4. */ public class DBOpenHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "person.db"; //数据库名称 private static final int DATABASE_VERSION = 1;//数据库版本 private static final String CREATE_TABLE_PERSON = "CREATE TABLE person (_id integer primary key autoincrement, name varchar(20), age varchar(10))"; private static final String DROP_TABLE_PERSON = "DROP TABLE IF EXISTS person"; public DBOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_TABLE_PERSON); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL(DROP_TABLE_PERSON); onCreate(db); } }
三、 创建一个自己的继承了ContentProvider的内容提供器:PersonProvider.java
- 做一些初始化的工作:
private final static String TAG = "PersonProvider"; private DBOpenHelper dbOpenHelper; private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH); private static final int PERSONS = 1; private static final int PERSON = 2; private static final String AUTHORITY = "com.example.linux.contentproviderserver.action.PersonProvider"; private static final String PATH_1 = "person"; private static final String PATH_2 = "person/#"; static { Log.i(TAG, "on PersonProvider static"); MATCHER.addURI(AUTHORITY, PATH_1, PERSONS); MATCHER.addURI(AUTHORITY, PATH_2, PERSON); } @Override public boolean onCreate() { Log.i(TAG, "on PersonProvider create"); this.dbOpenHelper = new DBOpenHelper(this.getContext()); return false; }
- 重写它的查插入方法:insert()
// 插入person表中的所有记录 /person // 插入person表中指定id的记录 /person/10 @Override public Uri insert(Uri uri, ContentValues values) { Log.i(TAG, "uri: " + uri.getPath() + ", values: " + values.getAsString("name")); SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); switch (MATCHER.match(uri)) { case PERSONS: // 特别说一下第二个参数是当name字段为空时,将自动插入一个NULL。 long rowid = db.insert("person", "name", values); Uri insertUri = ContentUris.withAppendedId(uri, rowid);// 得到代表新增记录的Uri this.getContext().getContentResolver().notifyChange(uri, null); return insertUri; case PERSON: Log.i("some", "soem"); return null; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
- 重写它的删除方法,delete()方法:
@Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); int count = 0; switch (MATCHER.match(uri)) { case PERSONS: count = db.delete("person", selection, selectionArgs); return count; case PERSON: long id = ContentUris.parseId(uri); String where = "_id=" + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } count = db.delete("person", where, selectionArgs); return count; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
- 重写它的更新方法:update()
@Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); int count = 0; switch (MATCHER.match(uri)) { case PERSONS: count = db.update("person", values, selection, selectionArgs); return count; case PERSON: long id = ContentUris.parseId(uri); String where = "_id=" + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } count = db.update("person", values, where, selectionArgs); return count; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
- 重写它的查询方法,query()
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Log.i(TAG, "PersonProvider query"); SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); int matchResult = MATCHER.match(uri); switch (MATCHER.match(uri)) { case PERSONS: return db.query("person", projection, selection, selectionArgs, null, null, sortOrder); case PERSON: long id = ContentUris.parseId(uri); String where = "_id=" + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } return db.query("person", projection, where, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
- 重写它的类型方法,getType()
//返回数据的MIME类型。 @Override public String getType(Uri uri) { Log.i(TAG, "PersonProvider get type"); switch (MATCHER.match(uri)) { case PERSONS: return "vnd.android.cursor.dir/person"; case PERSON: return "vnd.android.cursor.item/person"; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
五、 在MainActivity方法,为了方便得到数据库中的数据,添加了查询与增加方法:
package com.example.linux.contentproviderserver; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Toast; import com.example.linux.contentproviderserver.util.DBOpenHelper; /** * writer: huhx * 内容提供器的服务端 */ public class MainActivity extends AppCompatActivity { private final static String TAG = "PersonProvider"; private DBOpenHelper dbOpenHelper; SQLiteDatabase database = null; private StringBuffer stringBuffer = null; @Override protected void onCreate(Bundle savedInstanceState) { Log.i(TAG, "main on create."); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbOpenHelper = new DBOpenHelper(this); database = dbOpenHelper.getWritableDatabase(); } // 查询所有的数据 public void queryAll(View view) { stringBuffer = new StringBuffer(); Cursor cursor = database.rawQuery("select * from person", null); cursor.moveToFirst(); while(cursor.moveToNext()) { String name = cursor.getString(1); int age = cursor.getInt(2); stringBuffer.append("name: " + name + ", age: " + age + "\n"); } if (stringBuffer.toString().equals("")) { Toast.makeText(MainActivity.this, "nothing", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, stringBuffer, Toast.LENGTH_SHORT).show(); } } //插入数据 public void insertData(View view) { Object[] object = new Object[]{"linux", 23}; database.execSQL("insert into person(name, age) values(?, ?)", object); } @Override protected void onDestroy() { super.onDestroy(); database.close(); } }
使用内容提供器--Client
项目结构:
一、在MainActivity中增加了查询与插入功能:
package com.example.linux.contentproviderclient; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Toast; /** * 内容提供器的客户端 */ public class MainActivity extends AppCompatActivity { private StringBuffer stringBuffer = new StringBuffer(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // 插入数据 public void insert(View view) { ContentResolver contentResolver = getContentResolver(); Uri insertUri = Uri.parse("content://com.example.linux.contentproviderserver.action.PersonProvider/person"); ContentValues values = new ContentValues(); values.put("name", "wangkuifeng"); values.put("age", 23); Uri uri = contentResolver.insert(insertUri, values); Toast.makeText(MainActivity.this, "insert success: " + uri, Toast.LENGTH_SHORT).show(); } // 查询数据 public void query(View view) { ContentResolver contentResolver = getContentResolver(); Uri queryUri = Uri.parse("content://com.example.linux.contentproviderserver.action.PersonProvider/person/5"); Cursor queryResult = contentResolver.query(queryUri, null, null, null, null); int count = queryResult.getCount(); for (queryResult.moveToFirst(); !queryResult.isAfterLast(); queryResult.moveToNext()) { String name = queryResult.getString(1); int age = queryResult.getInt(2); stringBuffer.append("name: " + name + ", age: " + age + "\n"); } Toast.makeText(MainActivity.this, stringBuffer.toString() + "\ncount: " + count, Toast.LENGTH_SHORT).show(); queryResult.close(); } }
友情链接
- 访问其它的Content Provider 访问密码 777a
- 创建自己的Content Provider 访问密码 7388
相关文章
- Android jni 注意项
- Android在Fragment中如何安全访问父Activity中的SQLite实例
- 腾讯Android自动化测试实战第1章
- Android V1及V2签名原理简析
- Android基础总结(七)BroadcastReceiver
- Android基础总结(六)Activity
- Android基础-系统架构分析,环境搭建,下载Android Studio,AndroidDevTools,Git使用教程,Github入门,界面设计介绍
- Android基础-系统架构分析,环境搭建,下载Android Studio,AndroidDevTools,Git使用教程,Github入门,界面设计介绍
- Android开发利器 - Charles + Genymotion 调试网络应用程序
- Android ANR全解析&华为AGC性能管理解决ANR案例集
- 《精通移动App测试实战:技术、工具和案例》一1.7 创建一个Android项目
- Android JNI -基础篇
- Android基础【1】杀死进程(强行停止)应用程序的方法
- android二级listview列表
- android studio 不能在线更新android SDK Manager问题解决办法
- Android Studio报错:Could not find method android() for arguments
- 传Facebook故意破坏Android版软件以此测试用户忠诚度
- android基础开发学习记录一
- Android应用开发基础篇(3)-----ListView
- Android应用开发基础篇(4)-----TabHost(选项卡)
- Android系统启动流程(一)解析init进程启动过程
- 图片异步载入之 Android-Universal-Image-Loader
- Unity 基础 之 实现简单的Android移动端本地数据读取与写入封装(简单加密写入,解密读取 json 数据)
- Unity Android 之 基础 Unity 调用 Android 的原生方法的方式的一些简单整理(仅供参考)
- Android Studio 基础 之 截图,指定截图区域动态截图
- 【Android开源框架】使用andbase开发框架实现绘制折线图
- Android界面开发基础
- 亚马逊 android S3 sdk接入(sts)
- Android基础入门教程
- Android 使用 sqlcipher 加密数据库