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/ 
版權聲明:本文版權歸 傑瑞教育 技有限公司和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
技術咨詢:JRedu技術交流
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM