一、问题描述

  如何在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实现跨进程通讯的更多相关文章

  1. Android四大组件应用系列5——使用AIDL实现跨进程调用Service

    一.问题描述 Android应用程序的四大组件中Activity.BroadcastReceiver.ContentProvider.Service都可以进行跨进程.在上一篇我们通过ContentPr ...

  2. Android四大组件应用系列——使用BroadcastReceiver和Service实现倒计时

    一.问题描述 Service组件可以实现在后台执行一些耗时任务,甚至可以在程序退出的情况下,让Service在后台继续保持运行状态.Service分本地服务和远程服务,Local地服务附在主进程上的m ...

  3. Android四大组件应用系列——Activity与Service交互实现APK下载

    Servic与Activity相比它没有界面,主要是在后台执行一些任务,Service有两种启动方法startService()和bindService(),startService方式Service ...

  4. Android四大组件应用系列——实现电话拦截和电话录音

    一.问题描述 使用BordercastReceiver和Service组件实现下述功能: 1.当手机处于来电状态,启动监听服务,对来电进行监听录音. 2.设置电话黑名单,当来电是黑名单电话,则直接挂断 ...

  5. Android四大组件之——Activity的生命周期(图文详解)

        转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai       联系方式:JohnTsai.Work@gmail.com       [Andro ...

  6. Android四大组件之——Activity的开启:StartActivity()和StartActivityForResult()(图文详解)

                如需转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai       联系方式:JohnTsai.Work@gmail.com   ...

  7. 初学android:四大组件之contentprovider

    一.ContentProvider的概念ContentProvider:为存储和获取数据提供统一的接口.可以在不同的应用程序之间共享数据.Android已经为常见的一些数据提供了默认的ContentP ...

  8. Android 四大组件之" ContentProvider "

    前言 ContentProvider作为Android的四大组件之一,是属于需要掌握的基础知识,可能在我们的应用中,对于Activity和Service这两个组件用的很常见,了解的也很多,但是对Con ...

  9. Android四大组件之——ContentProvider(一)

    Android四大组件之--ContentProvider(一) 本人邮箱:JohnTsai.Work@gmail.com,欢迎交流讨论. 欢迎转载,转载请注明网址:http://www.cnblog ...

随机推荐

  1. LeetCode(48):旋转图像

    Medium! 题目描述: 给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转 ...

  2. Laravel 禁用指定 URL POST 请求的 csrf 检查

    由于在 chrome 插件中使用了跨域请求,所以需要禁用掉 laravel 默认的 post csrf 检查. 配置方法: 在 app/Http/Middleware/VerifyCsrfToken. ...

  3. Jmeter NonGUI模式

    一般情况下我们都是在NonGUI模式下运行jmeter.这样做有两个好处 节省系统资源,能够产生更大的负载 可以通过命令行参数对测试场景进行更精细的配置 示例 创建luzhi.jmx脚本 jmeter ...

  4. python 全栈开发,Day135(爬虫系列之第2章-BS和Xpath模块)

    一.BeautifulSoup 1. 简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: ''' Beautiful Soup提供一些简单 ...

  5. PE文件版本那些事儿

    发现文件的版本号很有意思,win7下右键属性显示两个版本号,分别是File Version 和 Product version.但使用vs编辑版本资源里面却有四处版本号,如下: 发现有以下区别,上面为 ...

  6. PHP函数之array_chunk

    有时候需要对数组进行按分页处理,之前的做法是计算出数组大小,按分页计算出偏移量,再从起始偏移量处开始遍历页大小个数据.现在不用这么麻烦了,原来PHP函数里有个现成的函数array_chunk可以配合我 ...

  7. P2376 [USACO09OCT]津贴Allowance

    P2376 [USACO09OCT]津贴Allowance一开始想的是多重背包,但是实践不了.实际是贪心,让多c尽可能少,所以先放大的,最后让小的来弥补. #include<iostream&g ...

  8. 使用boost线程定时器作为后台线程来切换主循环程序状态方法2

    上一篇的方法主要使用的是:通过线程延时实 现的定时,并且只能定时一次,如果需要对此定时处理,就需要使用下面的定时器: #include "stdafx.h" #include &l ...

  9. window10 还原精灵 破解版 冰点

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha=======

  10. AGC015 C-Nuske vs Phantom Thnook AtCoder 思路 前缀和

    目录 题目链接 题解 代码 题目链接 AGC015 C-Nuske vs Phantom Thnook AtCoder 题解 树的性质有: 如果每个蓝色连通块都是树,那么连通块个数=总点数−总边数. ...