您的位置:首页 > 移动开发 > Android开发

Android四大组件——ContentProvider

2016-08-31 20:52 190 查看
ContentProvider作为Android四大组件之一,看起来十分牛逼,但在真正的项目中,其实我们很少用到。除非像在腾讯、阿里这样的大公司里,由于本公司旗下的几个APP之间需要进行一些数据共享,例如微信需要调用QQ的一些数据库,此时就需要使用ContentProvider了。它是Android中专门用于不同应用之间进行数据共享的方式,ContentProvider的底层实现了Binder,但系统已经为我们进行了封装,我们无需关心底层即可轻松实现IPC(Inter-Process Communication跨进程通信)。

不同应用之间的通信,这里我主要讲两点:

第一:android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等),许多社交类APP中都需要导入系统得联系人,此处我们先介绍怎样在APP中导入系统得通讯录。

第二:自定一个ContentProvider,再通过另外一个APP访问其中数据。

源码地址

http://download.csdn.net/download/sinat_35615296/9618249

-

ContentResolver访问通讯录数据库

通讯录中的一个Item中主要有两个重要信息,姓名与电话号码,它们都是储存在手机的data/data/com.android.provider.contacts数据库中,但是姓名与电话号码并不是储存在同一张表中

- 表raw_contacts 储存 编号 _id 姓名display_name

- 表data 储存 编号raw_contact_id 号码data1

两者通过编号连接在一起

以下是代码,主要思路是

先从表raw_contacts取出编号和姓名

再通过编号在表data中取出对应的电话号码

放入一个list集合

通过一LIstView显示出来

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<Map<String, String>> list = new ArrayList<Map<String,String>>();

list = getContacts();

SimpleAdapter adapter = new SimpleAdapter(this, list,
android.R.layout.simple_list_item_2,
new String[]{"name", "num"},
new int[]{android.R.id.text1,android.R.id.text2});
listView.setAdapter(adapter);
}
/**
* 访问raw_contact和data两个表格,分别获取联系人名称和联系人电话号码
* @return 返回联系人名称和电话的集合
*/
private List<Map<String, String>> getContacts() {
List<Map<String, String>> newList = new ArrayList<Map<String,String>>();
//查询raw_contact联系人名称
ContentResolver resolver = getContentResolver();
Uri rawUri = Uri.parse(raw_contacts_string);
//获取raw_contact的Cursor数据
Cursor cursor = resolver.query(rawUri, null, null, null, null);
while(cursor.moveToNext()){
//获取联系人的名字
String name = cursor.getString(cursor.getColumnIndex("display_name"));

String id = cursor.getString(cursor.getColumnIndex("_id"));
Map<String, String> map = new HashMap<String, String>();
//将联系人名称保存到Map中
map.put("name", name);

Uri dataUri = Uri.parse(data_string);
//获取data表格的Cursor数据
Cursor dataCursor = resolver.query(dataUri, null, "raw_contact_id=?",
new String[]{id}, null);
if (dataCursor.moveToNext()) {
String num = dataCursor.getString(dataCursor.getColumnIndex("data1"));
map.put("num", num);
}
newList.add(map);
}
return newList;
}
}


使用ContentProvider的步骤:

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标签注册ContentProvider组件
android:name               指定ContentProvider的类名
android:authorities        指定访问此ContentProvider所需要的IP地址中的Authorities部分
完整的Uri路径,content://Authorities
android:exported           指定其他三方app是否可以访问此ContentProvider,默认true
-->
<provider

android:name=".MyContentProvider"
android:authorities="com.amanda.day13_contentproviderapk.MyContentProvider"
android:exported="true">

</provider>


源码地址

http://download.csdn.net/download/sinat_35615296/9618249
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息