Android中AIDL的实现使用

AIDL简介

AIDL即Android接口描述语言,用于跨进程之间的数据通信。关于其详细的信息可以网上搜,相关内容还是蛮多的。

基本类型的AIDL

AIDL支持的6中基本类型
byte,double,float,int,long,String
现在我们来实现AIDL的方法吧
1.实现*.aidl文件
IAIDLTest.aidl

   
package com.pachongzhang.myservice;

interface IAIDLTest {
    int add(int a, int b);
}

aidl文件的生成与一个接口类(interface)类的实现差不多,首先声明其所在的包名,然后定义其接口类,只是少了public,private这些属性,并且其支持的类型比较少。那我们要实现自定义类用于参数传递,我们就需要让自定义类实现Parcelable接口。下面我们来看下自定义类的AIDL的实现。

自定义类的AIDL

自定义类实现Parcelable,我们需要创建两个文件,.java和.aidl,下面举一个具体的实例。
CustomParcelable.java

   
package com.pachongzhang.myservice;

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

public class CustomParcelable implements Parcelable {

    private int a;
    private String b;

    public CustomParcelable(Parcel source) {
        this.a = source.readInt();
        this.b = source.readString();
    }

    public CustomParcelable(int a, String b) {
        this.a = a;
        this.b = b;
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

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

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

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {

        @Override
        public CustomParcelable createFromParcel(Parcel source) {
            return new CustomParcelable(source);
        }

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

}

CustomParcelable.aidl

   
package com.pachongzhang.myservice;

parcelable CustomParcelable;

从CustomParcelable.java可知其主要用于自定义类的实现方法,CustomParcelable.aidl用于其在AIDL的声明,那么我们要怎么样才能使用这个自定义类呢。
IAIDLTest.aidl

   
package com.pachongzhang.myservice;

import com.pachongzhang.myservice.CustomParcelable;

interface IAIDLTest {
    int add(int a, int b);
    void getCustom(in CustomParcelable custom);
}

从代码中我们可以看到IAIDLTest.aidl文件多了import com.pachongzhang.myservice.CustomParcelable;一个这样的声明,这个就是我们自己定义的那个类,有了这个声明我们就可以在.aidl文件中使用CustomParcelable这个类了,同时要注意的两点就是我们定义了CustomParcelable.java文件还是声明其CustomParcelable.aidl文件,其次是做为参数传递时要声明其是in还是out的方式表示其是输入参数还是输出参数。
说了这么多,我们看下具体的使用吧

AIDL的实践

Service端

首先,我们看service端的实现
代码结构
这里写图片描述
从Myservice的结构中,我们已经实现了CustomParcelable.java,CustomParcelable.aidl和IAIDLTest.aidl,下面我就看下MyService.java和AndroidManifest.xml。
MyService.java

   
package com.pachongzhang.myservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MyService extends Service{

    protected static final String TAG = "MyService";

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private Binder mBinder = new IAIDLTest.Stub() {

        @Override
        public int add(int a, int b) throws RemoteException {
            return (a+b);
        }

        @Override
        public void getCustom(CustomParcelable custom) throws RemoteException {
            Log.d(TAG,"getCustom:"+custom.getA()+",getB:"+custom.getB());
        }
    };

    @Override
    public void onDestroy() {
        mBinder = null;
    }
}

从MyService.java中我们可以看到我们实现了IAIDLTest.Stub()类,这个类就是用于接口数据传递及其实现,可以看到我们实现了add和getCustom方法。然后通过onBind把IAIDLTest.Stub()对象传递给别的进程,已使其调用MyService 里的方法。我们定义了服务自然而然就要在AndroidManifest.xml中声明。
AndroidManifest.xml

   
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.pachongzhang.myservice"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
       <service android:name="com.pachongzhang.myservice.MyService" >
            <intent-filter>
                <action android:name="com.pachongzhang.myservice.MyService.start" />
            </intent-filter>
        </service>
    </application>
</manifest>

可以看到我们声明了MyService服务,并定义了一个action=”com.pachongzhang.myservice.MyService.start”方便别的进程启动本服务。下面来看下Client端访问本服务的方法。

Client端

Client端的代码结构
这里写图片描述
从结构中我们知道,我们要把那些接口类都搬过来,如果使用了自定义类,还要把自定义的类的java和aidl文件搬过来。所以这么我们就只需要看下MainActivity.java和activity_main.xml的实现了。先来看下Client端实现的效果吧。
这里写图片描述
这里我们通过调用Service的add方法实现了加法运算。并且通过getCustom打印了对应的信息
这里写图片描述
效果看过后我们看MainActivity.java和activity_main.xml的实现吧。
activity_main.xml

   
<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" >

    <EditText
        android:id="@+id/id_edit_num1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="number" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="+" />

    <EditText
        android:id="@+id/id_edit_num2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="number" />

    <Button
        android:id="@+id/id_btn_equal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="=" />

    <EditText
        android:id="@+id/id_edit_num3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:editable="false" />

</LinearLayout>

MainActivity.java

   
package com.pachongzhang.myclient;

import com.pachongzhang.myservice.CustomParcelable;
import com.pachongzhang.myservice.IAIDLTest;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {

    private static final String SERVICE_START = "com.pachongzhang.myservice.MyService.start";

    private EditText mEditNum1;
    private EditText mEditNum2;
    private EditText mEditNum3;
    private Button mBtnEqual;
    private IAIDLTest mService;

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

        initView();
        bindService(true);
    }

    @Override
    protected void onDestroy() {
        bindService(false);
        super.onDestroy();
    }

    private void bindService(boolean isBind){
        if (isBind) {
            Intent intent = new Intent(SERVICE_START);
            bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        } else {
            if (mServiceConnection != null) {
                unbindService(mServiceConnection);
                mServiceConnection = null;
            }
        }
    }

    private void initView() {
        mEditNum1 = (EditText) findViewById(R.id.id_edit_num1);
        mEditNum2 = (EditText) findViewById(R.id.id_edit_num2);
        mEditNum3 = (EditText) findViewById(R.id.id_edit_num3);
        mBtnEqual = (Button) findViewById(R.id.id_btn_equal);

        mBtnEqual.setOnClickListener(this);
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {

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

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IAIDLTest.Stub.asInterface(service);
        }
    };


    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.id_btn_equal) {
            int num1 = Integer.valueOf(mEditNum1.getText().toString());
            int num2 = Integer.valueOf(mEditNum2.getText().toString());
            try {
                int num3 = mService.add(num1, num2);
                mEditNum3.setText(num3+"");

                CustomParcelable customParcelable = new CustomParcelable(num3, "Success");
                mService.getCustom(customParcelable);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
}

MainActivity.java的实现也是比较简单的,就简单介绍下,通过bindService获得远程服务的binder,然后通过它就可以调用那些接口了。

Android自定义类序列化

Android序列化一般是用于对象的传递的,因为在Android中一些自定义类对象是不能直接传递的,需要序列化。那我们来看看有哪些序列化的方式,Serializable是java提供的,Parcelable是Android提供的,相对来说Serializable的实现要简单很多,但Parcelable的效率要比Serializable高,可以参考这篇文章Android系统中Parcelable和Serializable的区别。下面我们来看下Parcelable和Serializable的简单实现。

Parcelable

MyParcelable.java

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

public class MyParcelable implements Parcelable{

    private int a;
    private String b;

    public MyParcelable(Parcel source) {
        this.a = source.readInt();
        this.b = source.readString();
    }

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

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

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {

        @Override
        public MyParcelable createFromParcel(Parcel source) {
            return new MyParcelable(source);
        }

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


    };

}

Serializable

MySerializable.java

   
import java.io.Serializable;

public class MySerializable implements Serializable {
    private static final long serialVersionUID = 6285493298229159093L;

    private int a;
    private String b;

}

从上面两个简单类里我们可以看出Parcelable要比Serializable 复杂的多,但是效率上正好相反。所以在使用上还是推荐使用Parcelable。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值