Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android進程間通信 — AIDL

Android進程間通信 — AIDL

編輯:關於Android編程

一、前言

Android中的RPC參考了JAVA中的RMI(remote methord invocation)方案;Android中的RPC機制是為了實現進程間通信,即一個進程使用另一個進程中的遠程對象,Android用AIDL(android interface defined language,Android接口定義語言)來實現,使用戶可以很方便的定義一套接口,然後通過遠程Service為代理,客戶端在綁定該遠程Service時,獲得遠程對象,然後就可以使用該對象。

二、流程

1. 定義一個.aidl接口文件,ADT則會在gen目錄下,自動生成一個對應的.java文件(此文件為自動生成,不可修改);
2. 自動生成的.java中,有一個抽象的Stub類,因此,創建一個基於Stub的子類,並實現在.aidl中定義的接口;
3. 創建一個Service子類,在onCreate中,創建步驟2中的實例對象,在onBind中,返回該實例對象;
4. 在Activity中,發送一個bindService(it, conn, BIND_AUTO_CREATE),請求綁定遠程Service;
5. 若成功,則在ServiceConnection.onServiceConnected中獲得步驟3中的實例對象;
6. 在AndroidManifest.xml中,注冊遠程Service;

三、例子

按照流程中的步驟,實現該例子:

3.1 定義.aidl文件

[java]
package com.chris.rpc.aidl; 
 
interface ITest { 
    void setCustomerName(String name); 
    String getCustomerName(); 

package com.chris.rpc.aidl;

interface ITest {
 void setCustomerName(String name);
 String getCustomerName();
}很簡單,定義了兩個接口,然後,ADT就會自動在gen目錄下生成ITest.java文件,我們來看看:

[java]
/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\chris\\Android_Dev\\eclipse\\workspace\\RpcAidl\\src\\com\\chris\\rpc\\aidl\\ITest.aidl
 */ 
package com.chris.rpc.aidl; 
public interface ITest extends android.os.IInterface 

/** Local-side IPC implementation stub class. */ 
public static abstract class Stub extends android.os.Binder implements com.chris.rpc.aidl.ITest 

private static final java.lang.String DESCRIPTOR = "com.chris.rpc.aidl.ITest"; 
/** Construct the stub at attach it to the interface. */ 
public Stub() 

this.attachInterface(this, DESCRIPTOR); 

/**
 * Cast an IBinder object into an com.chris.rpc.aidl.ITest interface,
 * generating a proxy if needed.
 */ 
public static com.chris.rpc.aidl.ITest asInterface(android.os.IBinder obj) 

if ((obj==null)) { 
return null; 

android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); 
if (((iin!=null)&&(iin instanceof com.chris.rpc.aidl.ITest))) { 
return ((com.chris.rpc.aidl.ITest)iin); 

return new com.chris.rpc.aidl.ITest.Stub.Proxy(obj); 

@Override 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_setCustomerName: 

data.enforceInterface(DESCRIPTOR); 
java.lang.String _arg0; 
_arg0 = data.readString(); 
this.setCustomerName(_arg0); 
reply.writeNoException(); 
return true; 

case TRANSACTION_getCustomerName: 

data.enforceInterface(DESCRIPTOR); 
java.lang.String _result = this.getCustomerName(); 
reply.writeNoException(); 
reply.writeString(_result); 
return true; 


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

private static class Proxy implements com.chris.rpc.aidl.ITest 

private android.os.IBinder mRemote; 
Proxy(android.os.IBinder remote) 

mRemote = remote; 

@Override public android.os.IBinder asBinder() 

return mRemote; 

public java.lang.String getInterfaceDescriptor() 

return DESCRIPTOR; 

@Override public void setCustomerName(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_setCustomerName, _data, _reply, 0); 
_reply.readException(); 

finally { 
_reply.recycle(); 
_data.recycle(); 


@Override public java.lang.String getCustomerName() 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_getCustomerName, _data, _reply, 0); 
_reply.readException(); 
_result = _reply.readString(); 

finally { 
_reply.recycle(); 
_data.recycle(); 

return _result; 


static final int TRANSACTION_setCustomerName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); 
static final int TRANSACTION_getCustomerName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); 

public void setCustomerName(java.lang.String name) throws android.os.RemoteException; 
public java.lang.String getCustomerName() throws android.os.RemoteException; 

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\chris\\Android_Dev\\eclipse\\workspace\\RpcAidl\\src\\com\\chris\\rpc\\aidl\\ITest.aidl
 */
package com.chris.rpc.aidl;
public interface ITest extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.chris.rpc.aidl.ITest
{
private static final java.lang.String DESCRIPTOR = "com.chris.rpc.aidl.ITest";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.chris.rpc.aidl.ITest interface,
 * generating a proxy if needed.
 */
public static com.chris.rpc.aidl.ITest asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.chris.rpc.aidl.ITest))) {
return ((com.chris.rpc.aidl.ITest)iin);
}
return new com.chris.rpc.aidl.ITest.Stub.Proxy(obj);
}
@Override 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_setCustomerName:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
this.setCustomerName(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getCustomerName:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getCustomerName();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.chris.rpc.aidl.ITest
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void setCustomerName(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_setCustomerName, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public java.lang.String getCustomerName() 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_getCustomerName, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_setCustomerName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getCustomerName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void setCustomerName(java.lang.String name) throws android.os.RemoteException;
public java.lang.String getCustomerName() throws android.os.RemoteException;
}
3.2 創建Stub子類,並實現接口:

[java]
package com.chris.rpc.aidl; 
 
import android.os.RemoteException; 
import android.util.Log; 
 
import com.chris.rpc.aidl.ITest.Stub; 
 
public class MyTest extends Stub { 
 
    private final static String TAG = "ChrisRpcAidl"; 
    private String strName = ""; 
    @Override 
    public void setCustomerName(String name) throws RemoteException { 
        Log.d(TAG, "[MyTest] setCustomerName name = " + name); 
        strName = name; 
    } 
 
    @Override 
    public String getCustomerName() throws RemoteException { 
        Log.d(TAG, "[MyTest] getCustomerName name = " + strName); 
        return strName; 
    } 
 

package com.chris.rpc.aidl;

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

import com.chris.rpc.aidl.ITest.Stub;

public class MyTest extends Stub {

 private final static String TAG = "ChrisRpcAidl";
 private String strName = "";
 @Override
 public void setCustomerName(String name) throws RemoteException {
  Log.d(TAG, "[MyTest] setCustomerName name = " + name);
  strName = name;
 }

 @Override
 public String getCustomerName() throws RemoteException {
  Log.d(TAG, "[MyTest] getCustomerName name = " + strName);
  return strName;
 }

}
3.3 創建遠程Service類:

[java]
package com.chris.rpc.aidl; 
 
import com.chris.rpc.aidl.ITest.Stub; 
 
import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
import android.util.Log; 
 
public class MyService extends Service { 
 
    private final static String TAG = "ChrisRpcAidl"; 
    private Stub mTest = null; 
    @Override 
    public IBinder onBind(Intent arg0) { 
        Log.d(TAG, "onBind ..."); 
        return mTest; 
    } 
    @Override 
    public void onCreate() { 
        Log.d(TAG, "onCreate ..."); 
        mTest = new MyTest(); 
        super.onCreate(); 
    } 
 

package com.chris.rpc.aidl;

import com.chris.rpc.aidl.ITest.Stub;

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

public class MyService extends Service {

 private final static String TAG = "ChrisRpcAidl";
 private Stub mTest = null;
 @Override
 public IBinder onBind(Intent arg0) {
  Log.d(TAG, "onBind ...");
  return mTest;
 }
 @Override
 public void onCreate() {
  Log.d(TAG, "onCreate ...");
  mTest = new MyTest();
  super.onCreate();
 }

}
3.4 在Activity中請求綁定該遠程Service,並獲取實例:

[java]
package com.chris.rpc.aidl; 
 
import android.os.Bundle; 
import android.os.IBinder; 
import android.os.RemoteException; 
import android.util.Log; 
import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Intent; 
import android.content.ServiceConnection; 
 
public class MainActivity extends Activity { 
 
    private final static String TAG = "ChrisRpcAidl"; 
    private final static String SERVICE_ACTION = "com.chris.rpc.aidl.action.MYSERVICE"; 
    private ITest mTest = null; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
         
        Intent it = new Intent(); 
        it.setAction(SERVICE_ACTION); 
        // 發送綁定Service請求,如果成功,則會調用ServiceConnection  
        bindService(it, conn, BIND_AUTO_CREATE); 
    } 
     
    private ServiceConnection conn = new ServiceConnection(){ 
        // 綁定成功,返回的對象是IBinder接口,通過asInterface轉換為定義的ITest接口  
        @Override 
        public void onServiceConnected(ComponentName name, IBinder service) { 
            Log.d(TAG, "onServiceConnected ..."); 
             
            mTest = ITest.Stub.asInterface(service); 
            if(mTest != null){ 
                try { 
                    mTest.setCustomerName("chris"); 
                    Log.d(TAG, "-------------------"); 
                    Log.d(TAG, "get name = " + mTest.getCustomerName()); 
                } catch (RemoteException e) { 
                    e.printStackTrace(); 
                } 
            } 
        } 
 
        @Override 
        public void onServiceDisconnected(ComponentName name) { 
             
        } 
    }; 

package com.chris.rpc.aidl;

import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;

public class MainActivity extends Activity {

 private final static String TAG = "ChrisRpcAidl";
 private final static String SERVICE_ACTION = "com.chris.rpc.aidl.action.MYSERVICE";
 private ITest mTest = null;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  Intent it = new Intent();
  it.setAction(SERVICE_ACTION);
  // 發送綁定Service請求,如果成功,則會調用ServiceConnection
  bindService(it, conn, BIND_AUTO_CREATE);
 }
 
 private ServiceConnection conn = new ServiceConnection(){
  // 綁定成功,返回的對象是IBinder接口,通過asInterface轉換為定義的ITest接口
  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   Log.d(TAG, "onServiceConnected ...");
   
   mTest = ITest.Stub.asInterface(service);
   if(mTest != null){
    try {
     mTest.setCustomerName("chris");
     Log.d(TAG, "-------------------");
     Log.d(TAG, "get name = " + mTest.getCustomerName());
    } catch (RemoteException e) {
     e.printStackTrace();
    }
   }
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   
  }
 };
}
3.5 在AndroidManifest.xml中,注冊遠程Service:

[html]
<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.chris.rpc.aidl" 
    android:versionCode="1" 
    android:versionName="1.0" > 
 
    <uses-sdk 
        android:minSdkVersion="10" 
        android:targetSdkVersion="10" /> 
 
    <application 
        android:allowBackup="true" 
        android:icon="@drawable/ic_launcher" 
        android:label="@string/app_name" 
        android:theme="@style/AppTheme" > 
        <activity 
            android:name="com.chris.rpc.aidl.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="com.chris.rpc.aidl.MyService"> 
            <intent-filter> 
                <action android:name="com.chris.rpc.aidl.action.MYSERVICE" /> 
            </intent-filter> 
        </service> 
    </application> 
 
</manifest> 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.chris.rpc.aidl"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="10" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.chris.rpc.aidl.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="com.chris.rpc.aidl.MyService">
            <intent-filter>
                <action android:name="com.chris.rpc.aidl.action.MYSERVICE" />
            </intent-filter>
        </service>
    </application>

</manifest>3.6 運行截圖:

 

\

四、小結

本篇文章是讓大家了解AIDL的過程,特別是大家需要理解一個自動生成的接口類的中Stub, asInterface, onTransact方法,這些方法在Android Java Framework中有對應的實現,並最終通過native來完成。然後就是大家要了解這個遠程Service的用法就可以了。AIDL通常用在如手機播放器這類應用中,各個activity與service綁定後,可以控制播放器的各個狀態。
(之後要是有空,我會繼續寫androd java framework中關於binder的理解)

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved