ContentProvider作为Android四大组件之一,看起来十分牛逼,但在真正的项目中,其实我们很少用到。除非像在腾讯、阿里这样的大公司里,由于本公司旗下的几个APP之间需要进行一些数据共享,例如微信需要调用QQ的一些数据库,此时就需要使用ContentProvider了。它是Android中专门用于不同应用之间进行数据共享的方式,ContentProvider的底层实现了Binder,但系统已经为我们进行了封装,我们无需关心底层即可轻松实现IPC(Inter-Process Communication跨进程通信)。
不同应用之间的通信,这里我主要讲两点:
第一:android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等),许多社交类APP中都需要导入系统得联系人,此处我们先介绍怎样在APP中导入系统得通讯录。
第二:自定一个ContentProvider,再通过另外一个APP访问其中数据。
源码地址
-
通讯录中的一个Item中主要有两个重要信息,姓名与电话号码,它们都是储存在手机的data/data/com.android.provider.contacts数据库中,但是姓名与电话号码并不是储存在同一张表中
- 表raw_contacts 储存 编号 _id 姓名display_name
- 表data 储存 编号raw_contact_id 号码data1
两者通过编号连接在一起
以下是代码,主要思路是
public class MainActivity extends Activity {
//声明访问通话记录的Uri字符串
//data/data/com.android.providers.contacts/databases
private String callLogs = "content://call_log/calls";
//声明访问raw_contacts表格的uri字符串
private String raw_contacts_string = "content://com.android.contacts/raw_contacts";
//声明访问data表格的uri字符串
private String data_string = "content://com.android.contacts/data/phones";
/**
* 表raw_contacts _id display_name
* 表data raw_contact_id data1
* 联系人姓名保存在表raw_contacts中的列名display_name中
* 电话号码保存在表data的列名data1中
* 两者通过一个共同的id和raw_contact_id联系在一起
*/
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list_main);
List
1 自定义类继承系统ContentProvider类
2 实现抽象方法,依次实现相关的数据库操作
3 在AndroidManifest.xml文件中注册CP
- name 指定自定义CP的类名
- authorities 指定访问此CP的IP地址
- exported 指定其他三方APP是否可以访问此CP所封装的数据
public class MyContentProvider extends ContentProvider{
private SQLiteDatabase database;
/**
* 当CP被创建时被回调--APK被安装时,此CP就会被创建出一个实例,保存在Framework层
* 一般此方法中,需要创建数据库的连接对象
* 返回true说明创建成功
*/
@Override
public boolean onCreate() {
/**
* 在ContentProvider中可以通过getContext获取上下文对象
*/
MySqliteOpenHelper helper = new MySqliteOpenHelper(getContext(),
"my_db", null, 1);
database = helper.getReadableDatabase();
Log.d("amanda","onCreate" );
return true;
}
/**
* 当外部APP调用ContentResolver.query方法访问此CP时,
* 此方法会被回调,传入参数就是ContentResolver所传递的参数
* 一般调用SQLiteDatabase查询数据库,并返回Cursor对象
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Log.d("amanda","query" );
Cursor cursor = database.query("person", projection, selection, selectionArgs,
null, null, sortOrder);
return cursor;
}
/**
* 返回Uri的类型
*/
@Override
public String getType(Uri uri) {
Log.d("amanda","getType" );
return null;
}
/**
* 当外部APP调用ContentResolver.insert方法访问此CP时,
* 此方法会被回调,传入参数就是ContentResolver所传递的参数
* 一般调用SQLiteDatabase查询数据库,并返回Cursor对象
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.d("amanda","insert" );
database.insert("person", null, values);
return null;
}
/**
* 当外部APP调用ContentResolver.delete方法访问此CP时,
* 此方法会被回调,传入参数就是ContentResolver所传递的参数
* 一般调用SQLiteDatabase查询数据库,并返回Cursor对象
*
* 通过数据库操作所影响的个数
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.d("amanda","delete" );
int affectNum = database.delete("person", selection, selectionArgs);
return affectNum;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
Log.d("amanda","onCreate" );
database.update("person", values, selection, selectionArgs);
return 0;
}
}
注册Provider
<provider
android:name=".MyContentProvider"
android:authorities="com.amanda.day13_contentproviderapk.MyContentProvider"
android:exported="true">
provider>
源码地址
http://download.csdn.net/download/sinat_35615296/9618249