標籤:android
Android實現IPC可使用Android本身提供的AIDL機制。網上也有很多相關文章,但寫的過於繁瑣和麻煩,重點也不突出。本文抽絲剝繭從工程角度給出一個最簡單的Android AIDL常式關鍵代碼,以最簡單的形式說明如何在代碼中使用Android AIDL。
AIDL首先在邏輯上可分為“服務端”和“用戶端”。在本樣本中,則以兩個完全不同、互相獨立的Eclipse 項目代表。
(1)server。一個Android App,即AIDL的服務端服務提供者。
(2)clinet。另外一個Android App,即AIDL的服務調用方。
實現的示範代碼功能很簡單:
(1)服務端首先啟動,啟動之後,什麼都不做。當客戶進程串連過來,返回“Hello , World !”字串。
(2)客戶串連服務端。獲得服務端返回的字串,然後在LogCat中列印出來。
代碼架構和具體步驟:
(第1步)Eclipse中建立一個服務端app。假設名字就是server。首先在服務端建立一個名為 ServerServiceInterface.aidl的原始碼放在原始碼包中。雖然ServerServiceInterface.aidl中介面定義遵循java規範,但唯一不同的是不要在裡面添加public, private等等諸如此類的修飾符。在ServerServiceInterface.aidl中定義一個getHelloWorld()的方法,注意:此方法就是隨後服務端暴露給用戶端,且將要提供給用戶端使用的介面,如:
如果ServerServiceInterface.aidl原始碼檔案中沒有寫錯誤,那麼Eclipse會自動在gen目錄下產生一個名字完全一致、相對應的ServerServiceInterface.java檔案。不需要關心ServerServiceInterface.java原始碼檔案中的具體內容。
(第2步)自己寫一個類ServerService.java,繼承自Service,在ServerService.java類內部再寫一個ServerServiceInstance.java類繼承自ServerServiceInterface.java中的Stub類,在此類中實現getHelloWorld()方法。
給出ServerService.java的全部原始碼如下:
package zhangphil.aidl.server;import android.app.Service;import android.content.Intent;import android.os.IBinder;public class ServerService extends Service {public class ServerServiceInstance extends ServerServiceInterface.Stub {//此方法供用戶端調用,返回用戶端一個 Hello , World ! 字串。@Overridepublic String getHelloWorld() {return "Hello , World !";}}@Overridepublic IBinder onBind(Intent intent) {//必須返回一個ServerServiceInstance執行個體、對象,供用戶端使用ServerServiceInstance mServerServiceInstance = new ServerServiceInstance();return mServerServiceInstance;}}
(第3步)寫一個服務端的主Activity。本例為使代碼簡單,主Activity中不做任何過多與AIDL無關的代碼,MainActivity僅作一個啟動App的“容器”而已:
package zhangphil.aidl.server;import android.app.Activity;public class MainActivity extends Activity {//為了使Demo代碼簡潔短小不繁冗,索性把主Activity都注釋掉。//@Override//protected void onCreate(Bundle savedInstanceState) {//super.onCreate(savedInstanceState);//}}
相對應的AndroidManifest.xml檔案:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="zhangphil.aidl.server" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="zhangphil.aidl.server.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="zhangphil.aidl.server.ServerService" > <intent-filter> <!-- action android:name的具體值可以任意給定,但必須保證用戶端調用時和此處定義的一致。 通常使用形如 ACTION_AIDL_SERVER_SERVICE或者com.xxx.xxx等等這種樣式。 --> <action android:name="start_zhangphil_aidl_server_service_action" /> </intent-filter> </service> </application></manifest>
服務端AndroidManifest.xml沒什麼特別的地方,唯一的重點是需要在此檔案中寫明在‘ 第(2)步 ’中的寫的service:
<service android:name="zhangphil.aidl.server.ServerService" > <intent-filter> <!-- action android:name的具體值可以任意給定,但必須保證用戶端調用時和此處定義的一致。 通常使用形如 ACTION_AIDL_SERVER_SERVICE或者com.xxx.xxx等等這種樣式。 --> <action android:name="start_zhangphil_aidl_server_service_action" /> </intent-filter> </service>
以上是服務端。
下面是用戶端。
(第4步)Eclipse中再建立一個名字為client的用戶端app。把上面服務端server項目工程中gen目錄下自動產生的ServerServiceInterface.java原始碼檔案原封不動、保持原貌(包括包結構)複製、粘貼到用戶端src目錄下:
(第5步)到這裡基本上大功告成。接下來只需要在用戶端中bind到服務端的service,然後調用getHelloWorld()方法即可,這裡面要用到Android的ServiceConnection。簡單期間,就在用戶端的MainActivity中bindService,把ServiceConnection中的關鍵方法重寫,用戶端MainActivity代碼:
package zhangphil.aidl.client;import zhangphil.aidl.server.ServerServiceInterface;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;public class MainActivity extends Activity {privateServerServiceInterface mServerServiceInterface;private ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mServerServiceInterface = ServerServiceInterface.Stub.asInterface(service);try {String hi=mServerServiceInterface.getHelloWorld();Log.d(this.getClass().getName(),hi);} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//構造Intent的值必須和所調用的服務端定義的值相同。//本例中就是Server端AndroidManifest.xml中定義service時的那個action namebindService(new Intent("start_zhangphil_aidl_server_service_action"), serviceConnection, Context.BIND_AUTO_CREATE); }}
在第5步中關鍵點有兩個:
(1)構造ServiceConnection,在ServiceConnection中Override onServiceConnected()方法。如果用戶端串連服務端進程成功,那麼onServiceConnected()將被回調。
(2)調用bindService()發起串連到服務進程端。
以上完成後,首先啟動server,然後再啟動client,client端的LogCat輸出:
一個最簡單的Android IPC AIDL之hello world完成!
Android處理序間通訊(IPC)的AIDL機制:Hello World樣本