Android学习(13)-跨程序共享数据

来源:互联网 发布:java jdk 编辑:程序博客网 时间:2024/05/22 17:35

之前说到的持久化技术只能提供本程序使用,是不能分享给其他程序使用的。比如电话簿信息,短信,媒体库等。都得实现跨程序数据分享的功能。这时候就涉及到内容提供器了。

Content Provider主要用于在不同应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另外一个程序中的数据,同时保证被访问数据的安全性。

内容提供器用法有两种:

(1)利用现有的内容提供器获取其它程序里面的数据。

(2)创建自己的内容提供器,供其它程序访问我们的数据。

如果已经会使用SQLite了,那么使用ContentProvider的套路都是一样的,只是某些参数不太一样。


下面通过一个小例子说明,我们想在自己的应用中获取手机联系人信息:


首先,设计布局如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >    <ListView        android:id="@+id/contactslist"        android:layout_width="match_parent"        android:layout_height="wrap_content"        >    </ListView></RelativeLayout>

活动中代码如下:

public class MainActivity extends Activity {private ListView contactList;List<String> list = new ArrayList<String>();ArrayAdapter<String> adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);contactList = (ListView)findViewById(R.id.contactslist);adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,list);contactList.setAdapter(adapter);readContacts();}private void readContacts(){Cursor cursor = null;cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);//第一个参数为路径,系统默认了一些路径//路径格式为:content://com.example.app.provider/table1  协议://一般是包名/数据表名while(cursor.moveToNext()){//获取用户名和 手机号String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));list.add(name+"\n"+number);}if(cursor != null){cursor.close();}}}
获取联系人信息,也需要权限申请:

    <uses-permission android:name="android.permission.READ_CONTACTS"/>

ok!  这样就可以获取到手机联系人信息了。 总结起来就是知道其它程序的数据访问路径,然后调用接口就ok了。


那么既然知道如何获取其它应用的数据了,如何对外暴露自身的数据呢?基于之前的SQLite项目进行修改,希望对外提供数据操作接口。

那么首先需要编写一个ContentProvider:

//对外提供内容共享接口public class MyContentProvider extends ContentProvider {public static final int BOOK_DIR = 0;public static final int BOOK_ITEM = 1;public static final int CATEGORY_DIR = 2;public static final int CATEGORY_ITEM = 3;//这些常量用于定义外人访问数据的类型,是访问整个表还是访问里面的某一条数据public static final String AUTHORITY = "com.example.databasetest.provider";//用于方法getType中,组织资源的MIME编码public static UriMatcher uriMatcher;//用于匹配URI的时候使用,判断别人调用数据的时候选择的是什么内容private MyDatabaseHelper dbHelper;//用于后续的操作数据库static{uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);uriMatcher.addURI(AUTHORITY, "category", BOOK_DIR);uriMatcher.addURI(AUTHORITY, "category/#", BOOK_DIR);} //初始化所有的URI@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {return 0;}@Overridepublic String getType(Uri uri) {//针对uri给出每一个内容的MIME编码switch(uriMatcher.match(uri)){case BOOK_DIR:return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.book";//对于目录型的MIME 格式:vnd + ".android.cursor.dir" + "/vnd" + authority + "数据表名"case BOOK_ITEM:return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.book";//对于涉及到具体数据  其MIME编码也有一定的格式  case CATEGORY_DIR:return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.category";case CATEGORY_ITEM:return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.category";}return null;}@Overridepublic Uri insert(Uri uri, ContentValues values) {//参数:uri  插入数据SQLiteDatabase db = dbHelper.getWritableDatabase();//获取数据库操作对象Uri uriReturn = null;switch (uriMatcher.match(uri)) {case BOOK_ITEM:long newBookId = db.insert("Book", null, values);uriReturn = Uri.parse("content://"+AUTHORITY+"/book/"+newBookId);break;case CATEGORY_ITEM:long categoryId = db.insert("Category", null, values);uriReturn = Uri.parse("content://"+AUTHORITY+"/category/"+categoryId);break;default:break;}//从上面的代码可以看出,其实思路都非常的简单,就是先通过URI判断其他人想要干什么事情,然后通过本地的数据库操作,修改相应的数据。//其实就是该类说自己可以对外提供数据服务,但是到了实际操作时还是依赖于数据库操作类return uriReturn;}@Overridepublic boolean onCreate() {//初始化的时候调用  当被那些ContentResolver访问数据时就执行该函数dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 1);return true;}@Overridepublic Cursor query(Uri uri, String[] columns, String selection, String[] selectionArgs,String sortOrder) {//数据地址   访问列  选择条件  选择数据  排序方式return null;}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {return 0;}}

我既然对外提供服务,那么就要在配置文件中配置信息如下:

<provider android:name="com.example.databasetest.MyContentProvider"            android:authorities="com.example.databasetest.provider"></provider>

在另外的程序中,如何消费这一个数据服务?

addBook = (Button)findViewById(R.id.addBook);addBook.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {Uri uri = Uri.parse("content://com.example.databasetest.provider/book");//明确资源路径  在哪增加数据ContentValues values = new ContentValues();values.put("name", "官路风流");values.put("pages", 200);getContentResolver().insert(uri, values);}});

这样就ok了。




0 0