四大组件之---ContentProvider(内容提供者)
一、ContentProvider应用场景:
我们想在自己的应用中访问别的应用,或者说一些ContentProvider暴露给我们的一些数据, 比如 手机联系人,短信等!我们想对这些数据进行读取或者修改,这就需要用到ContentProvider了! 我们自己的应用,想把自己的一些数据暴露出来,给其他的应用进行读取或操作,我们也可以用 到ContentProvider,另外我们可以选择要暴露的数据,就避免了我们隐私数据的的泄露!、
二、ContentProvider概念讲解
2.1 ContentProvider的URI:
主要分三个部分:scheme, authority and path。scheme表示上图中的content://, authority表示B部分,path表示C和D部分。
A部分:表示是一个Android内容URI,说明由ContentProvider控制数据,该部分是固定形式,不可 更改的。
B部分:是URI的授权部分,是唯一标识符,用来定位ContentProvider。格式一般是自定义 ContentProvider类的完全限定名称,注册时需要用到,如: com.example.transportationprovider
C部分和D部分:是每个ContentProvider内部的路径部分,C和D部分称为路径片段,C部分指向一个对 象集合,一般用表的名字,如:/trains表示一个笔记集合;D部分指向特定的记录, 如:/trains/122表示id为122的单条记录,如果没有指定D部分,则返回全部记录。
2.2 使用系统提供的ContentProvider(比如通讯录信息)
打开模拟器的file exploer/data/data/com.android.providers.contacts/databases/contact2.db 导 出后使用SQLite图形工具查看,三个核心的表:raw_contact表,data表,mimetypes表(具体请见上篇博客,这篇主要介绍自定义ContentProvider)
2.3 自定义ContentProvider
我们自己的应用,想把自己的一些数据暴露出来,给其他的应用进行读取或操作,我们也可以用到 ContentProvider,另外我们可以选择要暴露的数据,就避免了我们隐私数据的的泄露!
三、代码实现
1、在分享数据的app中创建一个类,继承ContentProvider
实现对应的方法,也可以不实现,默认空实现,按需进行重写。
onCreate() 只执行一次,用于初始化Provider
insert() 插入 delete()删除 update()更新 qurey()查询
getType() 获得ContentProvider数据的MIMI类型
public class NameContentProvider extends ContentProvider { //初始化一些常量 private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); private DBOpenHelper dbOpenHelper; //为了方便直接使用UriMatcher,这里addURI,下面再调用Matcher进行匹配 static { matcher.addURI("com.ttit.providers.myprovider", "test", 1); } @Override public boolean onCreate() { dbOpenHelper = new DBOpenHelper(this.getContext(), "test.db", null, 1); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { switch (matcher.match(uri)) { //把数据库打开放到里面是想证明uri匹配完成 case 1: SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); long rowId = db.insert("test", null, values); if (rowId > 0) { //在前面已有的Uri后面追加ID Uri nameUri = ContentUris.withAppendedId(uri, rowId); //通知数据已经发生改变 getContext().getContentResolver().notifyChange(nameUri, null); return nameUri; } } return null; } @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; } }
2、在AndroidManifest.xml对ContentProvider进行注册
<!-- 属性依次为:全限定类名,用于匹配的URI,是否共享数据 --> <provider android:name="com.ttit.core.provider.NameContentProvider" android:authorities="com.ttit.providers.myprovider" android:exported="true" />
3、使用UriMatchar,完成对uri的匹配
//1、初始化一些常量,UriMatcher private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); private DBOpenHelper dbOpenHelper; //2、为了方便直接使用UriMatcher,这里addURI,下面再调用Matcher进行匹配 //匹配返回标识码1,不匹配返回-1 static { matcher.addURI("com.ttit.providers.myprovider", "test", 1); } //3、在下面需要匹配uri地方使用match方法 @Override public Uri insert(Uri uri, ContentValues values) { switch (matcher.match(uri)) { //把数据库打开放到里面是想证明uri匹配完成 case 1: SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); long rowId = db.insert("test", null, values); if (rowId > 0) { //在前面已有的Uri后面追加ID Uri nameUri = ContentUris.withAppendedId(uri, rowId); //通知数据已经发生改变 getContext().getContentResolver().notifyChange(nameUri, null); return nameUri; } } return null; }
4、ContentProvider2Activity.java代码
在另一个工程中,调用getContentResolve()方法获得resolve对象,再调用对应的操作方法即可
public class ContentProvider2Activity extends AppCompatActivity { private Button btninsert; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.cp_layout2); btninsert = (Button) findViewById(R.id.btninsert); //读取contentprovider 数据 final ContentResolver resolver = this.getContentResolver(); btninsert.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ContentValues values = new ContentValues(); values.put("name", "测试"); Uri uri = Uri.parse("content://com.ttit.providers.myprovider/test"); resolver.insert(uri, values); Toast.makeText(getApplicationContext(), "数据插入成功", Toast.LENGTH_SHORT).show(); } }); } }
其他代码
cp_layout2.xml
<?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/btninsert" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="插入"/> </LinearLayout>
DBOpenHelper.java
public class DBOpenHelper extends SQLiteOpenHelper { final String CREATE_SQL = "CREATE TABLE test(_id INTEGER PRIMARY KEY AUTOINCREMENT,name)"; public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_SQL); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } }