Android---AIDL的使用

每個應用程序都運行在自己的獨立進程中,並且可以啓動另一個應用程序的服務。在不同的進程間傳遞數據對象

一個進程不能直接訪問另一個進程的內存空間,如果想對話,則需要將對象分解成操作系統可以理解的基本單元,並且有序的通過進程邊界

首先做一個簡單的練習:不傳遞參數,啓動另一個應用程序的服務

第一步:寫服務端。
在這裏插入圖片描述
Service(服務端):
aidl:

interface StudentAIDL {
    void AIDL_Student(String data);
    String reutrnString();
}

Service:

public class MyService extends Service {

    StudentAIDL.Stub mBinder=new StudentAIDL.Stub() {
        @Override
        public void AIDL_Student() throws RemoteException {
            Log.e("TAG", "AIDL_Student");

        }
    };
    @Override
    public void onCreate() {
        Log.e("TAG", "onCreate");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.e("TAG", "onDestroy");
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e("TAG", "onBind");
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("TAG", "onUnbind");
        return super.onUnbind(intent);
    }
}

配置文件:

    <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"  設置可被其他進程調用
            android:process=":remote"> //將本地服務設置成遠程服務
            <intent-filter>
                <action android:name="asd"></action>
            </intent-filter>
        </service>

第二步,寫客戶端,將服務斷的aidl文件夾整個複製到客戶端main包下。(也可以自己寫吧,就是寫一個一模一樣的)

Client(客戶端):

    private StudentAIDL studentAIDL;
    private  ServiceConnection comn;

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

    }

    //綁定
    public void bindService(View view){

        if(comn==null) {
        	//這裏寫的是服務端的action
            Intent intent=new Intent("asd");
            //這裏的路徑是服務端aidl文件的路徑
            intent.setPackage("com.example.serviceaidl");
            comn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.e("TAG", "onServiceConnected");

                    studentAIDL = StudentAIDL.Stub.asInterface(service);
                    try {
                        //通過該對象調用在MyAIDLService.aidl文件中定義的接口方法,從而實現跨進程通信
                        studentAIDL.AIDL_Student();
                        String s = studentAIDL.reutrnString();
                        Log.e("TAG", "studentAIDL");
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.e("TAG", "onServiceDisconnected");
                }
            };
            bindService(intent, comn, BIND_AUTO_CREATE);
            Log.e("TAG", "bindService");

        }else{
            Log.e("TAG", "Service is bound");
        }
    }

    //解除綁定
    public void unbindService(View view){
        if(comn!=null) {
            unbindService(comn);
            //如果不設置null,即使解除了綁定,activity也綁定不了服務
            comn=null;

            Toast.makeText(this, "unbindservice", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this, "未bind service", Toast.LENGTH_SHORT).show();
        }
    }


    public void startService(View view){

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(comn!=null){
            unbindService(comn);
            comn=null;
        }
    }

Service:

public class ClientService extends Service {
    
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("TAG", "onBind");
        return new Binder();
    }
}

傳遞複雜參數:

服務端返回一個bean類給客戶端:

要注意的點:
在客戶端和服務端都需要有一模一樣的bean類(也可以不一樣,比如單方只有打包和解包。)

首先,先上bean類,bean類要實現Parcelable接口,如下:

public class Student implements Parcelable {


    private int id;
    private String name;

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

    public Student(Parcel in) {
        id = in.readInt();
        name = in.readString();
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    
    //將當前對象的屬性數據打成包:寫到包中
    //打包
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
    }

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

    //添加一個靜態成員,名爲Creator,該對象實現了Parcelable.Creator接口
    public static final Creator<Student> CREATOR = new Creator<Student>() {
        //解包:讀取包中的數據,並封裝成對象
        @Override
        public Student createFromParcel(Parcel in) {
            return new Student(in);
        }

        //返回一個指定大小的對象容器
        @Override
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };
    
}

然後就是aidl接口:

package com.example.serviceaidl;
import com.example.serviceaidl.Student;


// Declare any non-default types here with import statements

interface StudentAIDL {

     void AIDL_Student(String data);
     String reutrnString();
     Student getStudent();
}

aidl文件,需要創建一個和Bean類同意樣名字的aidl:
內容如下:

parcelable Student;

上面三個文件是客戶端和服務端共有的。

服務端:

Service:

public class MyService extends Service {

    StudentAIDL.Stub mBinder=new StudentAIDL.Stub() {
        @Override
        public void AIDL_Student(String data) throws RemoteException {
            Log.e("TAG", data);
        }

        @Override
        public String reutrnString() throws RemoteException {
            return "Hello,Client";
        }

        @Override
        public Student getStudent() throws RemoteException {
            return new Student(12,"Tom");
        }
    };


    @Override
    public void onCreate() {
        Log.e("TAG", "onCreate");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.e("TAG", "onDestroy");
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e("TAG", "onBind");
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("TAG", "onUnbind");
        return super.onUnbind(intent);
    }
}

客戶端

和上面的沒什麼區別,只是多調用了兩個方法

public class MainActivity extends AppCompatActivity {

    private StudentAIDL studentAIDL;
    private  ServiceConnection comn;

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

    }
    //綁定
    public void bindService(View view){

        if(comn==null) {
            Intent intent=new Intent("asd");
            intent.setPackage("com.example.serviceaidl");
            comn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.e("TAG", "onServiceConnected");
                    // 從連接中獲取Stub對象
                    studentAIDL = StudentAIDL.Stub.asInterface(service);
                    try {
                        //通過該對象調用在MyAIDLService.aidl文件中定義的接口方法,從而實現跨進程通信
                        studentAIDL.AIDL_Student("hello world");
                        String s = studentAIDL.reutrnString();
                        Student student = studentAIDL.getStudent();
                        Log.e("TAG", student.getName()+"----------"+student.getId());
                        Log.e("TAG", s+"");
                        Log.e("TAG", "studentAIDL");
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.e("TAG", "onServiceDisconnected");
                }
            };
            bindService(intent, comn, BIND_AUTO_CREATE);
            Log.e("TAG", "bindService");

        }else{
            Log.e("TAG", "Service is bound");
        }
    }

    //解除綁定
    public void unbindService(View view){
        if(comn!=null) {
            unbindService(comn);
            //如果不設置null,即使解除了綁定,activity也綁定不了服務
            comn=null;

            Toast.makeText(this, "unbindservice", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this, "未bind service", Toast.LENGTH_SHORT).show();
        }
    }


    public void startService(View view){

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(comn!=null){
            unbindService(comn);
            comn=null;
        }
    }
}

Service:

public class ClientService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        Log.e("TAG", "onBind");
        return new Binder();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章