1. 程式人生 > >Android筆記三十四.Service綜合例項二

Android筆記三十四.Service綜合例項二

綜合例項2:客戶端訪問遠端Service服務 實現:通過一個按鈕來獲取遠端Service的狀態,並顯示在兩個文字框中。 思路:假設A應用需要與B應用進行通訊,呼叫B應用中的getName()、getAuthor()方法,B應用以Service方式向A應用提供服務。所以,我們可以將A應用看成是客戶端,B應用為服務端,分別命名為AILDClient、AILDServer.
一、服務端應用程式 1.src/com.example.aildserver/song.aidlAILD檔案     當完成aidl檔案建立後,選擇儲存,eclipse會自動在專案的gen目錄中同步生成Song.java介面檔案。介面檔案中生成一個Stub抽象類,裡面包括aidl定義的方法,還包括一些其它
輔助性的方法,如geName()、getSong()方法,我們可以通過這兩個方法實現客戶端讀寫Service服務端資料
  1.     package com.example.aildserver;  
  2.     interface Song  
  3.     {  
  4.          String getName();  
  5.          String getSong();  
  6.     } 
位置如下:
    編寫Aidl檔案時,需要注意:           1.介面名和aidl檔名相同;         2.介面和方法前不用加訪問許可權修飾符public,private等,也不能用final,static;    
    3.Aidl預設支援的型別包話java基本型別(int、long、boolean等)和(String、List、Map、CharSequence),使用這些型別時不需要import宣告。對於List和Map中的元素型別必須是Aidl支援的型別。如果使用自定義型別作為引數或返回值,自定義型別必須實現Parcelable介面。         4.自定義型別和AIDL生成的其它介面型別在aidl描述檔案中,應該顯式import,即便在該類和定義的包在同一個包中。                 5.在aidl檔案中所有非Java基本型別引數必須加上in、out、inout標記,以指明引數是輸入引數、輸出引數還是輸入輸出引數。   
     6.Java原始型別預設的標記為in,不能為其它標記。  2.src/com.example.aildserver/MyService.java 功能:Service子類,完成Service服務 開發核心步驟:     (1)重寫Service的onBind()方法(用於返回一個IBinder物件)、onCreate()方法、onDestroy() 方法、onUnbind()方法;     (2)定義一個Stub的子類,該內部類實現了IBinder、Song兩個介面,該子類物件將作為遠端Service的onBind()方法返回IBinder物件的代理傳給客戶端的ServiceConnection的onServiceConnected方法的第二個引數。
  1. package com.example.aildserver;  
  2. import com.example.aildserver.Song.Stub;  
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.Binder;  
  6. import android.os.IBinder;  
  7. import android.os.RemoteException;  
  8. public class MyService extends Service {  
  9.  private String[] names = new String[] {"林俊杰","蔡依林","鄧紫棋"};  
  10.  private String[] songs = new String[] {"可惜沒如果","第三人稱","多遠都要在一起"};  
  11.  private String name,song;  
  12.  private int current=1;  //當前位置  
  13.  private MyBinder binder = new MyBinder();  //例項化一個IBinder物件  
  14.  /*0.Stub內部類 
  15.   * 該內部類實現了IBinder、Song兩個介面,這個Stub類將會作為遠端Service的回撥類。*/  
  16.  public class MyBinder extends Stub  
  17.  {  
  18.   //a.客戶端回撥該方法獲取歌手名  
  19.   public String getName() throws RemoteException  
  20.   {  
  21.    return name;  
  22.   }  
  23.   //b.客戶端回撥該方法獲取歌曲  
  24.   public String getSong() throws RemoteException  
  25.   {  
  26.    return song;  
  27.   }  
  28.  }  
  29.  /*1.onBind方法 
  30.   * service用於返回一個IBinder物件給客戶端方便通訊 
  31.  */  
  32.  @Override  
  33.  public IBinder onBind(Intent arg0) {  
  34.   return binder;  
  35.  }  
  36.  /*2.onCreate方法 
  37.   * 當Service啟動後,自動呼叫該方法,用於初始化 
  38.   * */  
  39.  public void onCreate() {  
  40.   name = names[current];     //給name、song賦值  
  41.   song = songs[current];  
  42.   System.out.println("Service print:name="+name+"song="+song);  
  43.   super.onCreate();  
  44.  }  
  45.  /*3.onDestroy方法 
  46.   * 當訪問者呼叫Context.stopService方法後,呼叫該方法關閉Service服務 
  47.   * */  
  48.  public void onDestroy() {  
  49.   super.onDestroy();  
  50.  }  
  51.  /*4.onUnbind方法 
  52.   * 當訪問者調呼叫Context.unBind()方法後,呼叫該方法與Service解除繫結*/  
  53.  public boolean onUnbind(Intent intent) {  
  54.   return false;  
  55.  }  
注意1:客戶端訪問Service時,Android並不是直接返回Service物件給客戶端,Service只是將一個回撥物件(IBinder物件)通過onBind()方法回撥給客戶端。   注意2:與繫結本地Service不同的是,本地Service的onBind()方法會直接把IBinder物件本身傳給客戶端的ServiceConnection的onServiceConnected方法的第二個引數。但遠端Service的onBind()方法只是將IBinder物件的代理傳給客戶端的ServiceConnection的onServiceConnected方法的第二個引數。當客戶端獲取了遠端的Service的IBinder物件的代理之後,接下來可通過該IBinder物件去回撥遠端Service的屬性或方法。 3.AndroidManifest.xml 功能:配置Service元件,並指定其action屬性(方便其他應用程式啟動該Service服務)
  1.     <application  
  2.         ........  
  3.         <!-- 配置service -->  
  4.         <service android:name=".MyService">  
  5.             <intent-filter>  
  6.                     <action android:name="com.jiangdongguo.service"/>  
  7.             </intent-filter>  
  8.         </service>  
  9.     </application> 
二、客戶端應用程式
1.拷貝服務端.aidl檔案到客戶端     把AIDLService應用中aidl檔案所在package連同aidl檔案一起拷貝到客戶端AIDLClient應用,eclipse會自動在A應用的gen目錄中為aidl檔案同步生成Song.java介面檔案,接下來就可以在AIDLClient應用中實現與AIDLService應用通訊。 2.src/com.example.aildclient/MainActivity.java 功能:(1)啟動服務端Service服務;(2)獲取返回的IBinder代理物件,並完成與服務端程式的通訊
  1. package com.example.aildclient;  
  2. import com.example.aildserver.Song;  
  3. import android.app.Activity;  
  4. import android.app.Service;  
  5. import android.content.ComponentName;  
  6. import android.content.Intent;  
  7. import android.content.ServiceConnection;  
  8. import android.os.Bundle;  
  9. import android.os.IBinder;  
  10. import android.os.RemoteException;  
  11. import android.view.View;  
  12. import android.view.View.OnClickListener;  
  13. import android.widget.Button;  
  14. import android.widget.EditText;  
  15. public class MainActivity extends Activity {  
  16.     private Button getBtn;  
  17.     private EditText song;  
  18.     private EditText name;  
  19.     private Song binder;  
  20.     //1.建立一個ServiceConnection物件  
  21.     private ServiceConnection conn = new  ServiceConnection()  
  22.     {  
  23.   public void onServiceConnected(ComponentName name, IBinder service)  
  24.   {  
  25.    binder = Song.Stub.asInterface(service); //獲取Service返回的代理IBinder物件  
  26.   }  
  27.   public void onServiceDisconnected(ComponentName name) {  
  28.   }  
  29.     };  
  30.  protected void onCreate(Bundle savedInstanceState) {  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.main);  
  33.         getBtn=(Button)findViewById(R.id.get);  
  34.         song=(EditText)findViewById(R.id.song);  
  35.         name=(EditText)findViewById(R.id.name);  
  36.     //2.指定要啟動的Service  
  37.         Intent intent = new Intent("com.jiangdongguo.service");  
  38.         bindService(intent, conn, Service.BIND_AUTO_CREATE);  
  39.         getBtn.setOnClickListener(new OnClickListener(){  
  40.    public void onClick(View arg0)  
  41.    {  
  42.     try {  
  43.      name.setText(binder.getName());  
  44.      song.setText(binder.getSong());  
  45.     } catch (RemoteException e) {  
  46.      e.printStackTrace();  
  47.     }  
  48.    }  
  49.         });  
  50.     }  
  51. }
    對於遠端服務呼叫,遠端服務返回給客戶端的物件為代理物件,客戶端在onServiceConnected(ComponentName name, IBinder service)方法引用該物件時不能直接強轉成介面型別的例項,而應該使用asInterface(IBinder iBinder)進行型別轉換。 三、效果演示