跨進程通訊之AIDL-----不同應用程序之間跨進程

AIDL,通俗來說就是兩個Android應用要進行通信,且不能通過網絡雲服務器的方式進行數據交互,只能調用本地函數庫的機制來實現,這時Android系統提供AIDL的機制來實現Android的跨進程通訊(用戶進程之間是相對封閉的,無法直接訪問數據)。

我們先不管任何原理,把demo跑出來再說其他的:
準備材料:一個Service、一個Client、連接S—C的橋樑(AIDL文件)
第一步: 連接S—C的橋樑(AIDL文件),這個aidl文件是客戶端和服務器端都需要的,在服務端或者客戶端的項目中生成都可以,如果傳遞基本數據類型就直接使用,如果是引用數據類型,先聲明這個實體類,項目包結構如下在這裏插入圖片描述
①Person類中主要是實現Parcelable接口,代碼如下

package com.testaidl.model;

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

/**
 * Created by Administrator on 2018\10\31 0031.
 */

public class Person implements Parcelable {
    private String name;

    protected Person(Parcel in) {
        name = in.readString();
    }

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

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
    }

    @Override
    public String toString() {
        return "Person{" +
                "mName='" + this.getName() + '\'' +
                '}';
    }
}

②然後再項目的main結構下創建aidl文件夾,創建Person的aidl後綴文件,必須要和上面Person的包名(結構)相同,在這裏插入圖片描述這個Person類很簡單就是聲明一下parcelable 接口,
③IMyAidl這個接口的方法是提供給C-S調用的,

// IMyAidl.aidl
package com.testaidl;

// 這個引用類型必須是全類名的才能使用
import com.testaidl.model.Person;

interface IMyAidl {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    void addPerson(in Person person);
    List<Person> getPersonList();
}

這樣子,AIDL這個中間件就做好了,把它分別放到代表:客戶端和服務器項目中(例如我們在客戶端的項目中生成AIDL文件,然後copy給服務器,但是要注意包名必須完全一致,C-S兩端都要一致的,有點童鞋會說我想將客戶端或者服務端放到之前的項目中,這時包名是定好的,不方便修改怎麼辦,在與當前包名同級的地方創建Person類,這樣就保證了C-S兩端包名都是一致的)

第二部:創建服務端,在新的項目中copyAIDL文件(放到項目中main結構的aidl文件夾中),一定要注意包名相同!!!,然後在完全相同的包結構下複製Person這個實體類,編譯一下程序,服務端其實就是Android四大組件中的Service,

package com.my_project.test_aidl;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;

import com.testaidl.IMyAidl;
import com.testaidl.model.Person;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018\10\31 0031.
 * 服務端 service
 */

public class MyAidlService extends Service {
    private final String TAG = this.getClass().getSimpleName();
    public ArrayList<Person> mPersons;
    /**
     * 創建生成的本地 Binder 對象,實現 AIDL 制定的方法
     */
    private IBinder mIBinder = new IMyAidl.Stub() {
        @Override
        public void addPerson(Person person) throws RemoteException {
            Log.e("11111111111",person.toString());
            mPersons.add(person);
        }

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public List<Person> getPersonList() throws RemoteException {
            return mPersons;
        }
    };

    /**
     * 客戶端與服務端綁定時的回調,返回 mIBinder 後客戶端就可以通過它遠程調用服務端的方法,即實現了通訊
     *
     * @param intent
     * @return
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        mPersons = new ArrayList<>();
        Log.e(TAG, "MyAidlService onBind");
        return mIBinder;
    }

}

然後咱們再清單文件中聲明service的時候要設置其action(這個名字可以隨意取的):在這裏插入圖片描述
第三步:創建客戶端項目:同樣的方式copyAIDL文件和Person實體類,這個是和服務端一樣的,然後編譯生成Stub,做好準備工作以後,在客戶端上綁定這個服務,bingService(…)

package com.testaidl;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.testaidl.model.Person;

import java.util.List;
import java.util.Random;

/**
 * 客戶端client  代碼
 * */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent1 = new Intent();
        intent1.setPackage("com.my_project");
        intent1.setAction("com.test_aidl.aidl");
        bindService(intent1, mConnection, BIND_AUTO_CREATE);


        final Button btn_test = findViewById(R.id.btn_test);
        final TextView tv_test = findViewById(R.id.tv_test);
        btn_test.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Random random = new Random();
                Person person = new Person("shixin" + random.nextInt(10));
                try {
                    mAidl.addPerson(person);
                    List<Person> personList = mAidl.getPersonList();
                    tv_test.setText(personList.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private IMyAidl mAidl;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //連接後拿到 Binder,轉換成 AIDL,在不同進程會返回個代理
            mAidl = IMyAidl.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mAidl = null;
        }
    };

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

這樣客戶端生成好了,可以通過客戶端發消息給服務端,親測服務端可以收到消息
在這裏插入圖片描述

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