zoukankan      html  css  js  c++  java
  • Android Service总结06 之AIDL

    Android Service总结06 之AIDL

    版本

    版本说明

    发布时间

    发布人

    V1.0

    初始版本

    2013-04-03

    Skywang

           
     

    1 AIDL介绍

        AIDL,即Android InterfaceDefinition Language
        Android使用AIDL来完成进程间通信(IPC),并且一般在服务需要接受不同应用多线程的请求时才需要使用AIDL;如果是同一个应用内的请求使用Binder实现即可;如果只是应用间通信而不是多线程处理的话使用Messenger,当然这两种情况也可以使用AIDL。本地进程和远程进程使用AIDL有所不同,本地进程内调用时会都在调用的线程内执行,远程进程使用是通过Service进程内一个由系统维护的线程池发出调用,所以可能是未知线程同时调用,需要注意线程安全问题。
     


    2 AIDL示例

     创建AIDL服务的步骤:
    (01)创建.aidl文件。        .aidl是接口文件,它定义了服务所能提供的功能。
    (02)实现.aidl所定义的接口。
    (03)将接口开放给其它应用程序。 
    

    2.1 创建.aidl文件

        (01)打开eclipse,新建工程”AIDLServiceImpl”,然后在工程的“com.text”包下创建“MyAIDLInterface.aidl”文件。
        如下图:
     
    
        (02)编辑“MyAIDLInterface.aidl”,提供doubleValue(int val)和halfValue(int value)服务。
        “MyAIDLInterface.aidl”代码如下:
    package com.test;
    
    interface MyAIDLInterface {
    
        void doubleValue(int val);
    
        void halfValue(int val);
    }
        (03)编译工程,在“gen”目录下会自动生成与“MyAIDLInterface.aidl”对应的“MyAIDLInterface.java”文件。
        如下图:
    
    
        “MyAIDLInterface.java”代码如下:
    /*
     * This file is auto-generated.  DO NOT MODIFY.
     * Original file: F:\workout\android\AIDLServiceImpl\src\com\test\MyAIDLInterface.aidl
     */
    package com.test;
    public interface MyAIDLInterface extends android.os.IInterface
    {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.test.MyAIDLInterface
    {
    private static final java.lang.String DESCRIPTOR = "com.test.MyAIDLInterface";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
    this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.test.MyAIDLInterface interface,
     * generating a proxy if needed.
     */
    public static com.test.MyAIDLInterface asInterface(android.os.IBinder obj)
    {
    if ((obj==null)) {
    return null;
    }
    android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof com.test.MyAIDLInterface))) {
    return ((com.test.MyAIDLInterface)iin);
    }
    return new com.test.MyAIDLInterface.Stub.Proxy(obj);
    }
    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_doubleValue:
    {
    data.enforceInterface(DESCRIPTOR);
    int _arg0;
    _arg0 = data.readInt();
    this.doubleValue(_arg0);
    reply.writeNoException();
    return true;
    }
    case TRANSACTION_halfValue:
    {
    data.enforceInterface(DESCRIPTOR);
    int _arg0;
    _arg0 = data.readInt();
    this.halfValue(_arg0);
    reply.writeNoException();
    return true;
    }
    }
    return super.onTransact(code, data, reply, flags);
    }
    private static class Proxy implements com.test.MyAIDLInterface
    {
    private android.os.IBinder mRemote;
    Proxy(android.os.IBinder remote)
    {
    mRemote = remote;
    }
    public android.os.IBinder asBinder()
    {
    return mRemote;
    }
    public java.lang.String getInterfaceDescriptor()
    {
    return DESCRIPTOR;
    }
    public void doubleValue(int val) throws android.os.RemoteException
    {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    _data.writeInt(val);
    mRemote.transact(Stub.TRANSACTION_doubleValue, _data, _reply, 0);
    _reply.readException();
    }
    finally {
    _reply.recycle();
    _data.recycle();
    }
    }
    public void halfValue(int val) throws android.os.RemoteException
    {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    _data.writeInt(val);
    mRemote.transact(Stub.TRANSACTION_halfValue, _data, _reply, 0);
    _reply.readException();
    }
    finally {
    _reply.recycle();
    _data.recycle();
    }
    }
    }
    static final int TRANSACTION_doubleValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_halfValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }
    public void doubleValue(int val) throws android.os.RemoteException;
    public void halfValue(int val) throws android.os.RemoteException;
    }
     

    2.2 实现.aidl所定义的接口

        (04)在“com.test”包下新建文件MyAIDLService.java,并实现doubleValue(int val)和halfValue(int value)接口。
        如下图:
    
        MyAIDLService.java的代码如下:

    package com.test;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    
    public class MyAIDLService extends Service{
        private static final String TAG = "skywang-->MyAIDLService";
    
        private MyAIDLInterface.Stub myBinder = 
                new MyAIDLInterface.Stub() {
                    
                    @Override
                    public void halfValue(int val) throws RemoteException {
                        Log.d(TAG, "halfValue val="+val/2);
                         
                    } 
                    
                    @Override
                    public void doubleValue(int val) throws RemoteException {
                        Log.d(TAG, "doubleValue val="+val*2);                    
                    }
                };
        @Override
        public void onCreate() {        
            super.onCreate();
        }
        
        @Override
        public void onDestroy(){
            super.onDestroy();
        }
        
        @Override
        public IBinder onBind(Intent intent) {
            return myBinder;
        }
    }

    (05) 定义aidl对应的manifest
    manifest内容如下:
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.test"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="9"
            android:targetSdkVersion="17" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            
            <service android:name=".MyAIDLService" android:process=":remote"> 
                <intent-filter> 
                    <action android:name="com.test.MY_AIDL_SERVICE" /> 
                </intent-filter> 
            </service>
    
        </application>
    
    </manifest>
        至此,我们已经完成了.aidl服务的定义和实现。
     

    2.3 将接口开放给其它应用程序

        (06)新建一个工程“AIDLServiceTest”,然后在工程的“com.skywang”包下创建AIDLServiceTest.java;
    (07)然后,将MyAIDLInterface.aidl文件拷贝到AIDLServiceTest工程的“com.test”包下。
        如下图:
    
    注意:.aidl所在的包名,必须和定义它的包名一样!(即MyAIDLInterface.aidl所在的定义它的工程的包为com.test;那么,调用MyAIDLInterface.aidl的程序,也必须把MyAIDLInterface.aidl放在com.test包下面)
     
        (08)AIDLServiceTest.java首先必须实现ServiceConnection接口。
        实现ServiceConnection接口的原因是:我们在后面调用.aidl服务的时候,必须通过bindService()去绑定服务;而bindService()需要用到ServiceConnection对象。
        实现ServiceConnection很简单,只需要实现两个接口:
           onServiceConnected    —— 连上服务的回调函数。一般在此函数中,获取服务对象。   
           onServiceDisconnected —— 断开服务的回调函数。可以直接返回null。
        ServiceConnection的实现代码如下:
      private MyAIDLInterface mBinder = null;
      private ServiceConnection mConnection = new ServiceConnection() {
        
          @Override 
          public void onServiceDisconnected(ComponentName name) {
              mBinder = null;    
          }
        
          @Override
          public void onServiceConnected(ComponentName name, IBinder service) {
              Log.d(TAG, "Service connected!");
              mBinder = MyAIDLInterface.Stub.asInterface(service);
          }
      };

    (09)开始访问服务之前,我们要先通过bindService()绑定服务;使用完毕之后,通过unbindService()断开服务。
    AIDLServiceTest.java代码如下:
    package com.skywang;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.Context;
    import android.content.ServiceConnection;
    import com.test.MyAIDLInterface;
    
    public class AIDLServiceTest extends Activity {
        private static final String TAG = "skywang-->AIDLServiceTest";
    
        private Button mStart = null;
        private Button mHalf = null;
        private Button mDouble = null;
        private Button mEnd = null;
        
        private MyAIDLInterface mBinder = null;
        private ServiceConnection mConnection = new ServiceConnection() {
            
            @Override 
            public void onServiceDisconnected(ComponentName name) {
                mBinder = null;    
            }
        
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG, "Service connected!");
                mBinder = MyAIDLInterface.Stub.asInterface(service);
            }
        };
        
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.aidlservice_test);        
    
            mStart = (Button) findViewById(R.id.btStart);
            mStart.setOnClickListener(new View.OnClickListener() {
                
                @Override
                public void onClick(View arg0) {
                    Log.d(TAG, "click start button");
                
                    Intent intent = new Intent("com.test.MY_AIDL_SERVICE");
                    boolean result = bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
                    if (!result) {
                        mBinder = null;
                    }
                }
            });
    
    
            mHalf = (Button) findViewById(R.id.btHalf);
            mHalf.setOnClickListener(new View.OnClickListener() {
                
                @Override
                public void onClick(View arg0) {
                    Log.d(TAG, "click half button");
    
                    try {
                        if (mBinder != null) {
                            mBinder.halfValue(10);
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
    
    
            mDouble = (Button) findViewById(R.id.btDouble);
            mDouble.setOnClickListener(new View.OnClickListener() {
                
                @Override
                public void onClick(View arg0) {
                    Log.d(TAG, "click double button");
                    
                    try {
                        if (mBinder != null) {
                            mBinder.doubleValue(10);
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
            
    
            mEnd = (Button) findViewById(R.id.btEnd);
            mEnd.setOnClickListener(new View.OnClickListener() {
                
                @Override
                public void onClick(View arg0) {
                    Log.d(TAG, "click end button");
                    
                    if (mBinder != null) {
                        unbindService(mConnection);
                        mBinder = null;
                    }
                }
            });
        }
        
    }
    
    

    3 示例演示

        程序运行效果图:
        点击“Start”按钮,Logcat如下:
    DEBUG/skywang-->AIDLServiceTest(276):click half button
    DEBUG/skywang-->AIDLServiceTest(276):Service connected!
     
        点击“Half”按钮,Logcat如下:
    DEBUG/skywang-->AIDLServiceTest(276):click half button
    DEBUG/skywang-->MyAIDLService(285):halfValue val=5
     
        点击“Double”按钮,Logcat如下:
    DEBUG/skywang-->AIDLServiceTest(276):click double button
    DEBUG/skywang-->MyAIDLService(285):doubleValue val=20
     
        点击“End”按钮,Logcat如下:
    DEBUG/skywang-->AIDLServiceTest(276):click end button

    4 参考文献

    1. Android API文档:http://developer.android.com/guide/components/aidl.html
    2. Android AIDL使用详解:http://blog.csdn.net/stonecao/article/details/6425019
    
    
    点击下载:源代码

    更多service内容:

    Android Service总结01 目录

    Android Service总结02 service介绍

    Android Service总结03 之被启动的服务 -- Started Service

    Android Service总结04 之被绑定的服务 -- Bound Service

    Android Service总结05 之IntentService

    Android Service总结06 之AIDL


     
  • 相关阅读:
    什么是级联
    @GeneratedValue
    Spring Data JPA中CrudRepository与JpaRepository的不同
    Spring Data JPA的方法命名规则
    C/S架构的渗透测试-请求加解密及测试
    各类Fuzz字典
    Nessus8.11破解
    xss实验1-20writeup
    IIS短文件名漏洞
    Linux挂载exfat文件系统的U盘
  • 原文地址:https://www.cnblogs.com/skywang12345/p/3165544.html
Copyright © 2011-2022 走看看