理解Android系統的處理序間通訊原理(二)----RPC機制

來源:互聯網
上載者:User

標籤:

理解Android系統中的輕量級解決方案RPC的原理,需要先回顧一下JAVA中的RMI(Remote Method Invocation)這個便於使用的純JAVA方案(用來實現分布式應用)。有關RMI的相關知識,可以通過來歸納:Android中的RPC也是參考了JAVA中的RMI方案,這裡我們再詳細瞭解一下RPC的實現過程。Android中的RPC機制是為了實現一個進程使用另一個進程中的遠程對象,它使用了Android自己的AIDL(介面定義語言),使使用者很方便地定義出一個介面作為規範,通過一個遠程Service為代理 ,用戶端在綁定該遠程Service過程中擷取遠程對象,進而使用該對象。可參考所示:補充:RPC的另一個目的是對用戶端只聲明介面及方法,隱藏掉具體實作類別,供用戶端直接擷取此介面執行個體。執行個體代碼:執行個體一:通過Service來遠程調用一個介面子類的函數方法功能描述:在MainActivity中通過綁定MyService服務類,來遠程調用MyPlayer(實現了IPlayer介面)的方法過程。需要定義一個IPlayer.aidl檔案,ADT工具會自動產生一個IPlayer介面類,然後再由MyPlayer繼承IPlayer介面類中的靜態內部抽象類別,實現介面方法,進而供其它應用程式遠程調用。(在本例中為了方便,MainActivity與MyService類同處一個應用程式中,實現運用時,可以不在同一個應用程式中,只要有許可權訪問MyService服務,就能得到IPlayer介面,進而執行該介面執行個體方法)程式清單:IPlayer.aidl
package com.magc.rpc;

interface IPlayer
{

void setName(String name);
void addFile(String f_name);
String ToString();
}
程式清單:IPlayer.java (ADT根據上面IPlayer.aidl檔案自動產生,不能編輯該檔案)
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\\work\\Android_App\\MyRPCService\\src\\com\\magc\\rpc\\IPlayer.aidl
*/
package com.magc.rpc;
public interface IPlayer extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.magc.rpc.IPlayer
{
private static final java.lang.String DESCRIPTOR = "com.magc.rpc.IPlayer";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.magc.rpc.IPlayer interface,
* generating a proxy if needed.
*/
public static com.magc.rpc.IPlayer asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.magc.rpc.IPlayer))) {
return ((com.magc.rpc.IPlayer)iin);
}
return new com.magc.rpc.IPlayer.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_setName:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
this.setName(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_addFile:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
this.addFile(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_ToString:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.ToString();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.magc.rpc.IPlayer
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public void setName(java.lang.String name) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
mRemote.transact(Stub.TRANSACTION_setName, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public void addFile(java.lang.String f_name) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(f_name);
mRemote.transact(Stub.TRANSACTION_addFile, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public java.lang.String ToString() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_ToString, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_setName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addFile = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_ToString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
public void setName(java.lang.String name) throws android.os.RemoteException;
public void addFile(java.lang.String f_name) throws android.os.RemoteException;
public java.lang.String ToString() throws android.os.RemoteException;
}
 程式清單:MyPlayer.java  (實現IPlayer的靜態內部抽象類別Stub)
package com.magc.rpc;

import android.os.RemoteException;
import android.util.Log;

import com.magc.rpc.IPlayer.Stub;
/**
*
* @author magc
* 實現IPlayer介面類中的靜態內部抽象類別,即實現IPlayer介面方法
* 將來供其它應用程式遠程調用執行方法
*/
public class MyPlayer extends Stub {

private String name="";
@Override
public void addFile(String fName) throws RemoteException {

System.out.println("add file ...");

}

@Override
public void setName(String name) throws RemoteException {

this.name = name;
Log.i("magc", "setName--"+name);
}

public String ToString()
{
String str = "MyPlayer--"+name;
Log.i("magc", "MyPlayer--"+name);
return str;
}

}
 程式清單:MyService.java (一個Service類,供其它程式來遠程綁定,返回IPlayer介面)
package com.magc.rpc;

import com.magc.rpc.IPlayer.Stub;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;


/**
*
* @author magc
* 此服務類作為一個代理角色,供其它應用程式綁定,並返回介面執行個體
*
* 可看作是代理模式的應用
*/
public class MyService extends Service {

private Stub player = new MyPlayer();
@Override
public IBinder onBind(Intent arg0) {
return player;
}

@Override
public void onCreate() {
super.onCreate();
}

}
 程式清單:MainActivity.java (作為用戶端遠程調用IPlayer介面方法)
package com.magc.rpc;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
/**
*
* @author magc
* 作為一個用戶端通過綁定MyService服務,實現遠程調用IPlayer介面方法
*
*/
public class MainActivity extends Activity {
private String ACTION="com.magc.rpc.action.MYSERVICE";
private IPlayer player;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = new Intent();
intent.setAction(ACTION);
//綁定MyService服務
bindService(intent, conn, BIND_AUTO_CREATE);


}
private ServiceConnection conn = new ServiceConnection() {

@Override
public void onServiceDisconnected(ComponentName name) {

}

/**
* 綁定MyService服務後,返回IPlayer介面,進而調用該介面方法
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("magc", "bind service .....");
player = IPlayer.Stub.asInterface(service);
if(player!=null)
{
try {
player.setName("magc");
player.ToString();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
}
 程式清單:AndroidManifest.xml (註冊Activity和Service)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.magc.rpc"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="9" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".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>

<service android:name=".MyService">
<intent-filter>
<action android:name="com.magc.rpc.action.MYSERVICE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
</manifest>
 上面Android應用程式運行後結果如下所示:小結:1、重點理解Android中對AIDL檔案的定義,以及理解ADT工具自動產生的介面類IPlayer,特別是它的靜態內部類Stub以及Stub的asInterface方法, 2、Service作為一個代理角色,在其它應用程式通過Stub類的asInterface方法在綁定到一個服務時才能實現返回該介面執行個體,進而對該執行個體進行相關操作。   

理解Android系統的處理序間通訊原理(二)----RPC機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.