1. 程式人生 > >Android程序間通訊(二)——傳遞複雜資料

Android程序間通訊(二)——傳遞複雜資料

上一篇文章中介紹瞭如何在Android不同程序間傳遞資料,但是傳遞的都是基本資料型別或者String型別,這些都是系統資料型別。如何傳遞自定義資料型別呢?

下面我們來舉個栗子。假設我們有兩個自定義的類,一個是Person類,一個是Car類。一個Person物件有一個屬性:姓名(name);一個Car物件有兩個屬性:品牌(brand)和價格(price)。一個人可以有多輛車,在客戶端輸入一個人的名字,就可以從服務端獲取這個人擁有的車的資訊。因為Person和Car都是自定義類,通過這個例子就可以看看如何在程序間傳遞自定義型別的資料。

還是先看服務端

一、自定義類,實現Parcelable介面。
傳遞自定義型別和傳遞系統型別最大的區別就在於要為自定義型別實現Parcelable介面。其他步驟就和傳遞系統型別差不多了。

Parcelable介面是Android提供的一種輕量級的序列化方法。要在不同的程序間傳遞自定義的資料型別,就需要實現了Parcelable介面。

定義Person類和Car類,分別實現Parcelable介面。

Person類的程式碼如下:

package com.example.aidlservice;

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable {

    private String name;

    public
Person() { } public Person(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 要將Person物件作為HashMap的key,就必須重寫equals方法和hashCode方法 @Override
public boolean equals(Object o) { if(o==this) return true; if(o==null) return false; if(getClass()!=o.getClass()) return false; Person other=(Person)o; if(name==null) { if(other.name!=null) { return false; } else return true; } else { if(other.name==null) return false; else { if(name.equals(other.name)) return true; } } return false; } @Override public int hashCode() { final int prime=31; int result=1; result=prime*result+((name==null)?0:name.hashCode()); return result; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); } public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() { @Override public Person[] newArray(int size) { return new Person[size]; } @Override public Person createFromParcel(Parcel source) { Person p=new Person(source.readString()); return p; } }; }

Car類的程式碼如下:

package com.example.aidlservice;

import android.os.Parcel;
import android.os.Parcelable;

public class Car implements Parcelable {

    private Integer price;
    private String brand;

    public Car() {
        super();
    }

    public Car(Integer price, String brand) {
        super();
        this.price = price;
        this.brand = brand;
    }

    public Integer getPrice() {
        return price;
    }
    public void setPrice(Integer price) {
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }


    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // TODO Auto-generated method stub
        dest.writeInt(price);
        dest.writeString(brand);
    }

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

        @Override
        public Car[] newArray(int size) {
            // TODO Auto-generated method stub
            return new Car[size];
        }

        @Override
        public Car createFromParcel(Parcel source) {
            // TODO Auto-generated method stub
            return new Car(source.readInt(), source.readString());
        }
    };
}

二、為每個自定義類建立對應的aidl檔案
Java程式碼寫好以後,要為每個自定義類建立一個對應的aidl檔案。aidl檔案內容很簡單,類似於一個宣告。

Person.aidl檔案內容如下:

parcelable Person;

Car.aidl檔案內容如下:

parcelable Car;

三、在aidl檔案中定義一個供遠端呼叫的介面
ICar.aidl檔案內容如下:

package com.example.aidlservice;

import com.example.aidlservice.Car;
import com.example.aidlservice.Person;

interface ICar
{
    List<Car> getCars(in Person owner);
}

四、建立遠端Service

package com.example.aidlservice;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class AidlService extends Service {

    private CarBinder carBinder;
    private static Map<Person,List<Car>> cars=new HashMap<Person,List<Car>>();
    public AidlService() {
    }
    // 初始化塊,初始化一些資料
    static
    {
        List<Car> list1=new ArrayList<Car>();
        list1.add(new Car(80000, "現代"));
        list1.add(new Car(130000, "起亞"));
        cars.put(new Person("小張"),list1);

        List<Car> list2=new ArrayList<Car>();
        list2.add(new Car(200000, "奧迪"));
        list2.add(new Car(400000, "寶馬"));
        cars.put(new Person("李總"),list2);
    }
    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("Service created...");
        // 此處建立一個CarBinder 的例項
        carBinder=new CarBinder();
    }
    // 客戶端繫結到本Service的時候會呼叫此方法
    // 通過此方法將Binder的例項返回給客戶端
    @Override
    public IBinder onBind(Intent intent) {
        return carBinder;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
    // 此處定義一個com.example.aidlservice.ICar.Stub類的子類
    // 該類的例項會返回給客戶端,供客戶端呼叫
    public class CarBinder extends ICar.Stub
    {
        // 回撥方法,返回一個Person的車輛
        @Override
        public List<Car> getCars(Person owner) throws RemoteException {
            return cars.get(owner);
        }
    }
}

最後配置一下service,服務端就完成了。

客戶端的編寫就和上一篇文章差不多了。先將Person.java、Car.java、Person.aidl、Car.aidl、ICar.aidl一起拷貝到AidlClient專案的com.example.aidlservice包下。然後在com.example.aidlclient包下編寫Activity。直接上程式碼了:

package com.example.aidlclient;

import java.util.List;

import com.example.aidlservice.Car;
import com.example.aidlservice.ICar;
import com.example.aidlservice.Person;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

public class AidlClient extends Activity {

    private Button get;
    private EditText name;
    private ICar carService;
    private LinearLayout linearLayout;

    private ServiceConnection conn=new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            carService=null;
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            carService=ICar.Stub.asInterface(service);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        get=(Button)findViewById(R.id.btn_get);
        name=(EditText)findViewById(R.id.et_person);

        linearLayout=(LinearLayout)findViewById(R.id.ll_show);
        linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));

        // 繫結Service
        Intent service=new Intent();
        service.setAction("com.example.aidlservice.action.AIDL_SERVICE");
        bindService(service, conn, Service.BIND_AUTO_CREATE);

        get.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // 清除所有TextView
                linearLayout.removeAllViews();
                try {

                    List<Car> cars=carService.getCars(new Person(name.getText().toString()));
                    if(cars==null)
                    {
                        System.out.println("error! cars is null...");
                        return;
                    }
                    StringBuilder sb=new StringBuilder();
                    sb.append("Person:"+name.getText().toString()+"\n");
                    TextView tv1=new TextView(AidlClient.this);
                    tv1.setText(sb.toString());
                    linearLayout.addView(tv1);
                    for(Car car:cars)
                    {
                        TextView tv=new TextView(AidlClient.this);
                        tv.setText("car:"+car.getBrand()+" "+car.getPrice());
                        linearLayout.addView(tv);
                    }

                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        this.unbindService(conn);
    }
}

最後再配置一下Activity。
分別執行AidlServer和AidlClient專案。在客戶端介面輸入名字就可以獲取到該Person的車輛資訊,實現了複雜資料的跨程序傳輸。
這裡寫圖片描述

相關推薦

Android程序通訊——傳遞複雜資料

上一篇文章中介紹瞭如何在Android不同程序間傳遞資料,但是傳遞的都是基本資料型別或者String型別,這些都是系統資料型別。如何傳遞自定義資料型別呢? 下面我們來舉個栗子。假設我們有兩個自定義的類,一個是Person類,一個是Car類。一個Person

Android IPC程序通訊Messenger

Messenger實現程序間低併發即時通訊 Messenger是一種輕量級的IPC,底層實現是AIDL,即可認為Binder。通過在Message中攜帶Bundle進而實現程序之間傳遞資料。由於Messenger一次只能處理一個請求,因此服務端們不用考慮執行緒同步問題。 一,我們在服務端

讀書筆記:Android中的程序通訊

閱讀的書籍:《Android開發藝術探索》 關鍵詞:Serializable,Parcelable,Serializable和Parcelable的區別,Binder Serializable介面:java提供的一個序列化介面,為物件提供標準的序列化和反序列化操作

程序通訊命名管道fifo

要學習命名管道,我們必須首先對管道的特性有一定的瞭解,管道特性以及匿名管道連結 命名管道:管道的一個限制就是隻能用在親緣程序之間,如果我們想在不相關的程序間進行資料交換,可以使用FIFO檔案來進行,它叫做命名管道。 命名管道:檔案系統可見,是一個特殊型別(管道型別)的檔案。命名管

程序通訊共享記憶體、訊號量

本片部落格會貼上部分程式碼,想要了解更多程式碼資訊,可訪問小編的GitHub關於本篇的程式碼 共享記憶體 這裡有涉及的mmap的知識 下圖為共享記憶體原理圖 因為共享記憶體是直接將申請來的一塊實體記憶體對映到虛擬地址空間中,允許兩個或多個程序共享,因此進行

Linux環境程序通訊: 訊號(轉)

訊號本質訊號是在軟體層次上對中斷機制的一種模擬,在原理上,一個程序收到一個訊號與處理器收到一箇中斷請求可以說是一樣的。訊號是非同步的,一個程序不必通過任何操作來等待訊號的到達,事實上,程序也不知道訊號到底什麼時候到達。訊號是程序間通訊機制中唯一的非同步通訊機制,可以看作是非同步通知,通知接收訊號的程序有哪些事

Linux環境程序通訊: 訊號(轉)

從訊號傳送到訊號處理函式的執行完畢對於一個完整的訊號生命週期(從訊號傳送到相應的處理函式執行完畢)來說,可以分為三個重要的階段,這三個階段由四個重要事件來刻畫:訊號誕生;訊號在程序中註冊完畢;訊號在程序中的登出完畢;訊號處理函式執行完畢。相鄰兩個事件的時間間隔構成訊號生命週期的一個階段。 下面闡述四個事件的實

Android 程序通訊AIDL

在Android平臺,一個程序通常不能訪問另一個程序的記憶體空間,所以要想對話,需要將物件分解成作業系統可以理解的基本單元,並且有序的通過程序邊界。通過程式碼來實現這個資料傳輸過程是冗長乏味的,Android提供了AIDL工具來處理這項工作。 AIDL (An

Linux程序通訊

1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<unistd.h> 4 #include<sys/stat.h> 5 #include<fcntl.h> 6 #includ

Android程序通訊IPC機制Binder簡要介紹和學習計劃

轉載:http://blog.csdn.net/luoshengyang/article/details/6618363/在Android系統中,每一個應用程式都是由一些Activity和Service組成的,這些Activity和Service有可能執行在同一個程序中,也有

Android IPC程序通訊 Binder連線池

Binder管家之Binder連線池 IPC程序間通訊(四)之AIDL中的AIDL由一個Service進行管理,若是建立10個AIDL業務模組是不是也要建立10個Service來進行管理,那100個呢?顯然繁瑣,怎麼辦麼,用Binder連線池呀! 工作機制: 1.每個業務模組建立其AID

Android IPC程序通訊Socket

網路通訊之Socket 特點:功能強大,可通過網路傳輸位元組流,支援一對多併發即時通訊。 不支援RPC。 服務端實現: public class SorviceSocket extends Service { private static final String TAG

Android IPC程序通訊AIDL

AIDL-Android介面定義語言 一· 1.相比於Messenger AIDL可跨程序呼叫方法。 2.支援資料型別: (1) Java 的原生基本型別(int, long, char, boolean, double等) (2)String 和CharSequence (3) Arr

Android IPC程序通訊Binder

程序間通訊的介質Binder Binder實現了IBinder介面,是android中跨程序通訊的一種方式。是服務端和客戶端通訊的媒介。 Binder的建立: 1.建立自定義類Book.java實現Parcelable介面,以實現序列化可反序列化。 public class Book

Android IPC程序通訊檔案共享

IPC程序間通訊簡介 1.在AndroidManifest.xml中宣告元件android:process屬性。 不指定process屬性,則預設執行在主程序中,主程序名字為包名。 android:process = package:remote,將執行在package:remote程序

Android 8.0系統原始碼分析--Binder程序通訊

 開始我們的沉澱之路,老羅的書中第二章講的是Android HAL層的知識,而且直接自己實現了一個虛擬的freg驅動程式,後面的幾節是分別從native、java層如何訪問這個虛擬的驅動程式介面,我這裡沒有這樣的環境,所以就不分析這節了,第三章的智慧指標我對比8.0系統原

Android中的Service與程序通訊IPC詳解

Service 什麼是Service 在後臺長期執行的沒有介面的元件。其他元件可以啟動Service讓他在後臺執行,或者繫結Service與它進行互動,甚至實現程序間通訊(IPC)。例如,可以讓服務在後臺處理網路互動,播放音樂,檔案I/O,或者與Cont

Linux程序通訊IPC方式總結

程序間通訊概述 程序通訊的目的 資料傳輸  一個程序需要將它的資料傳送給另一個程序,傳送的資料量在一個位元組到幾M位元組之間 共享資料  多個程序想要操作共享資料,一個程序對共享資料 通知事件 一個程序需要向另一個或一組程序傳送訊息,通知它(它們)

程序通訊共享記憶體

概念: 共享記憶體區是最快的IPC形式。⼀一旦這樣的記憶體對映到共享它的程序的地址空間,這些程序間資料傳遞不再 涉及到核心,換句話說是程序不再通過執⾏行進⼊入核心的系統調⽤用來傳遞彼此的資料。 共享記憶體中的函式: shmget函式: 功能:⽤用來建立共享記憶體 原型

Androi IPC程序通訊ContentProvider

程序間通訊之ContentProvider 一,介紹 1.底層實現也是Binder 2.其6個方法除了onCreate方法運行於主執行緒,其他4個方法由外界回撥並運行於Binder執行緒池。 3.註冊ContentProvider需要一個屬性android:authorities=“XX