美文网首页Android Coding
使用AIDL(二)传递数据

使用AIDL(二)传递数据

作者: 李俊的博客 | 来源:发表于2016-07-27 20:04 被阅读468次

    AIDL默认支持的数据类型

    IData.aidl

    package jun.server;
    
    // Declare any non-default types here with import statements
    
    interface IBaseData {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        // 不支持short类型
        void basicTypes(byte aByte, int anInt, long aLong,
                boolean aBoolean,
                float aFloat, double aDouble,
                char aChar,
                String aString, CharSequence aCharSequence,
                inout List<String> aList);
    }
    

    除short外的Java八大基本数据类型,String、CharSequence、包含前面支持的数据类型的List。

    传递自定义数据类型

    1、服务端

    1)创建自定义数据类型Person类必须继承Parcelable,这样对象才能使用于传输或存储。
    app/src/main/java/jun.server.model/Person.java

    public class Person implements Parcelable {
    
        private String name;
        private int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public Person(Parcel source) {
    
            this.name = source.readString();
            this.age = source.readInt();
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
    
            dest.writeString(name);
            dest.writeInt(age);
        }
    
        public static final Creator<Person> CREATOR = new Creator<Person>() {
            @Override
            public Person createFromParcel(Parcel source) {
                return new Person(source);
            }
    
            @Override
            public Person[] newArray(int size) {
                return new Person[size];
            }
        };
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    

    2)创建Person类对应的AIDL文件
    app/src/main/aidl/jun.server.model/Person.aidl

    // Person.aidl
    package jun.server.model;
    
    // Declare any non-default types here with import statements
    
    parcelable Person;
    

    3)创建AIDL接口文件
    ICustomData.aidl

    // ICustomData.aidl
    package jun.server;
    
    // Declare any non-default types here with import statements
    
    // 注意:Person.aidl和Person.java的位置要一致
    // 需要导入自定义数据的类型
    import jun.server.model.Person;
    
    interface ICustomData {
    
        List<Person> add(in Person person);
    }
    

    其中add(in Person person)里面有个in这是什么意思?
      首先Person在发送方发送之前作为输出需要进行打包才能够传输,然后在接收方收到后作为输入需要进行拆包还原。而无论是打包还是拆包都非常消耗资源,所以如果只是作为输入那就是in,只是作为输出就是out,同时作为输入输出就是inout。这里由于Person是从客户端传过来的,所以是作为输入也就是in。

    4)创建服务
    RemoteService.java

    /**
     * 远程Service
     */
    public class RemoteService extends Service {
        
        private ArrayList<Person> persons;
    
        // 解释:Stub是继承Binder的
        ICustomData.Stub mBinder = new ICustomData.Stub() {
    
            @Override
            public List<Person> add(Person person) throws RemoteException {
                persons.add(person);
                return persons;
            }
        };
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            persons = new ArrayList<>();
            return mBinder;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            // 服务销毁前将Binder置空,方便垃圾回收器回收资源。
            mBinder = null;
        }
    }
    

    5)记得注册Service

    <service android:name=".RemoteService">
        <intent-filter>
            <action android:name="jun.server.RemoteService"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </service>
    
    2、客户端

    1)直接将服务端的Person.aidl、ICustomData.aidl和Person.java拷贝到客户端
    app/src/main/aidl/jun.server.model/Person.aidl
    app/src/main/aidl/jun.server/ICustomData.aidl
    app/src/main/java/jun.server.model/Person.java
    注意:包名一样。
      2)创建Activity的布局
    activity_main.xml

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <Button
            android:id="@+id/bind_service"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="绑定服务"/>
    
        <Button
            android:id="@+id/unbind_service"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="解除绑定"/>
    
        <Button
            android:id="@+id/invoke_method"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="调用远程服务的方法"/>
    </LinearLayout>
    

    3)在Activity中绑定远程服务并调用它的方法

    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
    
        private ICustomData mICustomData;
    
        private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                // 拿到远程服务的代理
                mICustomData = ICustomData.Stub.asInterface(service);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mICustomData = null;
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            findViewById(R.id.bind_service).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 设置Intent目标是jun.server包的RemoteService
                    Intent intent = new Intent("jun.server.RemoteService");
                    intent.setPackage("jun.server");
                    bindService(intent, serviceConnection, BIND_AUTO_CREATE);
                    Toast.makeText(MainActivity.this, "已绑定服务", Toast.LENGTH_SHORT).show();
                }
            });
    
            findViewById(R.id.unbind_service).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (serviceConnection != null) {
                        unbindService(serviceConnection);
                        // 解除绑定时需要回收mIStudent连接资源
                        mICustomData = null;
                        Toast.makeText(MainActivity.this, "已解除绑定", Toast.LENGTH_SHORT).show();
                    }
                }
            });
    
            findViewById(R.id.invoke_method).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mICustomData != null) {
                        try {
                            List<Person> persons = mICustomData.add(new Person("Tom", 18));
                            Log.i(TAG, persons.toString());
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    } else {
                        Toast.makeText(MainActivity.this, "请先绑定服务", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }
    
    3、运行

    先运行服务端再运行客户端,点击“绑定服务”按钮让客户端绑定服务端的服务,再点击“调用远程服务的方法”按钮调用服务端的getName()方法,最后点击“解除绑定”按钮解除绑定。运行结果如下:

    I/MainActivity: [Person{name='Tom', age=18}]
    

    参考

    墨客网:AIDL-小白成长记(视频教程)

    相关文章

      网友评论

        本文标题:使用AIDL(二)传递数据

        本文链接:https://www.haomeiwen.com/subject/ahbojttx.html