转载请注明出处:http://blog.csdn.net/ZhouLi_CSDN/article/details/46455071

介绍:

由于android不允许进程间访问彼此的内存空间,所以android提供了aidl来允许进程间访问。
注意:AIDL为多线程编程,因此实现aidl需要注意多线程问题。

实际过程中,aidl调用可能发生在不同的进程和线程中,一下几种情况:
* 从本地的进程调用,在调用它的线程中执行。(这种情况推荐使用binder而不是aidl)
* 远程过程调用,并且有多个线程同时调用,注意线程安全。
* 远程调用并不阻塞,发送调用方法后,立即返回。

定义AIDL接口

  1. 在src/目录下创建.aidl文件,同时给需要访问的客户端
  2. sdk工具会自动为你生成实现类,并且内部会有一个继承与Binder的Stub抽象类,你必须继承它,并实现接口。
  3. 实现一个service,覆盖onBind方法,返回Stub的实现。
  4. 你必须使用java编程语言定义接口,每一个.aidl文件只能定义一个接口,只能有接口定义。
  5. 支持的数据类型:
    • 基本数据类型
    • list和map,返回arraylist和hashmap。
  6. sdk工具会在 gen目录下生成对应的.aidl 名称的java文件。
    注意:
    • 保证多线程安全
    • 默认,远程调用是同步的,不要在主线程调用,可能导致应用无响应。
    • 没有Exceptions会返回给调用者。

使用举例:

在service中实现Stub类,并在onBind方法中返回实例。

public class RemoteService extends Service {    @Override    public void onCreate() {        super.onCreate();    }    @Override    public IBinder onBind(Intent intent) {        // Return the interface        return mBinder;    }    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {        public int getPid(){            return Process.myPid();        }        public void basicTypes(int anInt, long aLong, boolean aBoolean,            float aFloat, double aDouble, String aString) {            // Does nothing        }    };}

客户端接收binder方法:

IRemoteService mIRemoteService;private ServiceConnection mConnection = new ServiceConnection() {    // Called when the connection with the service is established    public void onServiceConnected(ComponentName className, IBinder service) {        // Following the example above for an AIDL interface,        // this gets an instance of the IRemoteInterface, which we can use to call on the service        mIRemoteService = IRemoteService.Stub.asInterface(service);    }    // Called when the connection with the service disconnects unexpectedly    public void onServiceDisconnected(ComponentName className) {        Log.e(TAG, "Service has unexpectedly disconnected");        mIRemoteService = null;    }};

在进程间传递对象
1. 类实现parcelable
2. 创建.aidl文件声明类
例如:Rect.aidl

package android.graphics;// Declare Rect so AIDL can find it and knows that it implements// the parcelable protocol.parcelable Rect;

Rect class

import android.os.Parcel;import android.os.Parcelable;public final class Rect implements Parcelable {    public int left;    public int top;    public int right;    public int bottom;    public static final Parcelable.Creator<Rect> CREATOR = newParcelable.Creator<Rect>() {        public Rect createFromParcel(Parcel in) {            return new Rect(in);        }        public Rect[] newArray(int size) {            return new Rect[size];        }    };    public Rect() {    }    private Rect(Parcel in) {        readFromParcel(in);    }    public void writeToParcel(Parcel out) {        out.writeInt(left);        out.writeInt(top);        out.writeInt(right);        out.writeInt(bottom);    }    public void readFromParcel(Parcel in) {        left = in.readInt();        top = in.readInt();        right = in.readInt();        bottom = in.readInt();    }}

调用aidl

  1. 在src/包含.aidl文件
  2. 声明一个IBinder接口
  3. 实现ServiceConnection
  4. 在onServiceConnected方法中YourInterfaceName.Stub.asInterface((IBinder)service)接收
  5. 调用方法注意 DeadObjectException异常,这是当连接异常时抛出的,仅此一个异常
  6. 断开连接 unbindService
  7. 可以参考一篇文章实例
    举例:
public static class Binding extends Activity {    /** The primary interface we will be calling on the service. */    IRemoteService mService = null;    /** Another interface we use on the service. */    ISecondary mSecondaryService = null;    Button mKillButton;    TextView mCallbackText;    private boolean mIsBound;    /** * Standard initialization of this activity. Set up the UI, then wait * for the user to poke it before doing anything. */    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.remote_service_binding);        // Watch for button clicks.        Button button = (Button)findViewById(R.id.bind);        button.setOnClickListener(mBindListener);        button = (Button)findViewById(R.id.unbind);        button.setOnClickListener(mUnbindListener);        mKillButton = (Button)findViewById(R.id.kill);        mKillButton.setOnClickListener(mKillListener);        mKillButton.setEnabled(false);        mCallbackText = (TextView)findViewById(R.id.callback);        mCallbackText.setText("Not attached.");    }    /** * Class for interacting with the main interface of the service. */    private ServiceConnection mConnection = new ServiceConnection() {        public void onServiceConnected(ComponentName className,                IBinder service) {            // This is called when the connection with the service has been            // established, giving us the service object we can use to            // interact with the service. We are communicating with our            // service through an IDL interface, so get a client-side            // representation of that from the raw service object.            mService = IRemoteService.Stub.asInterface(service);            mKillButton.setEnabled(true);            mCallbackText.setText("Attached.");            // We want to monitor the service for as long as we are            // connected to it.            try {                mService.registerCallback(mCallback);            } catch (RemoteException e) {                // In this case the service has crashed before we could even                // do anything with it; we can count on soon being                // disconnected (and then reconnected if it can be restarted)                // so there is no need to do anything here.            }            // As part of the sample, tell the user what happened.            Toast.makeText(Binding.this, R.string.remote_service_connected,                    Toast.LENGTH_SHORT).show();        }        public void onServiceDisconnected(ComponentName className) {            // This is called when the connection with the service has been            // unexpectedly disconnected -- that is, its process crashed.            mService = null;            mKillButton.setEnabled(false);            mCallbackText.setText("Disconnected.");            // As part of the sample, tell the user what happened.            Toast.makeText(Binding.this, R.string.remote_service_disconnected,                    Toast.LENGTH_SHORT).show();        }    };    /** * Class for interacting with the secondary interface of the service. */    private ServiceConnection mSecondaryConnection = new ServiceConnection() {        public void onServiceConnected(ComponentName className,                IBinder service) {            // Connecting to a secondary interface is the same as any            // other interface.            mSecondaryService = ISecondary.Stub.asInterface(service);            mKillButton.setEnabled(true);        }        public void onServiceDisconnected(ComponentName className) {            mSecondaryService = null;            mKillButton.setEnabled(false);        }    };    private OnClickListener mBindListener = new OnClickListener() {        public void onClick(View v) {            // Establish a couple connections with the service, binding            // by interface names. This allows other applications to be            // installed that replace the remote service by implementing            // the same interface.            bindService(new Intent(IRemoteService.class.getName()),                    mConnection, Context.BIND_AUTO_CREATE);            bindService(new Intent(ISecondary.class.getName()),                    mSecondaryConnection, Context.BIND_AUTO_CREATE);            mIsBound = true;            mCallbackText.setText("Binding.");        }    };    private OnClickListener mUnbindListener = new OnClickListener() {        public void onClick(View v) {            if (mIsBound) {                // If we have received the service, and hence registered with                // it, then now is the time to unregister.                if (mService != null) {                    try {                        mService.unregisterCallback(mCallback);                    } catch (RemoteException e) {                        // There is nothing special we need to do if the service                        // has crashed.                    }                }                // Detach our existing connection.                unbindService(mConnection);                unbindService(mSecondaryConnection);                mKillButton.setEnabled(false);                mIsBound = false;                mCallbackText.setText("Unbinding.");            }        }    };    private OnClickListener mKillListener = new OnClickListener() {        public void onClick(View v) {            // To kill the process hosting our service, we need to know its            // PID. Conveniently our service has a call that will return            // to us that information.            if (mSecondaryService != null) {                try {                    int pid = mSecondaryService.getPid();                    // Note that, though this API allows us to request to                    // kill any process based on its PID, the kernel will                    // still impose standard restrictions on which PIDs you                    // are actually able to kill. Typically this means only                    // the process running your application and any additional                    // processes created by that app as shown here; packages                    // sharing a common UID will also be able to kill each                    // other's processes.                    Process.killProcess(pid);                    mCallbackText.setText("Killed service process.");                } catch (RemoteException ex) {                    // Recover gracefully from the process hosting the                    // server dying.                    // Just for purposes of the sample, put up a notification.                    Toast.makeText(Binding.this,                            R.string.remote_call_failed,                            Toast.LENGTH_SHORT).show();                }            }        }    };    // ----------------------------------------------------------------------    // Code showing how to deal with callbacks.    // ----------------------------------------------------------------------    /** * This implementation is used to receive callbacks from the remote * service. */    private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {        /** * This is called by the remote service regularly to tell us about * new values. Note that IPC calls are dispatched through a thread * pool running in each process, so the code executing here will * NOT be running in our main thread like most other things -- so, * to update the UI, we need to use a Handler to hop over there. */        public void valueChanged(int value) {            mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0));        }    };    private static final int BUMP_MSG = 1;    private Handler mHandler = new Handler() {        @Override public void handleMessage(Message msg) {            switch (msg.what) {                case BUMP_MSG:                    mCallbackText.setText("Received from service: " + msg.arg1);                    break;                default:                    super.handleMessage(msg);            }        }    };}

更多相关文章

  1. 简单实现android和wp聊天
  2. Android(安卓)Wifi获取组播
  3. 使用Android(安卓)BindingAdapter与InverseBindingAdapter实现Se
  4. Android中实现Broastcast接收短信
  5. Android采用KSOAP2访问webservice
  6. 详解 Android(安卓)的 Activity 组件
  7. Android透明界面与ListView动态刷新
  8. 在Android里完美实现基站和WIFI定位
  9. 浅谈Java中Collections.sort对List排序的两种方法

随机推荐

  1. 【Android】给Android Studio设置代理
  2. Android ProgressBar控件理解
  3. Android---Hellow World
  4. android 获取手机信息工具类
  5. Android学习笔记-界面和数据存储以及一些
  6. 仿春雨医生 安卓app(android)
  7. 二、ANDROID命令详解
  8. android的启动过程
  9. android交叉编译工具链接下载
  10. 高级组件之进度条