二、IPC機制續(IPC方式)

IPC機制

具體方式有很多,比如可以在Intent中附加Extra來傳遞信息,或者通過共享文件的方式來共享數據,還可以採用Binder方式來跨進程通信,另外,Content Provider天生就是支持跨進程訪問的,因此,我們也可以使用它來進行IPC,另外通過網絡通信也是可以實現數據傳遞的,所以Socket也可以實現IPC。

1.使用Bundle

由於Bundle實現了Parcelable接口,所以它可以方便地在不同進程間傳輸。

除了直接傳遞數據這種典型的使用場景,他還有一種特殊的使用場景,如A進程正在進行計算,計算完成之後需要把結果傳遞給B進程,但是這個結果不支持放入Bundle中,那麼可以這樣考慮,A中,通過Intent啓動B進程的一個Service組件(如IntentService),讓Service進行後臺計算,計算完畢之後,再啓動B進程中真正想要啓動的組件由於Service也在B進程中,所以目標組件就可以直接獲取結果。

        findViewById(R.id. button).setOnClickListener( new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setClass(MainActivity. this, SecondActivity.class);
                User user = new User(0, "jake", true);
                user. book = new Book();
                intent.putExtra( "extra_user", (Serializable) user);
                startActivity( intent);
            }
        });

2.使用文件共享

兩個進程通過讀寫同一個文化夾來交換數據,比如A進程把數據寫進文件,B進程通過讀取這個文件來獲取數據。Linux使得併發讀寫文件可以沒有限制,甚至兩個線程同時對一個文件進行讀寫都是運行的。

希望在ManActivity中的onResume中序列化一個User對象到SDk卡上面的一個文件裏面,在SecondActivity的onResume中去反序列化。

MainActivity:onResume執行下面的方法
      private void persistToFile() {
             new Thread( new Runnable() {
                   @Override
                   public void run() {
                        User user = new User(1, "hello world", false);
                        File dir = new File(MyConstants. CHAPTER_2_PATH);
                         if (! dir.exists()) {
                               dir.mkdirs();
                        }
                        File cachedFile = new File(MyConstants. CACHE_FILE_PATH );
                        ObjectOutputStream objectOutputStream = null;
                         try {
                               objectOutputStream = new ObjectOutputStream(
                                           new FileOutputStream(cachedFile));
                               objectOutputStream.writeObject( user);
                              Log. d(TAG, "persist user:" + user);
                        } catch (IOException e) {
                               e.printStackTrace();
                        } finally {
                              MyUtils. close(objectOutputStream);
                        }
                  }
            }).start();
      }
SecondActivity中取:
    private void recoverFromFile() {
        new Thread(new Runnable() {

            @Override
            public void run() {
                User user = null;
                File cachedFile = new File(MyConstants. CACHE_FILE_PATH);
                if ( cachedFile.exists()) {
                    ObjectInputStream objectInputStream = null;
                    try {
                        objectInputStream = new ObjectInputStream(
                                new FileInputStream( cachedFile));
                        user = (User) objectInputStream.readObject();
                        Log. d(TAG, "recover user:" + user);
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } finally {
                        MyUtils. close(objectInputStream);
                    }
                }
            }
        }).start();
    }

當然這種不支持併發,如果想要併發,需要使用線程同步機制來解決。SharePreferences是個特例,通過鍵值對來存儲數據,底層採用xml來存儲鍵值對,位置在/data/data/packagename/shared_prefs目錄下面,從本質來說SharePreferences也屬於文件的一種,但是由於系統對它的讀寫有一定的緩存策略,即在內存裏面有一份SharePreferences文件的緩存,因此在多進程模式下,系統對他的讀寫變得不可靠,當面對高併發的讀寫訪問就有很大機率丟失數據,因此不建議進程間通信使用SP。

3.使用Messenger

Messenger是一種輕量級的IPC方案,它的底層實現是AIDL。從構造方法可以很明顯的看出AIDL的痕跡。

public Messenger(Handler target) {
     mTarget = target.getIMessenger();
}

public Messenger(IBinder target) {
     mTarget = IMessenger.Stub.asInterface(target);
}

Messenger的使用方法很簡單,它對AIDL做了封裝,使得我們可以更簡單地進行線程間通信,同時由於它一次處理一個請求,因此在服務端我們不用考慮線程同步的問題,這個是因爲服務端不存在併發執行的情況。

步驟:
1.服務端進程,首先我們要創建一個Service來處理客戶端的請求,同時創建一個Handler並通過它來創建一個Messenger對象,在Service的onBind裏面返回這個Messenger對象底層的Binder即可。
2.客戶端進程,首先要綁定服務端的Service,綁定成功之後用服務端返回的IBinder對象創建一個Messenger,通過這個Messenger就可以向服務端發送消息了發送消息類型爲Message對象。

如果要服務端能夠迴應客戶端,就和服務端一樣,需要創建一個Handler並創建一個新的Messenger,並把這個Messenger對象通過Message的replyTo參數傳遞給服務端,服務端通過這個replyTo參數就可以迴應客戶端。

服務端:
public class MessengerService extends Service {
    private static final String TAG = "MessengerService";
    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch ( msg. what) {
            case MyConstants. MSG_FROM_CLIENT:
                Log. i(TAG, "receive msg from Client:" + msg.getData().getString( "msg"));
                Messenger client = msg. replyTo;
                Message relpyMessage = Message. obtain(null, MyConstants.MSG_FROM_SERVICE );
                Bundle bundle = new Bundle();
                bundle.putString( "reply", "嗯,你的消息我已經收到,稍後會回覆你。" );
                relpyMessage.setData( bundle);
                try {
                    client. send(relpyMessage);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            default:
                super.handleMessage( msg);
            }
        }
    }
    private final Messenger mMessenger = new Messenger( new MessengerHandler());
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand( intent, flags, startId);
    }
}
客戶端:
public class MessengerActivity extends Activity {
    private static final String TAG = "MessengerActivity";
    private Messenger mService;
    private Messenger mGetReplyMessenger = new Messenger( new MessengerHandler());
    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch ( msg. what) {
            case MyConstants. MSG_FROM_SERVICE:
                Log. i(TAG, "receive msg from Service:" + msg.getData().getString( "reply"));
                break;
            default:
                super.handleMessage( msg);
            }
        }
    }
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = new Messenger( service);
            Log. d(TAG, "bind service");
            Message msg = Message. obtain(null, MyConstants.MSG_FROM_CLIENT );
            Bundle data = new Bundle();
            data.putString( "msg", "hello, this is client.");
            msg.setData( data);
            msg. replyTo = mGetReplyMessenger;
            try {
                mService.send( msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        public void onServiceDisconnected(ComponentName className) {
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate( savedInstanceState);
        setContentView(R.layout. activity_messenger);
        Intent intent = new Intent( "com.ryg.MessengerService.launch");
        bindService( intent, mConnection, Context. BIND_AUTO_CREATE);
    }
    @Override
    protected void onDestroy() {
        unbindService( mConnection);
        super.onDestroy();
    }
}
Mainfest裏面:
        <activity
            android:name= ".messenger.MessengerActivity"
            android:label= "@string/title_activity_messenger" >
            <intent-filter >
                <action android:name ="android.intent.action.MAIN" />
            </intent-filter >
        </activity >

        <service
            android:name= ".messenger.MessengerService"
            android:process= ":remote" >
            <intent-filter >
                <action android:name ="com.ryg.MessengerService.launch" />
            </intent-filter >
        </service >

注意:
通過Messenger來傳遞Message,Message中能用的載體只有what,arg1,arg2,Bundle以及replyTo。Message中的另外一個字段object在同一個進程中是很實用的,但是在跨進程間通信的時候,在Android2.2以前object字段不支持跨進程傳輸,
即使2.2以後,也僅僅是系統提供的實現了Parcelable接口的對象才能通過它來傳輸。這就意味着我們自定義的Parcelable對象是無法通過object字段來傳輸的。

Messenger的工作原理圖:
Messenger的工作原理

4.使用AIDL

由於Messenger的主要作用還是傳遞消息,有時候可能需要跨進程調用服務端的方法,那麼Messenger就不行了。
使用AIDL進行跨進程通信也分爲客戶端和服務端兩個方面:
(1)服務端
服務端首先要創建一個Service用來監聽客戶端的連接請求,然後創建一個AIDL文件,將暴露給客戶端的接口咋這個AIDL文件中聲明,最後在Service中實現這個AIDL接口即可。

(2)客戶端
首先綁定服務端的Service,綁定成功之後,將服務端返回的Binder對象轉換成AIDL接口所屬的類型,接着就可以調用AIDL中的方法了。

(3)AIDL接口的創建

package com.ryg.chapter_2.aidl;
import com.ryg.chapter_2.aidl.Book;
interface IBookManager {
     List<Book> getBookList();
     void addBook(in Book book);
}

AIDL文件支持的數據類型:
1)基本數據類型(int,long,char,boolean,double等)
2)String和CharSquence
3)List,只支持ArrayList,裏面的每個元素都要必須能被AIDL支持
4)Map,只支持HashMap,裏面的每個元素都必須被AIDL支持,
包括Key和Value
5)Parcelable,所有實現了Parcelable接口的對象
6)AIDL,所有的AIDL接口本身也可以在AIDL文件中使用
以上的6種數據類型就是AIDL所支持的所有類型,其中自定義的Parcelable對象和AIDL對象必須要顯式import進來,不管是否和當前的AIDL文件位於同一個包裏面。
另外,如果AIDL文件裏面用到了自定義的Parcelable對象,那麼必須新建一個和它同名的AIDL文件,並在裏面聲明它爲Parcelable類型。
在IBookManager.aidl文件中使用到了自定義的Book對象,所以必須創建Book.aidl在裏面添加:

package com.ryg.chapter_2.aidl;
parcelable Book;

AIDL中每個實現了Parcelable接口的類型的類,都需要像上面那樣去聲明,創建對應的AIDL文件,並聲明那個類爲parcelable。除此之外,AIDL中除了基本數據類型,其他類型的參數必須標上方向,in,out或者inout,in表示輸入型參數,out表示輸出型參數,inout表示輸入輸出型參數。AIDL接口中只支持方法,不支持靜態常量。

in,out,inout區別:
http://hold-on.iteye.com/blog/2026138
inout區別

inout區別

爲了方便開發,建議把所有的和AIDL相關的類和文件全部放入同一個包中,這樣的好處是,當客戶端是另外的應用時,我們可以直接把整個包複製放入到客戶端工程中。
AIDL包結構,在客戶端和服務端要一致,否則會運行出錯,這是因爲客戶端需要反序列化服務端中和AIDL接口相關的所有類。

(4)遠程服務端的Service實現

public class BookManagerService extends Service {
    private static final String TAG = "BMS";
    private CopyOnWriteArrayList<Book> mBookList = 
    new CopyOnWriteArrayList<Book>();
    private Binder mBinder = new IBookManager.Stub() {
        @Override
        public List<Book> getBookList() throws RemoteException {
            return mBookList;
        }
        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add( book);
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        mBookList.add(new Book(1, "Android"));
        mBookList.add(new Book(2, "Ios"));
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

}
        <service
            android:name= ".aidl.BookManagerService"
            android:process= ":remote" >
        </service >

採用CopyOnWriteArrayList,它支持併發讀寫,AIDL方法是在服務端的Binder線程池中執行的,因此當多個客戶端同時連接的時候,會存在多個線程同時訪問的問題,所以要在AIDL方法中處理線程同步,這裏使用它來進行自動的線程同步。

服務端可以使用CopyOnWriteArrayList和ConcurrentHashMap來進行自動線程同步,客戶端拿到的依然是ArrayList和HashMap。

(5)客戶端的實現
客戶端首先綁定遠程服務,綁定成功之後將服務端返回的Binder對象轉換成爲AIDL接口,然後就可以通過這個接口去調用服務端的遠程方法了。

public class BookManagerActivity extends Activity {
    private static final String TAG = "BookManagerActivity";
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            IBookManager bookManager = IBookManager.Stub.asInterface(service);
            try {
                List<Book> list = bookManager.getBookList();
                Log. i(TAG, "query book list, list type:"
                        + list.getClass().getCanonicalName());
                Log. i(TAG, "query book list:" + list.toString());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        public void onServiceDisconnected(ComponentName className) {
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate( savedInstanceState);
        setContentView(R.layout. activity_book_manager);      
        Intent intent = new Intent( this, BookManagerService. class);
        bindService( intent, mConnection, Context. BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        unbindService( mConnection);
        super.onDestroy();
    }

}

(6)監聽
比如現在想服務端有新書的時候通知客戶端,那麼必須要監聽了需要使用RemoteCallbackList,存儲我們自定義的監聽器,它是一個泛型,支持管理任意的AIDL接口。它的內部是Map結構,key是IBinder類型,value是Callback類型。

注意:
服務端和客戶端之間做監聽器,服務端需要使用RemoteCallbackList,否則客戶端的監聽器無法收到通知(因爲服務端實質還是一份新的序列化後的監聽器實例,並不是客戶端那份)

RemoteCallbackList的beginBroadcast和finishBroadcast必須配對使用,哪怕我們僅僅需要獲取RemoteCallbackList中的元素個數。

(7)不要在客戶端的ui線程裏面調用服務端的耗時方法
客戶端調用遠程服務方法時,因爲遠程方法運行在服務端的binder線程池中(服務端方法可以執行大量耗時操作,不需要開線程執行異步任務的);
同時客戶端線程會被掛起,所以如果該方法過於耗時,而客戶端又是UI線程,會導致ANR,所以當確認該遠程方法是耗時操作時,應避免客戶端在UI線程中調用該方法。
同理,當服務器調用客戶端的listener方法時,該方法也運行在客戶端的binder線程池中,所以如果該方法也是耗時操作,請確認運行在服務端的非UI線程中。
另外,因爲客戶端的回調listener運行在binder線程池中,所以更新UI需要用到handler。

(8)服務端進程意外終止
客戶端通過IBinder.DeathRecipient來監聽Binder死亡,也可以在onServiceDisconnected中監聽並重連服務端。區別在於前者是在binder線程池中,訪問UI需要用Handler,後者則是UI線程。

(9)權限驗證
可通過自定義權限在onBind或者onTransact中進行權限驗證。

onBind中驗證,驗證不通過返回null,驗證方式可以使用permission驗證,首先在manifest裏面註冊。

<permission
        android:name= "com.ryg.chapter_2.permission.ACCESS_BOOK_SERVICE"
        android:protectionLevel= "normal" />

就可以在onBind裏面驗證了。

      @Override
      public IBinder onBind(Intent intent) {
             int check = checkCallingOrSelfPermission("com.ryg.chapter_2.permission.ACCESS_BOOK_SERVICE" );
            Log. d(TAG, "onbind check=" + check);
             if ( check == PackageManager. PERMISSION_DENIED) {
                   return null;
            }
             return mBinder;
      }

一個應用來綁定我們的服務的時候,會驗證這個應用的權限,沒有權限就返回null。這個方法同樣適用於Messenger中。

我們自己內部的應用想要綁定我們的服務,只需要在Manifest採用如下方式使用permission即可。

<uses-permission android:name="com.ryg.chapter_2.permission.ACCESS_BOOK_SERVICE" />

服務端的onTransact方法中進行權限驗證,驗證失敗就會返回false,服務端的方法就不會執行,驗證方式可以採用permission驗證,也可以使用Uid和Pid來驗證。通過getCallingUid和getCallingPid可以拿到客戶端所屬的應用的Uid和Pid,通過這兩個參數可以做一些驗證工作,比如驗證包名。

下面即驗證了權限又需要包名以com.rgy開始。

             public boolean onTransact( int code, Parcel data, Parcel reply, int flags)
                         throws RemoteException {
                   int check = checkCallingOrSelfPermission( "com.ryg.chapter_2.permission.ACCESS_BOOK_SERVICE" );
                  Log. d(TAG, "check=" + check);
                   if ( check == PackageManager. PERMISSION_DENIED) {
                         return false;
                  }

                  String packageName = null;
                  String[] packages = getPackageManager().getPackagesForUid(
                               getCallingUid());
                   if ( packages != null && packages. length > 0) {
                         packageName = packages[0];
                  }
                  Log. d(TAG, "onTransact: " + packageName);
                   if (! packageName.startsWith( "com.ryg")) {
                         return false;
                  }

                   return super.onTransact( code, data, reply, flags);
            }

5.使用ContentProvider

底層實現是AIDL,使用比AIDL簡單許多。自定義ContentProvider需要繼承ContentProvider並實現裏面的方法即可,onCreate,query,update,insert,delete,getType,getType用來返回Uri請求所對應的MimeType。如果應用不關係這個,只需要返回null或者”/“,根據Binder,我們知道這6個方法均運行在ContentProvider的進程裏面,除了onCreate方法由系統回調並運行在主線程裏面,其餘的5個均由外界調用並運行在Binder線程池中。

雖然ContentProvider的底層數據看起來很像一個SQLite數據庫,但是它對底層的數據的存儲方式沒有任何要求,我們即可以使用SQLite,也可以使用普通文件,甚至可以採用內存中的一個對象來進行數據的存儲。

註冊android:authorities是它的唯一標識,建議命名的時候加上包名前綴,如果聲明瞭權限,那麼外界應用也需要相應的權限。

ContentProvider(有的手機上會出現不加uses-permission依然可以訪問BookProvider的問題)

6.使用Socket
Socket 一般用於網絡通信,AIDL用這種方式會過於繁瑣,不建議。

7.Binder連接池
比如100個地方需要用到AIDL那麼不可能創建100個Service,需要減少Service的數量,將AIDL放在同一個Service裏面去管理。

Binder連接池的作用就是將每個業務模塊的Binder請求統一轉發到遠程的Service中去。

Binder連接池

Binder連接池,通過BinderPool的方式將Binder的控制與Service本身解耦,同時只需要維護一份Service即可。這裏用到了CountDownLatch,大概解釋下用意:線程在await後等待,直到CountDownLatch的計數爲0,BinderPool裏使用它的目的是爲了保證Activity獲取BinderPool的時候Service已確定bind完成~

例子:
兩個AIDL:

ISecurityCenter.aidl
package com.ryg.chapter_2.binderpool;
interface ISecurityCenter {
    String encrypt(String content);
    String decrypt(String password);
}
ICompute.aidl
package com.ryg.chapter_2.binderpool;
interface ICompute {
    int add( int a, int b);
}

實現:

public class SecurityCenterImpl extends ISecurityCenter.Stub {
    private static final char SECRET_CODE = '^';
    @Override
    public String encrypt(String content) throws RemoteException {
        char[] chars = content.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            chars[ i] ^= SECRET_CODE;
        }
        return new String(chars);
    }

    @Override
    public String decrypt (String password ) throws RemoteException {
        return encrypt( password);
    }

}

以及:

public class ComputeImpl extends ICompute.Stub {
    @Override
    public int add(int a, int b) throws RemoteException {
        return a + b;
    }
}

爲Binder連接池創建AIDL接口IBinderPool.aidl

interface IBinderPool {
    /**
     * @param binderCode, the unique token of specific Binder<br/>
     * @return specific Binder who's token is binderCode.
     */
    IBinder queryBinder( int binderCode);
}

爲Binder連接池創建遠程Service並實現IBinderPool,
下面是queryBinder的實現:

        @Override
        public IBinder queryBinder( int binderCode) throws RemoteException {
            IBinder binder = null;
            switch ( binderCode) {
            case BINDER_SECURITY_CENTER: {
                binder = new SecurityCenterImpl();
                break;
            }
            case BINDER_COMPUTE: {
                binder = new ComputeImpl();
                break;
            }
            default:
                break;
            }
            return binder;
        }

遠程Service的實現比較簡單了:

public class BinderPoolService extends Service {
    private static final String TAG = "BinderPoolService";
    private Binder mBinderPool = new BinderPool.BinderPoolImpl();
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Override
    public IBinder onBind(Intent intent ) {
        Log.d(TAG, "onBind");
        return mBinderPool;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

下面還有Binder連接池的具體實現,首先綁定遠程服務,成功之後,客戶端就可以通過它的queryBinder方法獲取各自對應的Binder,拿到所需要的Binder之後,不同的業務模塊之間就可以進行各自的操作了。

public class BinderPool {
    private static final String TAG = "BinderPool";
    public static final int BINDER_NONE = -1;
    public static final int BINDER_COMPUTE = 0;
    public static final int BINDER_SECURITY_CENTER = 1;

    private Context mContext;
    private IBinderPool mBinderPool;
    private static volatile BinderPool sInstance;
    private CountDownLatch mConnectBinderPoolCountDownLatch;

    private BinderPool(Context context) {
        mContext = context.getApplicationContext();
        connectBinderPoolService();
    }

    public static BinderPool getInsance(Context context) {
        if (sInstance == null) {
            synchronized (BinderPool.class) {
                if (sInstance == null) {
                    sInstance = new BinderPool(context);
                }
            }
        }
        return sInstance;
    }

    private synchronized void connectBinderPoolService() {
        mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
        Intent service = new Intent(mContext, BinderPoolService.class);
        mContext.bindService(service, mBinderPoolConnection,
                Context.BIND_AUTO_CREATE);
        try {
            mConnectBinderPoolCountDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * query binder by binderCode from binder pool
     * 
     * @param binderCode
     *            the unique token of binder
     * @return binder who's token is binderCode<br>
     *         return null when not found or BinderPoolService died.
     */
    public IBinder queryBinder(int binderCode) {
        IBinder binder = null;
        try {
            if (mBinderPool != null) {
                binder = mBinderPool.queryBinder(binderCode);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return binder;
    }

    private ServiceConnection mBinderPoolConnection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // ignored.
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinderPool = IBinderPool.Stub.asInterface(service);
            try {
                mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            mConnectBinderPoolCountDownLatch.countDown();
        }
    };

    private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            Log.w(TAG, "binder died.");
            mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
            mBinderPool = null;
            connectBinderPoolService();
        }
    };

    public static class BinderPoolImpl extends IBinderPool.Stub {

        public BinderPoolImpl() {
            super();
        }

        @Override
        public IBinder queryBinder(int binderCode) throws RemoteException {
            IBinder binder = null;
            switch (binderCode) {
            case BINDER_SECURITY_CENTER: {
                binder = new SecurityCenterImpl();
                break;
            }
            case BINDER_COMPUTE: {
                binder = new ComputeImpl();
                break;
            }
            default:
                break;
            }

            return binder;
        }
    }

}

使用:

public class BinderPoolActivity extends Activity {
    private static final String TAG = "BinderPoolActivity";
    private ISecurityCenter mSecurityCenter;
    private ICompute mCompute;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate( savedInstanceState);
        setContentView(R.layout. activity_binder_pool);
        new Thread(new Runnable() {
            @Override
            public void run() {
                doWork();
            }
        }).start();
    }
    private void doWork() {
        BinderPool binderPool = BinderPool.getInsance(BinderPoolActivity. this);
        IBinder securityBinder = binderPool
                .queryBinder(BinderPool. BINDER_SECURITY_CENTER);
        mSecurityCenter = (ISecurityCenter) SecurityCenterImpl
                . asInterface(securityBinder);
        Log.d(TAG, "visit ISecurityCenter");
        String msg = "helloworld-安卓";
        System. out.println( "content:" + msg);
        try {
            String password = mSecurityCenter.encrypt( msg);
            System. out.println( "encrypt:" + password);
            System. out.println( "decrypt:" + mSecurityCenter.decrypt(password ));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        Log.d(TAG, "visit ICompute");
        IBinder computeBinder = binderPool
                .queryBinder(BinderPool. BINDER_COMPUTE);        
        mCompute = ComputeImpl.asInterface(computeBinder );
        try {
            System. out.println( "3+5=" + mCompute.add(3, 5));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

8.選擇適合的IPC方式

選擇方式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章