Android学习笔记七之ContentProvider
2016-06-20 14:28
543 查看
Android学习笔记起之ContentProvider
ContentProvicer简介
Content provider,即是内容提供者或者内容提供商。ContentProvider生命周期应用安装完成,就会创建完成,手机开机后,第一次被访问时,被创建
只要创建了,只要手机没关机,就会一直存在,类似于在注册表里注册一样
手机关机,才会消失
应用里的数据都可以提供访问.不一定是数据库,在方法里自已定义就可以,但通常是访问数据库
作用
ContentProvider用于不同进程之间传递数据,这也是官方推荐的方式。当我们想要在自己的应用中访问别的应用的数据,比如获取手机联系人,手机短信等的时候,就需要用到ContentProvider了
当我们自己的应用,需要把自己的一些数据给其它应用进行操作,我们就可以用到contentprovider了。
简单的说,就是Contentprovider为不同应用之间数据共享提供统一的接口。ContentProvider使用表的形式组织数据,所以提供的方法跟表的操作类似,ContentProvider提供如下的方法:
query:查询数据
insert:插入数据
update:更新数据
delete:删除数据
getType:得到数据类型
onCreate:创建数据时调用的回调函数
使用ContentProvider需要一个uri,例如获取手机联系人的uri:
content://com.android.contacts/data/phones
URI解析如下图所示
使用系统提供的ContentProvider
很多时候我们都是使用系统提供的ContentProvider,使用ContentResolver来读取其他应用的信息,例如读取系统APP,短信,联系人, 手机相册等!例如,我们读取手机联系人读取手机联系人
package com.example.contentprovider; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.provider.ContactsContract; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getContacts(); } private void getContacts() { ContentResolver contentResolver = this.getContentResolver(); Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; System.out.println("------>>" + uri); Cursor cursor = contentResolver.query(uri, null, null, null, null); while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); System.out.println("-----------------------------------"); System.out.println("联系人:" + name); System.out.println("电话号码:" + number); } cursor.close(); } }
获取手机联系人需要用到系统权限,所以需要在AndroidManifest.xml文件中注册:
<uses-permission android:name="android.permission.READ_CONTACTS"/>
运行效果截图
这样就可以实现简单的读取手机联系人的效果,下面介绍自定义ContentProvider.
自定义ContentProvider
自定义ContentProvider的步骤如下:在想要进行数据分享的APP中,创建一个继承ContentProvider的类
实现对应的方法,按照需要进行重写,方法有onCreate()只执行一次,初始化ContentProvider,insert(),delete(),update(),query(),getType()获取ContentProvider数据的MIME类型
在AndroidManifest.xml文件中注册自定义的ContentProvider,至少需要三个属性,name,用于指定ContentProvider的全限定类名;authorities,用于匹配ContentProvider的uri;exported,用于指定是否共享数据,true,共享,false,不共享。
使用UriMatcher,完成uri的匹配
在另外的应用中调用getContentProvider()方法获取到Resolver对象,再进行对应的操作
下面进行代码实现:
创建一个继承ContentProvider的类
package com.example.contentprovider; 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; import android.support.annotation.Nullable; /** * Created by Devin on 2016/6/17. */ public class MYContentProvicer extends ContentProvider { private static UriMatcher mUriMatcher; private static final String AUTHORITIES = "com.example.contentprovider"; private static final int PERSON = 1; private SQLiteDatabaseOpenHelper mOpenHelper; /** * 利用静态代码块初始化UriMatcher * 在UriMatcher中包含了多个Uri,每个Uri代表一种操作 * 当调用UriMatcher.match(Uri uri)方法时就会返回该uri对应的code; */ static { mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); mUriMatcher.addURI(AUTHORITIES, "test", PERSON); } /** * 初始化方法,只执行一次,完成对ContentProvider的初始化 * * @return */ @Override public boolean onCreate() { mOpenHelper = new SQLiteDatabaseOpenHelper(this.getContext()); return true; } /** * 查询方法 * * @param uri * @param strings * @param s * @param strings1 * @param s1 * @return */ @Nullable @Override public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) { return null; } /** * 获取ContentProvider的MIME类型 * * @param uri * @return */ @Nullable @Override public String getType(Uri uri) { return null; } /** * 插入数据方法 * * @param uri * @param contentValues * @return */ @Nullable @Override public Uri insert(Uri uri, ContentValues contentValues) { switch (mUriMatcher.match(uri)) { case PERSON: SQLiteDatabase mDataBase = mOpenHelper.getReadableDatabase(); long rowId = mDataBase.insert("test", null, contentValues); if (rowId >= 1) { //通知数据已经发生改变 getContext().getContentResolver().notifyChange(uri, null); return ContentUris.withAppendedId(uri, rowId); } break; } return null; } /** * 删除数据的方法 * * @param uri * @param s * @param strings * @return */ @Override public int delete(Uri uri, String s, String[] strings) { return 0; } /** * 更新数据的方法 * * @param uri * @param contentValues * @param s * @param strings * @return */ @Override public int update(Uri uri, ContentValues contentValues, String s, String[] strings) { return 0; } }
SQliteDatabaseHelper
package com.example.contentprovider; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; /** * Created by Devin on 2016/6/17. */ public class SQLiteDatabaseOpenHelper extends SQLiteOpenHelper { private static final String DATABASENAME = "test1";//数据库名称 private static final int DATABASEVERSION = 1;//数据库版本 private String sql = "CREATE TABLE test(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(20),phone varchar(50),salary Integer(12))"; public SQLiteDatabaseOpenHelper(Context context) { super(context, DATABASENAME, null, DATABASEVERSION); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { sqLiteDatabase.execSQL(sql); } /** * 数据库版本版本发生变化时的方法 * * @param sqLiteDatabase * @param i * @param i1 */ @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } }
在AndroidManifest.xml文件中注册
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.contentprovider">
<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=".MYContentProvicer"
android:authorities="com.example.contentprovider"
android:exported="true"></provider>
</application>
</manifest>
新建一个project,在应用中调用getContentResolver()方法获取ContentResolver,然后实现对ContentProvider的操作
package com.example.client; import android.content.ContentResolver; import android.content.ContentValues; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends AppCompatActivity { Button btn_insert; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_insert = (Button) findViewById(R.id.btn_insert); final ContentResolver resolver = this.getContentResolver(); btn_insert.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ContentValues values = new ContentValues(); values.put("name", "张三"); values.put("phone", "15677822442"); values.put("salary", 8000); Uri uri = Uri.parse("content://com.example.contentprovider/test"); resolver.insert(uri, values); Toast.makeText(getApplicationContext(), "恭喜你,数据插入成功", Toast.LENGTH_SHORT).show(); } }); } }
最后实现效果如下:
插入数据之后,在File Explorer中将数据表导出,用SQLite Expert Personal 4打开
这样就可以实现一个简单的自定义ContentProvider,将自己应用的数据共享出去,不过这种做法比较少见,因为自己的应用数据很少有向其他应用共享的。
通过注册一个观察者,观察ContentProvider的数据变化
/** * 自定义一个类,继承ContentObserver,重写onChange方法,观察ContentProvider数据发生变化 */ private class MYContentObserver extends ContentObserver { public MYContentObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { System.out.println("MYContentObserver正在观察ContentProvider数据变化"); long lastTime = 0; if (System.currentTimeMillis() - lastTime > 2000) { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://com.example.contentprovider/test"); lastTime = System.currentTimeMillis(); } else { System.out.println("时间间隔过短,忽略此次更新"); } } @Override public boolean deliverSelfNotifications() { return true; } }
在onCreate方法中注册观察者
Uri uri = Uri.parse("content://com.example.contentprovider/test"); mContentObserver = new MYContentObserver(new Handler()); getApplicationContext().getContentResolver().registerContentObserver(uri, true, mContentObserver);
在onDestroy方法中取消注册观察者
@Override protected void onDestroy() { super.onDestroy(); if (mContentObserver != null) { getApplicationContext().getContentResolver().unregisterContentObserver(mContentObserver); } }
至此,ContentProvider的简单学习就完成了。
相关文章推荐
- px、pt、ppi、dpi、dp、sp之间的关系
- 我的Android进阶之旅---Activity不同启动模式下应用程序栈的变化
- Java Jvm、Android Dalvik和Android Art(一)——Android之路
- Android TypedArray使用方法
- 1.1、Android Studio创建一个项目
- 1.1、Android Studio创建一个项目
- 使用android自带的DownloadManager来实现版本更新
- Android SQLiteDatabase帮助类SQLiteOpenHelper的使用
- android 各类常用框架大全(不全)
- android中The connection to adb is down,问题和解决
- android material design之CollapsingToolbarLayout(五)
- 如何在Android Studio添加aar包或jar包引用
- synchronized的理解
- Android缓存机制&一个缓存框架推荐
- android 使用代码和xml配合进行布局
- Android混淆打包
- Android中的Surface和SurfaceView
- Android studio 自动导入(全部)包 import
- Android富文本编辑器总结(二)
- Android-扫二维码和生成二维码