服务 远程服务 AIDL 进程间通讯 IPC 深化

时间:2024-05-09 15:34:25

示例
服务 远程服务 AIDL 进程间通讯 IPC 深化
服务 远程服务 AIDL 进程间通讯 IPC 深化服务 远程服务 AIDL 进程间通讯 IPC 深化

aidl接口文件
package com.bqt.aidlservice.aidl;
parcelable Person; 

package com.bqt.aidlservice.aidl;
parcelable Salary;  

package com.bqt.aidlservice.aidl;
import com.bqt.aidlservice.aidl.Salary;  
import com.bqt.aidlservice.aidl.Person;
interface IBinderInterface {
     void callMethodInService();
     String queryPerson(int num);
    //定义一个Person对象作为传入参数。接口中定义方法时,需要制定新参的传递模式,这里是传入,所以前面有一个【in】
    Salary getMsg(in Person owner);  
}

Bean1
package com.bqt.aidlservice.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
    public String name;
    public Person(String name) {
        this.name = name;
    }
    @Override
    public int hashCode() {
        return name.hashCode();
    }
    @Override
    public boolean equals(Object o) {
        if (o instanceof Person) {
            return name.equals(((Person) o).name);
        } else {
            return false;
        }
    }

    @Override
    public int describeContents() { //实现Parcelable必须实现的方法,不知道拿来干嘛的,直接返回0就行了
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) { //把对象所包含的数据写入到parcel中
        dest.writeString(name);//可以write各种类型的数据
    }
    //必须提供一个名为【CREATOR】的static final属性,该属性需要实现android.os.Parcelable.Creator<T>接口
    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel source) {
            return new Person(source.readString());//从Parcel中读取数据,返回Person对象,和构造方法中的参数列表相对应
        }
        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

Bean2
package com.bqt.aidlservice.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Salary implements Parcelable {
    public String type;
    public Integer salary;
    public Salary(String type, Integer salary) {
        this.type = type;
        this.salary = salary;
    }
    public String toString() {
        return "工作:" + type + "    薪水: " + salary;
    }

    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(type);
        dest.writeInt(salary);
    }
    public static final Parcelable.Creator<Salary> CREATOR = new Parcelable.Creator<Salary>() {
        //从Parcel中读取数据,返回Person对象
        @Override
        public Salary createFromParcel(Parcel source) {
            return new Salary(source.readString(), source.readInt());
        }
        @Override
        public Salary[] newArray(int size) {
            return new Salary[size];
        }
    };
}

自动生成的Java接口文件
/*
 * This file is auto-generated. DO NOT MODIFY. Original file:
 * D:\\workspace_bqt\\
 * Զ�̷���\\src\\com\\bqt\\aidlservice\\aidl\\IBinderInterface.aidl
 */
package com.bqt.aidlservice.aidl;
public interface IBinderInterface extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.bqt.aidlservice.aidl.IBinderInterface {
        private static final java.lang.String DESCRIPTOR = "com.bqt.aidlservice.aidl.IBinderInterface";
        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.bqt.aidlservice.aidl.IBinderInterface interface,
         * generating a proxy if needed.
         */
        public static com.bqt.aidlservice.aidl.IBinderInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.bqt.aidlservice.aidl.IBinderInterface))) {
                return ((com.bqt.aidlservice.aidl.IBinderInterface) iin);
            }
            return new com.bqt.aidlservice.aidl.IBinderInterface.Stub.Proxy(obj);
        }
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_callMethodInService: {
                data.enforceInterface(DESCRIPTOR);
                this.callMethodInService();
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_queryPerson: {
                data.enforceInterface(DESCRIPTOR);
                int _arg0;
                _arg0 = data.readInt();
                java.lang.String _result = this.queryPerson(_arg0);
                reply.writeNoException();
                reply.writeString(_result);
                return true;
            }
            case TRANSACTION_getMsg: {
                data.enforceInterface(DESCRIPTOR);
                com.bqt.aidlservice.aidl.Person _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.bqt.aidlservice.aidl.Person.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                com.bqt.aidlservice.aidl.Salary _result = this.getMsg(_arg0);
                reply.writeNoException();
                if ((_result != null)) {
                    reply.writeInt(1);
                    _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }
        private static class Proxy implements com.bqt.aidlservice.aidl.IBinderInterface {
            private android.os.IBinder mRemote;
            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }
            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }
            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }
            @Override
            public void callMethodInService() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_callMethodInService, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override
            public java.lang.String queryPerson(int num) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.lang.String _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(num);
                    mRemote.transact(Stub.TRANSACTION_queryPerson, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readString();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
            //定义一个Person对象作为传入参数。接口中定义方法时,需要制定新参的传递模式,这里是传入,所以前面有一个【in】
            @Override
            public com.bqt.aidlservice.aidl.Salary getMsg(com.bqt.aidlservice.aidl.Person owner) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                com.bqt.aidlservice.aidl.Salary _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((owner != null)) {
                        _data.writeInt(1);
                        owner.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_getMsg, _data, _reply, 0);
                    _reply.readException();
                    if ((0 != _reply.readInt())) {
                        _result = com.bqt.aidlservice.aidl.Salary.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
        static final int TRANSACTION_callMethodInService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_queryPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_getMsg = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    }
    public void callMethodInService() throws android.os.RemoteException;
    public java.lang.String queryPerson(int num) throws android.os.RemoteException;
    //定义一个Person对象作为传入参数。接口中定义方法时,需要制定新参的传递模式,这里是传入,所以前面有一个【in】
    public com.bqt.aidlservice.aidl.Salary getMsg(com.bqt.aidlservice.aidl.Person owner) throws android.os.RemoteException;
}

远程Service
public class MyRemoteService extends Service {
    private String[] names = { "B神", "艹神", "基神", "J神", "翔神" };
    private static Map<Person, Salary> map = new HashMap<Person, Salary>();
    static {
        map.put(new Person("包青天"), new Salary("码农", 20000));
        map.put(new Person("白乾涛"), new Salary("歌手", 1000));
        map.put(new Person("baiqiantao"), new Salary("学生", 50));
        map.put(new Person("bqt"), new Salary("老师", 8000));
    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("bqt", "onBind");
        return new MyBinder();
    }

    /**无参无返回值的方法*/
    private void methodInService() {
        Log.i("bqt", "服务里的方法被调用了……");
    }
    /**基本类型有返回值方法*/
    private String query(int num) {
        if (num >= 0 && num < 5) {
            return names[num];
        }
        return "尼玛,只能传0-4";
    }
    /**传递复杂数据*/
    private Salary getPersonSalary(Person person) throws RemoteException {
        Salary salary = map.get(person);//对于Hash系列的集合,是先判断对象的【hashCode】返回值是否相同,再判断对象的【equals】返回值是否为true
        if (salary != null) {
            return salary;
        } else {
            return new Salary("木有工作", 0);
        }
    }

    private class MyBinder extends Stub {//不是由【extends Binder implements IBinderInterface】改为【extends IBinderInterface.Stub】而是改为【extends Stub】
        @Override
        public void callMethodInService() throws RemoteException {
            methodInService();
        }
        @Override
        public String queryPerson(int num) throws RemoteException {
            return query(num);
        }
        @Override
        public Salary getMsg(Person person) throws RemoteException {
            return getPersonSalary(person);
        }
    }
}

清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.bqt.aidlservice"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />
    <!-- 声明权限 -->
    <permission
        android:name="com.bqt.permission"
        android:protectionLevel="normal" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 指定激活此Service需要的权限 -->
        <service
            android:name=".MyRemoteService"
            android:permission="com.bqt.permission" >
            <intent-filter>
                <action android:name="com.bqt.service.REMOTE_SERVICE" />
            </intent-filter>
        </service>
    </application>
</manifest>

调用者Activity
public class MainActivity extends ListActivity {
    public static final String ACTION_REMOTE_SERVICE = "com.bqt.service.REMOTE_SERVICE";
    private MyServiceConnection conn;
    private IBinderInterface mIBinder;
    public static final String[] personNames = { "包青天", "白乾涛", "baiqiantao", "bqt", "O(∩_∩)O哈哈~" };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        List<String> mData = new ArrayList<String>(Arrays.asList("bindService绑定服务", "unbindService取消绑定服务"//
                , "调用无参无返回值的方法", "调用基本类型有返回值方法", "传递复杂数据"));
        setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mData));
        conn = new MyServiceConnection();
    }
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        if (position == 0) {
            bindService(new Intent(ACTION_REMOTE_SERVICE), conn, BIND_AUTO_CREATE);
        } else if (position == 1) {
            unbindService(conn);
            mIBinder = null;
        } else {
            if (mIBinder == null) {
                Toast.makeText(this, "还没绑定呦", Toast.LENGTH_SHORT).show();
                return;
            }
            try {
                switch (position) {
                case 2:
                    mIBinder.callMethodInService();
                    break;
                case 3:
                    Toast.makeText(this, "查询结果为:" + mIBinder.queryPerson(new Random().nextInt(6)), Toast.LENGTH_SHORT).show();
                    break;
                case 4:
                    Toast.makeText(this, mIBinder.getMsg(new Person(personNames[new Random().nextInt(5)])).toString(), Toast.LENGTH_SHORT).show();
                    break;
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
    private class MyServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIBinder = IBinderInterface.Stub.asInterface(service);
            Toast.makeText(MainActivity.this, "服务已连接", Toast.LENGTH_SHORT).show();
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    }
}

调用者清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.bqt.bindremote"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <!-- 声明使用指定的权限 -->
    <uses-permission android:name="com.bqt.permission" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.bqt.bindremote.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

附件列表