Android四大组件应用系列——使用ContentProvider实现跨进程通讯
| 一、问题描述 |
如何在Android中实现不同应用之间的通讯(既跨进程进行调用)?Android提供了多种实现方式,使我们可以实现跨进程访问Activity、通过ContentProvider跨进程访问其他应用的数据、通过Broadcast可以向android系统中所有应用程序发送广播、使用AIDL实现跨进程的Service。下面我们就使用ContentProvider实现跨进程访问数据,并可对数据进行增、删、改、查
| 二、应用实现 |
使用ContentProvider实现数据共享,主要是共享应用的Sqlite数据库,再一个应用中(本例的shareinfo)提供数据源(Sqlite数据库)并创建ContentProvider组件, ContentProvider组件主要对外(其他应用)提供访问数据的接口(Uri信息),其他应用(本例的other)通过这个接口(Uri信息)实现跨进程的方法调用
如图所示:

本例涉及两个应用shareinfo和other
| 三、shareinfo应用的核心 |
作为数据的提供者首先是开发对外可访问的数据库(Sqlite)
涉及两个组件DbOpenHelper和SQLiteHelper
代码如下:
public class DbOpenHelper extends SQLiteOpenHelper {
public DbOpenHelper(Context context) {
super(context, "jereh.db", null, 4);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table person(personid integer primary key " +
" autoincrement,name varchar(20),phone varchar(12) null)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
db.execSQL("drop table person");
onCreate(db);
}
}
public class SQLiteHelper {
private Context context;
private DbOpenHelper helper = null;
public SQLiteHelper(Context context){
helper = new DbOpenHelper(context);
}
public void save(Person person){//增
SQLiteDatabase db = helper.getWritableDatabase();
db.execSQL("insert into person(name,phone) values(?,?)",new Object[]{person.getName(),person.getPhone()});
db.close();
}
public void delete(int personid){//删
SQLiteDatabase db = helper.getWritableDatabase();
db.execSQL("delete from person where personid=?", new Integer[]{personid});
db.close();
}
public void update(Person person){//改
SQLiteDatabase db = helper.getWritableDatabase();
db.execSQL("update person set name=?,phone=? where personid=?", new Object[]{person.getName(),person.getPhone(),person.getPersonid()});
db.close();
}
public Person find(int personid){//查
SQLiteDatabase db = helper.getReadableDatabase();
//Cursor cursor = db.rawQuery("select * from person where personid=?", new String[]{personid+""});
Cursor cursor=db.rawQuery("select * from person",null);
if(cursor.moveToFirst()){
int id = cursor.getInt(cursor.getColumnIndex("personid"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
return new Person(personid, name, phone);
}
cursor.close();
return null;
}
}
然后编写ContentProvider组件代码如下:
package com.jereh;
public class PersonProvider extends ContentProvider {
private DbOpenHelper openHelper;
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int PERSONS = 1;
private static final int PERSON = 2;
static{
MATCHER.addURI("com.jereh.providers.personprovider", "person", PERSONS);
//* 根据pesonid来删除记录
MATCHER.addURI("com.jereh.providers.personprovider", "person/#", PERSON);
}
@Override
public boolean onCreate() {
openHelper = new DbOpenHelper(this.getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase sqLiteDatabase = openHelper.getReadableDatabase();
switch (MATCHER.match(uri)) {
case 1:
return sqLiteDatabase.query("person", projection, selection, selectionArgs, null, null, sortOrder);
case 2:
long rowid = ContentUris.parseId(uri);
String where = "personid="+rowid;
if(selection != null && "".equals(selection.trim())){
where = selection+"and"+where;
}
return sqLiteDatabase.query("person", projection, where, selectionArgs, null, null, sortOrder);
}
return null;
}
@Override
public String getType(Uri uri) {
switch (MATCHER.match(uri)) {
case 1:
return "vnd.android.cursor.dir/person";
case 2:
return "vnd.android.cursor.item/person";
}
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase sqLiteDatabase = openHelper.getWritableDatabase();
switch (MATCHER.match(uri)) {
case 1:
long rowid = sqLiteDatabase.insert("person", "name", values);
return ContentUris.withAppendedId(uri, rowid);
default:
break;
}
return null;
}
//* 删除特定personid行的记录
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase sqLiteDatabase = openHelper.getWritableDatabase();
switch (MATCHER.match(uri)) {
case 1:
return sqLiteDatabase.delete("person", selection, selectionArgs);
case 2:
long rowid = ContentUris.parseId(uri);
String where = "personid="+rowid;
if(selection != null && "".equals(selection.trim())){
where = selection+"and"+where;
}
return sqLiteDatabase.delete("person", where, selectionArgs);
}
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase sqLiteDatabase = openHelper.getWritableDatabase();
switch (MATCHER.match(uri)) {
case 1:
return sqLiteDatabase.update("person", values, selection, selectionArgs);
case 2:
long rowid = ContentUris.parseId(uri);
String where = "personid="+rowid;
if(selection != null && "".equals(selection.trim())){
where = selection+"and"+where;
}
return sqLiteDatabase.update("person", values, where, selectionArgs);
}
return 0;
}
}
在AndroidManifest.xml中注册provider
<provider android:name="com.jereh.PersonProvider"
android:authorities="com.jereh.providers.personprovider">
shareinfo应用编写完成
| 四、编写other应用 |
接下来编写other应用,在这个应用中访问shareinfo中数据,我们使用Android JUnit进行测试,开发单元测试组件如下:
public class AccessProvider extends AndroidTestCase {
public void testInsert(){
Uri uri = Uri.parse("content://com.jereh.providers.personprovider/person");
ContentResolver resolver = this.getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "xiaoli");
values.put("phone", "333333");
resolver.insert(uri, values);
}
public void testDelete(){
Uri uri = Uri.parse("content://com.jereh.providers.personprovider/person/2");
ContentResolver resolver = this.getContext().getContentResolver();
resolver.delete(uri, null, null);
}
public void testUpdate(){
Uri uri = Uri.parse("content://com.jereh.providers.personprovider/person/3");
ContentResolver resolver = this.getContext().getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "ljb");
values.put("phone", "00000000");
resolver.update(uri, values, null, null);
}
public void testQuery(){
Uri uri = Uri.parse("content://com.jereh.providers.personprovider/person");
ContentResolver resolver = this.getContext().getContentResolver();
Cursor cursor = resolver.query(uri, new String[]{"name","phone"}, null, null, null);
while(cursor.moveToNext()){
String name = cursor.getString(cursor.getColumnIndex("name"));
String phone = cursor.getString(cursor.getColumnIndex("phone"));
System.out.println("name="+name+" "+"phone="+phone);
}
}
}
执行单元测试,测试结果如图所示:

所有方法均通过了测试,实现了在一个应用(other)中访问另一个应用(shareinfo)中的数据
AndroidManifest.xml配置:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.jereh.other.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.jereh" android:label="My Test">
</instrumentation>
出处:http://www.cnblogs.com/jerehedu/
版权声明:本文版权归烟台杰瑞教育科技有限公司和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
技术咨询:

Android四大组件应用系列——使用ContentProvider实现跨进程通讯的更多相关文章
- Android四大组件应用系列5——使用AIDL实现跨进程调用Service
一.问题描述 Android应用程序的四大组件中Activity.BroadcastReceiver.ContentProvider.Service都可以进行跨进程.在上一篇我们通过ContentPr ...
- Android四大组件应用系列——使用BroadcastReceiver和Service实现倒计时
一.问题描述 Service组件可以实现在后台执行一些耗时任务,甚至可以在程序退出的情况下,让Service在后台继续保持运行状态.Service分本地服务和远程服务,Local地服务附在主进程上的m ...
- Android四大组件应用系列——Activity与Service交互实现APK下载
Servic与Activity相比它没有界面,主要是在后台执行一些任务,Service有两种启动方法startService()和bindService(),startService方式Service ...
- Android四大组件应用系列——实现电话拦截和电话录音
一.问题描述 使用BordercastReceiver和Service组件实现下述功能: 1.当手机处于来电状态,启动监听服务,对来电进行监听录音. 2.设置电话黑名单,当来电是黑名单电话,则直接挂断 ...
- Android四大组件之——Activity的生命周期(图文详解)
转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai 联系方式:JohnTsai.Work@gmail.com [Andro ...
- Android四大组件之——Activity的开启:StartActivity()和StartActivityForResult()(图文详解)
如需转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai 联系方式:JohnTsai.Work@gmail.com ...
- 初学android:四大组件之contentprovider
一.ContentProvider的概念ContentProvider:为存储和获取数据提供统一的接口.可以在不同的应用程序之间共享数据.Android已经为常见的一些数据提供了默认的ContentP ...
- Android 四大组件之" ContentProvider "
前言 ContentProvider作为Android的四大组件之一,是属于需要掌握的基础知识,可能在我们的应用中,对于Activity和Service这两个组件用的很常见,了解的也很多,但是对Con ...
- Android四大组件之——ContentProvider(一)
Android四大组件之--ContentProvider(一) 本人邮箱:JohnTsai.Work@gmail.com,欢迎交流讨论. 欢迎转载,转载请注明网址:http://www.cnblog ...
随机推荐
- LeetCode(48):旋转图像
Medium! 题目描述: 给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转 ...
- Laravel 禁用指定 URL POST 请求的 csrf 检查
由于在 chrome 插件中使用了跨域请求,所以需要禁用掉 laravel 默认的 post csrf 检查. 配置方法: 在 app/Http/Middleware/VerifyCsrfToken. ...
- Jmeter NonGUI模式
一般情况下我们都是在NonGUI模式下运行jmeter.这样做有两个好处 节省系统资源,能够产生更大的负载 可以通过命令行参数对测试场景进行更精细的配置 示例 创建luzhi.jmx脚本 jmeter ...
- python 全栈开发,Day135(爬虫系列之第2章-BS和Xpath模块)
一.BeautifulSoup 1. 简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: ''' Beautiful Soup提供一些简单 ...
- PE文件版本那些事儿
发现文件的版本号很有意思,win7下右键属性显示两个版本号,分别是File Version 和 Product version.但使用vs编辑版本资源里面却有四处版本号,如下: 发现有以下区别,上面为 ...
- PHP函数之array_chunk
有时候需要对数组进行按分页处理,之前的做法是计算出数组大小,按分页计算出偏移量,再从起始偏移量处开始遍历页大小个数据.现在不用这么麻烦了,原来PHP函数里有个现成的函数array_chunk可以配合我 ...
- P2376 [USACO09OCT]津贴Allowance
P2376 [USACO09OCT]津贴Allowance一开始想的是多重背包,但是实践不了.实际是贪心,让多c尽可能少,所以先放大的,最后让小的来弥补. #include<iostream&g ...
- 使用boost线程定时器作为后台线程来切换主循环程序状态方法2
上一篇的方法主要使用的是:通过线程延时实 现的定时,并且只能定时一次,如果需要对此定时处理,就需要使用下面的定时器: #include "stdafx.h" #include &l ...
- window10 还原精灵 破解版 冰点
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha=======
- AGC015 C-Nuske vs Phantom Thnook AtCoder 思路 前缀和
目录 题目链接 题解 代码 题目链接 AGC015 C-Nuske vs Phantom Thnook AtCoder 题解 树的性质有: 如果每个蓝色连通块都是树,那么连通块个数=总点数−总边数. ...