Android開發:使用AIDL實現兩個App間通信

Android開發:使用AIDL實現兩個App間通信

今天開發了一個功能,通過Android的AIDL機制完成兩個app間的通信。功能需求很簡單,一個客戶端app,叫做client,一個服務端app叫orderManager;客戶端負責展示訂單列表,並且可以向服務端添加訂單;服務端負責管理訂單,可以對外提供訂單信息。
閒言少敘,下面直接上代碼。


1、編寫bean類。
首先在client中定義OrderBean類,字段很簡單,注意需要實現Parcelable接口:

package com.example.wang.client.bean;

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

public class OrderBean implements Parcelable{
    private String id;
    private String name;
    private int amount;

    public OrderBean(){}

    public OrderBean(String id, String name, int amount) {
        this.id = id;
        this.name = name;
        this.amount = amount;
    }

    protected OrderBean(Parcel in) {
        id = in.readString();
        name = in.readString();
        amount = in.readInt();
    }

    public static final Creator<OrderBean> CREATOR = new Creator<OrderBean>() {
        @Override
        public OrderBean createFromParcel(Parcel in) {
            return new OrderBean(in);
        }

        @Override
        public OrderBean[] newArray(int size) {
            return new OrderBean[size];
        }
    };
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(id);
        dest.writeString(name);
        dest.writeInt(amount);
    }
    //get/set方法略
}

2、定義aidl文件。aidl文件的存放位置在Android Studio中一般存放在如下路徑:
client/src/aidl/…

 // OrderBean.aidl
package com.example.wang.client.bean;//存放的包路徑同bean類
parcelable OrderBean;//通信用到的Parcelable需要聲明,並且使用小寫的parcelable

// IBookManager.aidl
package com.example.wang.client.aidl;

import com.example.wang.client.bean.OrderBean;//除了系統提供的對象,都需要明確導入

interface IOrderManager {
    List<OrderBean> getAll();
    void add(in OrderBean bean);
}

3、定義佈局文件,編寫MainActivity。這個很簡單,Button和RecyclerView結合即可:

#activity_main.xml - 主頁面佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="5dp"
        android:text="訂單管理"
        android:textSize="20dp"/>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp">
        <Button
            android:id="@+id/search_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15dp"
            android:text="刷新訂單"/>
        <Button
            android:id="@+id/add_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15dp"
            android:text="添加訂單"/>
    </LinearLayout>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</LinearLayout>

還要寫一個item_order.xml,用於RecyclerView的展示,很簡單,此處略過。

//MainActivity.java
package com.example.wang.client;
...
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private List<OrderBean> orderList;
    private IOrderManager orderManager;
    //UI
    private Button search_button;
    private Button add_button;
    private RecyclerView recyclerView;
    private OrderAdapter adapter;

    ServiceConnection conn = new ServiceConnection() {//這個最重要,用於連接Service
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("MainActivity.conn","@@ onServiceConnected name="+name);
            IOrderManager manager = IOrderManager.Stub.asInterface(service);
            orderManager = manager;
            refreshOrderList();
            try {
                service.linkToDeath(deathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("MainActivity.conn","@@ onServiceDisconnected name="+name);
        }
    };
    IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {//註冊一個死亡代理,監測連接狀態
        @Override
        public void binderDied() {
            Log.i("MainActivity","@@ binderDied "+(orderManager==null));
            if(orderManager==null){
                return;
            }
            orderManager.asBinder().unlinkToDeath(deathRecipient, 0);
            orderManager = null;
            //重新綁定
            bindOrderService();
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("MainActivity","@@ onCreate");
        setContentView(R.layout.activity_main);
        getLayoutInflater();
        //view
        search_button=findViewById(R.id.search_button);
        add_button=findViewById(R.id.add_button);
        recyclerView=findViewById(R.id.recyclerView);
        //組裝recyclerView
        LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        adapter=new OrderAdapter(this);
        recyclerView.setAdapter(adapter);
        //onclick
        search_button.setOnClickListener(this);
        add_button.setOnClickListener(this);
        //bind
        bindOrderService();
    }
    private void bindOrderService(){
        Intent intent = new Intent("com.example.wang.ordermanager.OrderService");
        intent.setPackage("com.example.wang.ordermanager");
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }
    /**
     * 重新獲取數據並刷新列表。
     */
    private void refreshOrderList(){
        try {
            if(orderManager!=null){
                orderList = orderManager.getAll();
            }
            if(orderList!=null){
                adapter.setData(orderList);
                adapter.notifyDataSetChanged();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onClick(View v) {
        if(v==search_button){
            //刷新訂單
            refreshOrderList();
        }else if(v==add_button){
            //增加訂單
            try {
                OrderBean orderBean=new OrderBean();
                Random random=new Random();
                orderBean.setAmount(random.nextInt(800)+100);
                orderBean.setId(random.nextInt(100000000)+100000+"");
                orderBean.setName("玩具"+random.nextInt());
                orderManager.add(orderBean);
                refreshOrderList();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

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

4、編寫服務端代碼
這裏主要做兩件事,第一個是移植aidl文件和bean類,將client中的aidl文件和OrderBean移植過來,文件路徑要保持一致,第二個是編寫OrderService.java類。

//OrderService.java
package com.example.wang.ordermanager;
...

public class OrderService extends Service{
    private CopyOnWriteArrayList<OrderBean> list = new CopyOnWriteArrayList<>();

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("OrderService","@@ onCreate");

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("OrderService","@@ onBind");
        return binder;
    }

    Binder binder = new IOrderManager.Stub(){

        @Override
        public List<OrderBean> getAll() throws RemoteException {
            return list;
        }

        @Override
        public void add(OrderBean bean) throws RemoteException {
            list.add(bean);
        }
    };

}

OrderService服務在AndroidManifest.xml中的配置如下:

<service android:name=".OrderService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.wang.ordermanager.OrderService"/>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </service>

代碼編寫就完成了,運行時需要先運行服務端app,再運行client,如果運行過程中OrderService服務斷掉了,client會通過死亡代理得到通知,再重新綁定即可。
運行如下:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章