你的位置:首页 > 操作系统

[操作系统]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.

 <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.

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