綁定帳號登入

Android 台灣中文網

打印 上一主題 下一主題

[資料] Android怎麼跨進程調用外部服務

[複製連結] 查看: 1341|回覆: 0|好評: 0
跳轉到指定樓層
樓主
暗桌之光 | 收聽TA | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
發表於 2011-6-14 15:36

馬上加入Android 台灣中文網,立即免費下載應用遊戲。

您需要 登錄 才可以下載或查看,沒有帳號?註冊

x
跨進程調用服務主要步驟:創建AIDL服務端,此服務端將提供一個Student 的javabean 提供客戶端取得數據,因為aidl 支持的數據類型比較簡單,故這裡建議把常用的數據類型的數據寫入服務。

1、創建AIDL 服務端

在Android 的src 文件夾下的任意包裡面新建文件,後綴名為*.aidl

輸入如下代碼:
  1. package com.aidl.test;
  2. import com.aidl.test.Student;

  3. interface IMyService
  4. {
  5.         Map getMap(in String test_class,in Student student);
  6.          Student getStudent();
  7. }
複製代碼
Student 類是一個序列化的類,這裡使用Parcelable 接口來序列化是Google 提供的一個比Serializable 效率更高的序列化類。Student  類代碼如下:
  1. package com.aidl.test;

  2. import android.os.Parcel;
  3. import android.os.Parcelable;

  4. public class Student implements Parcelable {

  5.     private int age;
  6.     private String name;

  7.     public int getAge() {
  8.         return age;
  9.     }

  10.     public void setAge(int age) {
  11.         this.age = age;
  12.     }

  13.     public String getName() {
  14.         return name;
  15.     }

  16.     public void setName(String name) {
  17.         this.name = name;
  18.     }

  19.     public static final Parcelable.Creator<Student> CREATOR = new Creator<Student>() {

  20.         @Override
  21.         public Student[] newArray(int size) {
  22.             // TODO Auto-generated method stub
  23.             return new Student[size];
  24.         }

  25.         @Override
  26.         public Student createFromParcel(Parcel source) {
  27.             // TODO Auto-generated method stub
  28.             return new Student(source);
  29.         }
  30.     };

  31.     public Student() {
  32.     }

  33.     public Student(Parcel pl) {
  34.         age = pl.readInt();
  35.         name = pl.readString();
  36.     }

  37.     @Override
  38.     public int describeContents() {
  39.         // TODO Auto-generated method stub
  40.         return 0;
  41.     }

  42.     @Override
  43.     public void writeToParcel(Parcel dest, int flags) {
  44.         // TODO Auto-generated method stub
  45.         dest.writeInt(age);
  46.         dest.writeString(name);
  47.     }

  48. }
複製代碼
在這裡必須注意,編寫javabean時必須注意如下三點:

在Student 類中必須有一個靜態常量,常量名必須是CREATOR,而且CREATOR 常量的數據類型必須是 Parcelable.Creator
在writeToParcel 方法中需要將要序列化的值寫入到 Parcel對像中。
編寫完Student 為時,必須再新建一個Student.aidl 文件,此文件輸入以下內容:
parcelable Student; 這裡的書寫是供上面我們說過的接口   *.aidl 文件導包時可以找到,並通過此文件找到Student類對象。
如果上面的步驟順利通過的話,Android 將會自動在gen 目錄下R文件的相同目錄生成一個以*.aidl 文件命名的*.java 文件

順利生成成功後,我們再來編寫一個AIDL 服務類,代碼如下:
  1. package com.aidl.test;

  2. import java.util.HashMap;
  3. import java.util.Map;

  4. import android.app.Service;
  5. import android.content.Intent;
  6. import android.os.IBinder;
  7. import android.os.RemoteException;

  8. public class MyService extends Service {

  9.     @Override
  10.     public IBinder onBind(Intent intent) {
  11.         // TODO Auto-generated method stub
  12.         return new MyServiceimpl();
  13.     }

  14.     public class MyServiceimpl extends IMyService.Stub {

  15.         @Override
  16.         public Student getStudent() throws RemoteException {
  17.             // TODO Auto-generated method stub
  18.             Student st = new Student();
  19.             st.setAge(18);
  20.             st.setName("terry");

  21.             return st;
  22.         }

  23.         @Override
  24.         public Map getMap(String testClass, Student student)
  25.                 throws RemoteException {
  26.             // TODO Auto-generated method stub
  27.             Map<String, Object> map = new HashMap<String, Object>();
  28.             map.put("class", "五年級");
  29.             map.put("age", student.getAge());
  30.             map.put("name", student.getName());
  31.             return map;
  32.         }

  33.     }

  34. }
複製代碼
如上代碼,MyService 服務類有一個子類並繼承自我們上面生成的*.java 文件重寫其中我們在*.aidl 中聲明的兩個接口方法,實現了其功能。上面IBinder 必須返回此服務類的子類對象,否則客戶端將無法獲得服務對象。

最後,即然有服務的操作,那麼就得在manifest文件中註冊服務類,代碼如下:
  1. <service android:name=".MyService">
  2.     <intent-filter>
  3.         <action android:name="com.aidl.test.IMyService"></action>
  4.     </intent-filter>
  5. </service>
複製代碼
至此,服務端就己經開發完成了,下面接著開發客啟端。

2、創建AIDL 客戶端 同樣是新建一個項目,這裡要注意,需要將服務端生成成功後的gen 目錄下的包複製過來,放到我們新建項目的src 文件夾下

因為IMyService 這個生成類,引用到了Student 這個javabean 所以這裡一併將javabean也複製過來。

至此,客戶端的創建己經完畢,下面我們就要利用創建的客戶端去調用服務端的方法。

3、客戶端調用服務端提供的服務接口

細心的朋友會發現,上面的數據不是我們在上面客戶端為Student 設置的數據嗎?怎麼在這個程序 裡面也同樣得到了?沒錯。這就是aidl 的魅力,下面來看看如何調用 吧,圖中有兩個按鈕,一個按鈕為綁定AIDL 服務,即通過Activity 的 bindService 綁定 AIDL 外部服務,全部代碼如下:
  1. package com.aidl.client;

  2. import com.aidl.test.IMyService;

  3. import android.app.Activity;
  4. import android.app.AlertDialog;
  5. import android.content.ComponentName;
  6. import android.content.Context;
  7. import android.content.Intent;
  8. import android.content.ServiceConnection;
  9. import android.os.Bundle;
  10. import android.os.IBinder;
  11. import android.os.RemoteException;
  12. import android.view.View;
  13. import android.view.View.OnClickListener;
  14. import android.widget.Button;

  15. public class aidlActivity extends Activity implements OnClickListener {
  16.     Button btn1, btn2;

  17.     private IMyService myService = null;
  18.     private ServiceConnection serviceConnection = new ServiceConnection() {

  19.         @Override
  20.         public void onServiceDisconnected(ComponentName name) {
  21.             // TODO Auto-generated method stub

  22.         }

  23.         @Override
  24.         public void onServiceConnected(ComponentName name, IBinder service) {
  25.             // TODO Auto-generated method stub
  26.             myService = IMyService.Stub.asInterface(service);
  27.             btn2.setEnabled(true);

  28.         }
  29.     };

  30.     /** Called when the activity is first created. */
  31.     @Override
  32.     public void onCreate(Bundle savedInstanceState) {
  33.         super.onCreate(savedInstanceState);
  34.         setContentView(R.layout.main);

  35.         btn1 = (Button) findViewById(R.id.Button01);
  36.         btn2 = (Button) findViewById(R.id.Button02);
  37.         btn2.setEnabled(false);

  38.         btn1.setOnClickListener(this);
  39.         btn2.setOnClickListener(this);
  40.     }

  41.     @Override
  42.     public void onClick(View v) {
  43.         // TODO Auto-generated method stub
  44.         switch (v.getId()) {
  45.         case R.id.Button01:
  46.             bindService(new Intent("com.aidl.test.IMyService"),
  47.                     serviceConnection, Context.BIND_AUTO_CREATE);
  48.             break;
  49.         case R.id.Button02:
  50.             StringBuilder sb = new StringBuilder();
  51.             try {
  52.                 sb.append("學生名稱為:" + myService.getStudent().getName() + "\n");
  53.                 sb.append("年齡為:" + myService.getStudent().getAge() + "\n");
  54.                 sb.append("map 對像內容為如下:"
  55.                         + myService.getMap("台灣", myService.getStudent())
  56.                                 .toString());
  57.             } catch (RemoteException e) {
  58.                 // TODO Auto-generated catch block
  59.                 e.printStackTrace();
  60.             }

  61.             new AlertDialog.Builder(aidlActivity.this).setTitle("調用外部服務")
  62.                     .setMessage(sb.toString()).setPositiveButton(
  63.                             android.R.string.ok, null).show();
  64.             break;
  65.         default:
  66.             break;
  67.         }
  68.     }
  69. }
複製代碼

「用Android 就來APK.TW」,快來加入粉絲吧!
Android 台灣中文網(APK.TW)

評分

參與人數 1碎鑽 +5 收起 理由
y776 + 5 支持一下

查看全部評分

收藏收藏 分享分享 分享專題
用Android 就來Android 台灣中文網(https://apk.tw)
您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則