Android AIDL 实现过程

Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure CallRPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition LanguageIDL)来公开服务的接口。我们知道4Android应用程序组件中的3个(ActivityBroadcastReceiverContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDLAndroid Interface Definition Language)服务。

 

Aidl文件所在的包名和文件名要相同:

 

 

应为用到了parcelable接口,这里先说说它: 

Parcelable接口

Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE本身就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。

注:Android中Intent传递对象有两种方法:一是Bundle.putSerializable(Key,Object),另一种是Bundle.putParcelable(Key,Object)。当然这些Object是有一定的条件的,前者是实现了Serializable接口,而后者是实现了Parcelable接口。

 

HarlaInfo.Java:

package com.harlan.demo.aidl;

 

import android.os.Parcel;

import android.os.Parcelable;

 

public class HarlanInfo implements Parcelable {

private String name;

 

private int age;

 

private String place;

 

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;

}

 

public String getPlace() {

return place;

}

 

public void setPlace(String place) {

this.place = place;

}

 

public HarlanInfo() {

 

}

 

public HarlanInfo(Parcel parcel) {

this.name = parcel.readString();

this.age = parcel.readInt();

this.place = parcel.readString();

 

}

 

public int describeContents() {

return 0;

}

 

/**

 * 将对象序列化为一个Parcel对象 可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,

 * 再通过createFromParcel从流里读取对象 注意:写的顺序和读的顺序必须一致。

 */

public void writeToParcel(Parcel parcel, int arg1) {

parcel.writeString(name);

parcel.writeInt(age);

parcel.writeString(place);

}

 

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

public HarlanInfo createFromParcel(Parcel parcel) {

HarlanInfo harlan=new HarlanInfo(parcel);

return harlan;

}

 

@Override

public HarlanInfo[] newArray(int size) {

// TODO Auto-generated method stub

return new HarlanInfo [size];

}

 

};

 

HarlanInfo.aidl

package com.harlan.demo.aidl;

parcelable HarlanInfo;

 

 

 

 

定义一个aidl文件,使client端利用回调拿到serviceparam参数;然后设置到toast上显示出来。

ICallBack.aidl:

 

package com.harlan.demo.aidl;

interface ICallBack{

void handleByServer(String param);

}

 

 

 

定义这个aidl文件,使clientharlanInfoclient)传数据和到serviceservice用harlanInfoservice)取得数据;

ExecuteServiceAIDL.aidl

package com.harlan.demo.aidl;

import com.harlan.demo.aidl.HarlanInfo;

import com.harlan.demo.aidl.ICallBack;

interface ExecuteServiceAIDL

{

/**

 *get info from server and 

 *Transfer a callback methods handle;

 *if occur error ,will be return null

 *对于非基本数据类型和StringCharSequence类型,要加上方向指示

 *包括inoutinout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。

     */

HarlanInfo getServerHarlanInfo(in HarlanInfo info,ICallBack icallback);

}

 

 

ClientActivity.java:

package com.harlan.demo.activity;

 

import android.app.Activity;

import android.content.ComponentName;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.Bundle;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.Toast;

 

import com.harlan.demo.aidl.ExecuteServiceAIDL;

import com.harlan.demo.aidl.HarlanInfo;

import com.harlan.demo.aidl.ICallBack;

 

public class ClientActivity extends Activity

{

    public static final String TAG = "ClientActivity";

    

    private static final String BIND_ACTION = "com.harlan.demo.aidl.service";

    

    private EditText mEditTextName;

    

    private EditText mEditTextAge;

    

    private EditText mEditTextPlace;

    

    private Button mButtonCommit;

    

    private ExecuteServiceAIDL executeService;

    

    @Override

    protected void onCreate(Bundle savedInstanceState)

    {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_client);

        getView();

        mButtonCommit.setOnClickListener(new View.OnClickListener()

        {

            

            @Override

            public void onClick(View v)

            {

                getServiceConnect();

                

            }

        });

    }

        

    private void getView()

    {

        mEditTextName = (EditText)findViewById(R.id.editText_name);

        mEditTextAge = (EditText)findViewById(R.id.editText_age);

        mEditTextPlace = (EditText)findViewById(R.id.editText_place);

        mButtonCommit = (Button)findViewById(R.id.button_commit);

    }

    

    private void getServiceConnect()

    {

        Intent it = new Intent();

        it.setAction(BIND_ACTION);

        startService(it);

        bindService(it, mserviceConnection, BIND_AUTO_CREATE);

    }

    

    ServiceConnection mserviceConnection = new ServiceConnection()

    {

        

        @Override

        public void onServiceDisconnected(ComponentName name)

        {

            Log.d(TAG, "onServiceDisconnected");

            

        }

        

        @Override

        public void onServiceConnected(ComponentName name, IBinder service)

        {

            Log.d(TAG, "onServiceConnected");

            executeService = ExecuteServiceAIDL.Stub.asInterface(service);

            if (executeService != null)

            {

                handlerInfo();

            }

        }

    };

    

    private void handlerInfo()

    {

        String mName;

        int mAge;

        String mPlace;

        if (mEditTextName.getText().toString().equals(""))

        {

            mName = "孤独";

        }

        else

        {

            mName = mEditTextName.getText().toString();

        }

        if (mEditTextAge.getText().toString().equals(""))

        {

            mAge = 23;

        }

        else

        {

            mAge = Integer.parseInt(mEditTextAge.getText().toString());

        }

        if (mEditTextPlace.getText().toString().equals(""))

        {

            mPlace = "世界";

        }

        else

        {

            mPlace = mEditTextPlace.getText().toString();

        }

        //将数据传到harlanInfo中  

        HarlanInfo mInfo = new HarlanInfo();

        mInfo.setName(mName);

        mInfo.setAge(mAge);

        mInfo.setPlace(mPlace);

        try

        {

            HarlanInfo serverInfo = new HarlanInfo();

            serverInfo = executeService.getServerHarlanInfo(mInfo, mCallBack);

            //拿到service传回的数据

            mEditTextName.setText(serverInfo.getName());

            mEditTextAge.setText(String.valueOf(serverInfo.getAge()));

            mEditTextPlace.setText(serverInfo.getPlace());

            unbindService(mserviceConnection);

        }

        catch (RemoteException e)

        {

            e.printStackTrace();

        }

    }

    

    ICallBack.Stub mCallBack = new ICallBack.Stub()

    {

        

        @Override

        public void handleByServer(String param)

            throws RemoteException

        {

            Toast.makeText(getApplicationContext(), param, Toast.LENGTH_LONG).show();

            

        }

    };

    

}

 

 

 

AIDLService.Java:

package com.harlan.demo.service;

 

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

 

import com.harlan.demo.aidl.ExecuteServiceAIDL;

import com.harlan.demo.aidl.HarlanInfo;

import com.harlan.demo.aidl.ICallBack;

 

public class AIDLService extends Service

{

    public static final String TAG = "AIDLService";

    

    private ICallBack mCallBack;

    

    /**

     * 绑定服务

     */

    @Override

    public IBinder onBind(Intent intent)

    {

        // TODO Auto-generated method stub

        return mBinder;

    }

    

    /**

     * 创建服务

     */

    @Override

    public void onCreate()

    {

        super.onCreate();

    }

 

    /**

     * 销毁服务

     */

    @Override

    public void onDestroy()

    {

        super.onDestroy();

    }

 

    /**

     * 启动服务

     */

    @Override

    public void onStart(Intent intent, int startId)

    {

        super.onStart(intent, startId);

    }

 

    /**

     * 解绑服务

     */

    @Override

    public boolean onUnbind(Intent intent)

    {

        mCallBack = null;

        return super.onUnbind(intent);

    }

    

    ExecuteServiceAIDL.Stub mBinder = new ExecuteServiceAIDL.Stub()

    {

        @Override

        public HarlanInfo getServerHarlanInfo(HarlanInfo info, ICallBack icallback)

            throws RemoteException

        {

            Log.d(TAG,"getServerHarlanInfo");

            mCallBack = icallback;

//传参数给client

            mCallBack.handleByServer("The msg is from server");

            HarlanInfo newInfo = new HarlanInfo();

//通过HarlanInfo序列化数据 再传给client

            newInfo.setName(info.getName()+"幸福");

            newInfo.setAge(info.getAge() + 10);

            newInfo.setPlace(info.getPlace()+"Home");

            return newInfo;

        }

    };

    

}

 

 

效果图,布局文件自己写

 

 

 ps:本人也是参考别人的例子写的,中间有解释不对的地方,望轻喷。。。。

 

posted @ 2015-07-29 19:58  手酒刘  阅读(1065)  评论(0编辑  收藏  举报