怎樣用AIDL Service 傳遞複雜數據

来源:http://www.cnblogs.com/shouce/archive/2016/05/25/5525719.html
-Advertisement-
Play Games

大家都知道在Android中通過AIDL可以跨進程調用Service中的數據,網上也有很多實例,但是大部分實例都是關於基本數據類型的遠程調用,很少講到複雜數據的調用,今天我用一個例子來演示一下怎樣用AIDL Service 傳遞複雜數據。 我們分2步開始: 第一步:部署我們的服務端,也就是Servi ...


大家都知道在Android中通過AIDL可以跨進程調用Service中的數據,網上也有很多實例,但是大部分實例都是關於基本數據類型的遠程調用,很少講到複雜數據的調用,今天我用一個例子來演示一下怎樣用AIDL Service 傳遞複雜數據。

我們分2步開始:

第一步:部署我們的服務端,也就是Service端:

1:在Service端我先自定義2個類型:Person和Pet。因為我們需要跨進程傳遞Person對象和Pet對象,所以Person類和Pet類都必須實現Parcelable介面,並要求在實現類中定義一個名為CREATER,類型為Parcelable.creator的靜態Field。

代碼如下:

複製代碼
  1 package com.example.remoteservice;
  2 
  3 import android.os.Parcel;
  4 import android.os.Parcelable;
  5 
  6 public class Person implements Parcelable {
  7     int id;
  8     String name;
  9     String pass;
 10 
 11     public Person() {
 12 
 13     }
 14 
 15     public Person(int id, String name, String pass) {
 16         this.id = id;
 17         this.name = name;
 18         this.pass = pass;
 19     }
 20 
 21     @Override
 22     public boolean equals(Object o) {
 23         if (this == o) {
 24             return true;
 25         }
 26         if (o == null) {
 27             return false;
 28         }
 29 
 30         if (getClass() != o.getClass()) {
 31             return false;
 32         }
 33         Person other = (Person) o;
 34 
 35         if (name == null) {
 36             if (other.name != null) {
 37                 return false;
 38             }
 39         } else if (!name.equals(other.name)) {
 40             return false;
 41         }
 42 
 43         if (pass == null) {
 44             if (other.pass != null) {
 45                 return false;
 46             }
 47         } else if (!pass.equals(other.pass)) {
 48             return false;
 49         }
 50 
 51         return true;
 52     }
 53 
 54     @Override
 55     public int hashCode() {
 56         final int prime = 31;
 57         int result = 1;
 58         result = prime * result + (name == null ? 0 : name.hashCode());
 59         result = prime * result + (pass == null ? 0 : pass.hashCode());
 60         return result;
 61     }
 62 
 63     @Override
 64     public int describeContents() {
 65 
 66         return 0;
 67     }
 68 
 69     @Override
 70     public void writeToParcel(Parcel arg0, int arg1) {
 71         arg0.writeInt(id);
 72         arg0.writeString(name);
 73         arg0.writeString(pass);
 74     }
 75 
 76     public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() {
 77 
 78         @Override
 79         public Person createFromParcel(Parcel source) {
 80 
 81             return new Person(source.readInt(), source.readString(), source.readString());
 82         }
 83 
 84         @Override
 85         public Person[] newArray(int size) {
 86 
 87             return new Person[size];
 88         }
 89     };
 90 
 91     public int getId() {
 92         return id;
 93     }
 94 
 95     public void setId(int id) {
 96         this.id = id;
 97     }
 98 
 99     public String getName() {
100         return name;
101     }
102 
103     public void setName(String name) {
104         this.name = name;
105     }
106 
107     public String getPass() {
108         return pass;
109     }
110 
111     public void setPass(String pass) {
112         this.pass = pass;
113     }
114 
115 }
複製代碼

因為我們會對Person進行比較,所以在Person類中我重寫了

public int hashCode() 和 public boolean equals(Object o)方法
複製代碼
 1 package com.example.remoteservice;
 2 
 3 import android.os.Parcel;
 4 import android.os.Parcelable;
 5 
 6 public class Pet implements Parcelable {
 7     String name;
 8     float weight;
 9 
10     public Pet(String name, float weight) {
11         this.name = name;
12         this.weight = weight;
13     }
14 
15     public String getName() {
16         return name;
17     }
18 
19     public void setName(String name) {
20         this.name = name;
21     }
22 
23     public float getWeight() {
24         return weight;
25     }
26 
27     public void setWeight(float weight) {
28         this.weight = weight;
29     }
30 
31     @Override
32     public int describeContents() {
33 
34         return 1;
35     }
36 
37     @Override
38     public void writeToParcel(Parcel dest, int flags) {
39         dest.writeString(name);
40         dest.writeFloat(weight);
41 
42     }
43 
44     public static final Parcelable.Creator<Pet> CREATOR = new Creator<Pet>() {
45 
46         @Override
47         public Pet createFromParcel(Parcel source) {
48 
49             return new Pet(source.readString(), source.readFloat());
50         }
51 
52         @Override
53         public Pet[] newArray(int size) {
54 
55             return new Pet[size];
56         }
57     };
58 
59     @Override
60     public String toString() {
61 
62         return "name:" + this.name + ";weight:" + this.weight;
63     }
64 
65 }
複製代碼

2:創建完自定義類型之後還需要用AIDL來定義它們,Person.aidl和Pet.aidl的代碼如下:

1 package com.example.remoteservice;
2 parcelable Person;
1 package com.example.remoteservice;
2 parcelable Pet;

3:完成1,2之後就可以使用AIDL定義通信介面了,在這裡我定義一個IPet.aidl的介面,代碼如下:

複製代碼
1 package com.example.remoteservice; //必須導入包 
2 import com.example.remoteservice.Person; //指定自定義類的位置
3 import com.example.remoteservice.Pet;
4 
5 interface IPet
6 {
7 List<Pet> getPets(in Person owner);//這裡的in表示Person對象是輸入的參數
8 }
複製代碼

4:服務端的最後一步就是實現Service了,當然不要忘了註冊Service,代碼如下:

複製代碼
 1 package com.example.remoteservice;
 2 
 3 import com.example.remoteservice.IPet.Stub;
 4 
 5 import java.util.ArrayList;
 6 import java.util.HashMap;
 7 import java.util.List;
 8 import java.util.Map;
 9 
10 import android.app.Service;
11 import android.content.Intent;
12 import android.os.IBinder;
13 import android.os.RemoteException;
14 import android.util.Log;
15 
16 public class RemoteService extends Service {
17 
18     private PetBinder petBinder;
19 
20     private static Map<Person, List<Pet>> pets = new HashMap<Person, List<Pet>>();
21     static {
22         ArrayList<Pet> list1 = new ArrayList<Pet>();
23         list1.add(new Pet("candy", 2.2f));
24         list1.add(new Pet("sandy", 4.2f));
25         pets.put(new Person(1, "sun", "sun"), list1);
26 
27         ArrayList<Pet> list2 = new ArrayList<Pet>();
28         list2.add(new Pet("moon", 5.2f));
29         list2.add(new Pet("hony", 6.2f));
30         pets.put(new Person(1, "csx", "csx"), list2);
31 
32     }
33 
34     public class PetBinder extends Stub {// 繼承IPet介面中的Stub類,Stub類繼承了Binder類,所有PetBinder也間接的繼承了Binder類
35 
36         @Override
37         public List<Pet> getPets(Person owner) throws RemoteException {
38 
39             return pets.get(owner);
40         }
41 
42     }
43 
44     @Override
45     public IBinder onBind(Intent intent) {
46 
47         Log.i("csx", "onBind");
48         return petBinder;
49     }
50 
51     @Override
52     public void onCreate() {
53 
54         super.onCreate();
55         Log.i("csx", "onCreate");
56         petBinder = new PetBinder();// 實例化Binder
57 
58     }
59 
60     @Override
61     public boolean onUnbind(Intent intent) {
62 
63         Log.i("csx", "onUnbind");
64         return super.onUnbind(intent);
65     }
66 
67     @Override
68     public void onDestroy() {
69 
70         super.onDestroy();
71         Log.i("csx", "onDestroy");
72     }
73 
74 }
複製代碼

這是我Service端的部署情況(其中MainActivity可以不用去實現,因為我們只提供服務,沒有視窗顯示):

第二步:部署客戶端:

1.在客戶端新建一個包,命名需要和服務端放置aidl文件的包名相同(我這裡是com.example.remoteservice),然後把服務端的Person.java,Pet.java,Person.aidl,Pet.aidl,IPet.aidl複製到這個包下麵

 

2.在activity中綁定遠程服務進行數據交換,layout佈局和activity代碼如下:

複製代碼
 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.example.remoteclient.RemoteClient" >
10 
11     <LinearLayout
12         android:layout_width="match_parent"
13         android:layout_height="match_parent"
14         android:orientation="vertical" >
15 
16         <LinearLayout
17             android:layout_width="match_parent"
18             android:layout_height="wrap_content"
19             android:orientation="horizontal" >
20 
21             <EditText
22                 android:id="@+id/editText_person"
23                 android:layout_width="wrap_content"
24                 android:layout_height="wrap_content"
25                 android:layout_gravity="bottom"
26                 android:ems="10" >
27             </EditText>
28 
29             <Button
30                 android:id="@+id/button_ok"
31                 android:layout_width="wrap_content"
32                 android:layout_height="wrap_content"
33                 android:layout_gravity="bottom"
34                 android:text="確定" />
35         </LinearLayout>
36 
37         <ListView
38             android:id="@+id/listView_pet"
39             android:layout_width="match_parent"
40             android:layout_height="wrap_content" >
41         </ListView>
42     </LinearLayout>
43 
44 </RelativeLayout>
複製代碼

複製代碼
  1 package com.example.remoteclient;
  2 
  3 import android.app.Service;
  4 import android.content.ComponentName;
  5 import android.content.Intent;
  6 import android.content.ServiceConnection;
  7 import android.os.Bundle;
  8 import android.os.IBinder;
  9 import android.os.RemoteException;
 10 import android.support.v7.app.ActionBarActivity;
 11 import android.util.Log;
 12 import android.view.View;
 13 import android.view.View.OnClickListener;
 14 import android.widget.ArrayAdapter;
 15 import android.widget.Button;
 16 import android.widget.EditText;
 17 import android.widget.ListView;
 18 
 19 import com.example.remoteservice.IPet;
 20 import com.example.remoteservice.Person;
 21 import com.example.remoteservice.Pet;
 22 
 23 import java.util.List;
 24 
 25 public class RemoteClient extends ActionBarActivity {
 26 
 27     public static final String REMOTE_SERVICE_ACTION = "com.example.remoteservice.RemoteService.ACTION";
 28     EditText editText;
 29     Button button;
 30     ListView listView;
 31 
 32     IPet petService;// 聲明IPet介面
 33     List<Pet> pets;
 34     ServiceConnection conn = new ServiceConnection() {
 35 
 36         @Override
 37         public void onServiceDisconnected(ComponentName name) {
 38             Log.i("csx", "onServiceDisconnected");
 39             conn = null;
 40         }
 41 
 42         @Override
 43         public void onServiceConnected(ComponentName name, IBinder service) {
 44             Log.i("csx", "onServiceConnected");
 45             petService = IPet.Stub.asInterface(service);// 通過遠程服務的Binder實現介面
 46 
 47         }
 48     };
 49 
 50     @Override
 51     protected void onCreate(Bundle savedInstanceState) {
 52         super.onCreate(savedInstanceState);
 53         setContentView(R.layout.remote_client_layout);
 54         editText = (EditText) findViewById(R.id.editText_person);
 55         button = (Button) findViewById(R.id.button_ok);
 56         listView = (ListView) findViewById(R.id.listView_pet);
 57 
 58         Intent service = new Intent();
 59         service.setAction(REMOTE_SERVICE_ACTION);
 60 
 61         bindService(service, conn, Service.BIND_AUTO_CREATE);// 綁定遠程服務
 62 
 63         button.setOnClickListener(new OnClickListener() {
 64 
 65             @Override
 66             public void onClick(View v) {
 67                 String personName = editText.getText().toString();
 68                 if (personName == null || personName.equals("")) {
 69 
 70                     return;
 71                 }
 72 
 73                 try {
 74                     pets = petService.getPets(new Person(1, personName, personName));// 調用遠程service的getPets方法
 75                     updataListView();
 76 
 77                 } catch (RemoteException e) {
 78 
 79                     e.printStackTrace();
 80                 } catch (NullPointerException e) {
 81                     e.printStackTrace();
 82                 }
 83 
 84             }
 85         });
 86 
 87     }
 88 
 89     public void updataListView() {
 90         listView.setAdapter(null);
 91 
 92         if (pets == null || pets.isEmpty()) {
 93             return;
 94 
 95         }
 96         ArrayAdapter<Pet> adapter = new ArrayAdapter<Pet>(RemoteClient.this,
 97                 android.R.layout.simple_list_item_1, pets);
 98         listView.setAdapter(adapter);
 99 
100     }
101 
102     @Override
103     protected void onDestroy() {
104 
105         unbindService(conn);// 解除綁定
106         super.onDestroy();
107     }
108 
109 }
複製代碼

到此為止所有的工作都完成了,下麵我們看一下效果:我在編輯框中輸入“csx”,點擊確定,就會顯示出服務端RemoteService中pets的相應數據。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在javascript中,經常會需要操作DOM操作,在此記錄一下學習到DOM操作的知識。 一、JavaScript DOM 操作 1.1、DOM概念 DOM :Document Object Model(文本對象模型)。 D : 文檔(html或xml文檔) O : 對象(文檔對象) M : 模型 ...
  • 終於完成了手頭的項目,失蹤人口又回歸啦!在做項目的過程中,遇到很多值得思考的點,速速道來。 第一個遇到的就是網頁大小自適應的問題。 目前比較常用的方法有: 首先要讓頁面大小鋪滿屏幕又不能溢出。只需要在html``標簽內加入viewport(如下),參數分別表示:頁面寬度= 屏幕寬度,最大和最小伸縮比 ...
  • 最近在模仿各大網站寫頁面樣式和交互,發現好多都有回到頂部的需要,所以寫了一下js,記錄下來。 發現還可以添加從快到慢的動畫效果和隨時下拉滾動條停止滾動的功能, 參考了imooc上相關課程,最終實現JS代碼如下: ...
  • 這款app是我花一周左右時間做出來的,一款閱讀笑話,段子,糗事,腦筋急轉彎,神回覆,語錄,謎語等的休閑娛樂app,用戶除了可以瀏覽他人發佈的內容外,自己也可以發佈相關內容,和其他人一同分享有趣的內容,整個app集成了用戶註冊登錄,修改昵稱用戶名及個性簽名併在前端調用顯示,用戶自主發佈帖子,他人點贊, ...
  • 比如我們想在xib 中設置按鈕的圓角,這樣的話我們就可以在xib文件中進行修改,具體操作如下 實現效果,如下 ...
  • 代碼: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //使圖片兩邊不拉伸,中間拉伸 UIImage *image = [UIImage imageNamed ...
  • 轉自:http://blog.csdn.net/totogo2010/article/details/9100767 準備2個文件: 文件一,ThisService.app 文件二,Doxygen.rb 下載上述2個文件:ThisService&Doxygen_rb 準備好之後,兩步配置,一步操作: ...
  • CocoaPods是什麼 當我們開發iOS項目時候,會經常使用到第三方類庫,並且會使用很多。大家的做法基本上都是到GitHub上下載一個一個的類庫,然後導入到工程中,並且引入各種的類庫,做各種的配置。有時候還要處理ARC與MRC的問題,很麻煩。還有一種情況,就是當第三方類庫出現升級的情況時候,我們還 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...