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/ 
版权声明:本文版权归烟台杰瑞教育科技有限公司和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

技术咨询:

时间: 2024-10-10 17:13:12

Android四大组件应用系列——使用ContentProvider实现跨进程通讯的相关文章

Android四大组件之内容提供者--ContentProvider

Android四大组件之内容提供者--ContentProvider 1,什么是ContentProvider ContentProvider将应用中的数据对其它应用进行共享, 提供增删改查的方法 ContentProvider统一了数据的访问方式,不必针对不同数据类型采取不同的访问策略 ContentProvider将数据封装,只暴露出我们希望提供给其它程序的数据 ContentProvider中可以注册观察者, 监听数据的变化 2,怎么创建 2.1定义类继承ContentProvider,

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

一.问题描述 Service组件可以实现在后台执行一些耗时任务,甚至可以在程序退出的情况下,让Service在后台继续保持运行状态.Service分本地服务和远程服务,Local地服务附在主进程上的main线程上而不是独立的进程,这样在一定程度上节约了资源:Remote服务占用独立的进程,由于是独立的进程,因此会占用一定的资源但在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性,一些提供系统服务的Service就是这种常驻的远

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

一.问题描述 使用BordercastReceiver和Service组件实现下述功能: 1.当手机处于来电状态,启动监听服务,对来电进行监听录音. 2.设置电话黑名单,当来电是黑名单电话,则直接挂断. 当拨打电话或电话状态发生改变时,系统就会发出有序广播,因此我们可以使用BordercastReceiver接受广播,因BordercastReceiver执行时间短不能执行耗时任务也不能使用子线程,因此我们应启动一个Service来监听电话并进行处理 二.加入AIDL文件 Android没有对外

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

Servic与Activity相比它没有界面,主要是在后台执行一些任务,Service有两种启动方法startService()和bindService(),startService方式Service不可交互,可一直在后台即便应用结束,bindService方式可通过ServiceConnection获得运行的Service实例的方式实现Activity和Service之间的交互,通常Activity退出则绑定的服务也就取消了.我们可以通过同时执行启动服务和绑定服务的方式实现Service交互同

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

            如需转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai       联系方式:[email protected]       [Android四大组件学习系列Activity篇]        1.Android四大组件之——Activity(一)定义.状态和后退栈(图文详解) 2.Android四大组件之——Activity的生命周期(图文详解) 3.Android四大组件之——Activity的开启StartActivit

android四大组件--ContentProvider详解

一.相关ContentProvider概念解析: 1.ContentProvider简介 在Android官方指出的Android的数据存储方式总共有五种,分别是:Shared Preferences.网络存储.文件存储.外储存储.SQLite.但是我们知道一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,例如我们需要操作系统里的媒体库.通讯录等,这时我们就可能通过ContentProvider来满足我们的需求了. 2.为什么要选择Conte

android四大组件--ContentProvider具体解释

一.相关ContentProvider概念解析: 1.ContentProvider简单介绍 在Android官方指出的Android的数据存储方式总共同拥有五种,各自是:Shared Preferences.网络存储.文件存储.外储存储.SQLite.可是我们知道一般这些存储都仅仅是在单独的一个应用程序之中达到一个数据的共享,有时候我们须要操作其它应用程序的一些数据,比如我们须要操作系统里的媒体库.通讯录等,这时我们就可能通过ContentProvider来满足我们的需求了. 2.为什么要选择

Android四大组件——ContentProvider

ContentProvider数据提供者 用与程序与程序之间的数据传递. ContentProvider提供了其他程序调用该程序内部数据的调用方法. /* * 用来定义其他程序调用该程序数据时 * 可以进行的操作. */ public class MyContentProvider extends ContentProvider { @Override//在ContentProvider创建后被调用 public boolean onCreate() { // TODO Auto-generat

深入理解Android四大组件之一ContentProvider

ContentProvider作为Android四大组件之一,平时写自己的ContentProvider比较少,但是用到ContentProvider地方还是有的,比如去获取通讯录信息,这其实就间接的使用到了通讯录程序的ContentProvider组件. 先简单说一下ContentProvider组件.后面重点分析源码了解ContentProvider运行的过程. ContentProvider可以实现在应用程序之间共享数据. Android为常见的一些数据提供了默认的ContentProvi