`

关于AIDL进程间通信

 
阅读更多
一.基础知识
AIDL的作用
    在Android平台,每个应用程序App都运行在自己的进程空间。通常一 个进程不能访问另一个进程的内存空间(一个应用不能访问另一个应用),如果想沟通,需要将对象分解成操作系统可以理解的基本单元,Android提供了AIDL来处理。

    AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参 数。换句比较浅显的话来说,就是我这个App应用的activity,需要调用其他App应用的Service.当然同一App应用的activity 与service也可以在不同进程间,这可以设置Service配置中,android:process=":remote"
AIDL的使用
    官方文档特别提醒我们何时使用AIDL是必要的:只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。(太生硬了,不同进程的组件调用吧。)
那么怎么制作AIDL呢?下面步骤

    1:创建.aidl文件。新建立个文件并且以.aidl作为后缀保存,在这个文件中编写接口以及方法,这个我们普通java接口声明是一样的,不同的是要显示import 复杂类型,即便复杂类型对象在同一个包内。Java基本数据类型 (int, long, char, boolean等),String和CharSequence,集合接口类型List和Map,不需要import 。

比如:

package com.dongzi;
interface IStockQuoteService{
  double getPrice(String ticker);
}


    2:创建好AIDL文件后,刷新下工程,你会发现在gen包下,对应的包下面出现一个与AIDL文件相同的java文件。如:



/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: D:\\mywordspace\\MyPhone\\src\\com\\dongzi\\IStockQuoteService.aidl
 */
package com.dongzi;

public interface IStockQuoteService extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.dongzi.IStockQuoteService {
        private static final java.lang.String DESCRIPTOR = "com.dongzi.IStockQuoteService";

        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.dongzi.IStockQuoteService
         * interface, generating a proxy if needed.
         */
        public static com.dongzi.IStockQuoteService 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.dongzi.IStockQuoteService))) {
                return ((com.dongzi.IStockQuoteService) iin);
            }
            return new com.dongzi.IStockQuoteService.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_getPrice: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                double _result = this.getPrice(_arg0);
                reply.writeNoException();
                reply.writeDouble(_result);
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.dongzi.IStockQuoteService {
            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 double getPrice(java.lang.String ticker) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                double _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(ticker);
                    mRemote.transact(Stub.TRANSACTION_getPrice, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readDouble();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_getPrice = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public double getPrice(java.lang.String ticker) throws android.os.RemoteException;
}

AIDL工具自动生成了那么多代码,其实我们只需要知道3个就够了。

public static abstract class Stub extends android.os.Binder implements com.dongzi.IStockQuoteService 静态抽象内部类Stub

private static class Proxy implements com.dongzi.IStockQuoteService         AIDL服务代理类

public double getPrice(java.lang.String ticker) throws android.os.RemoteException;     AIDL公布出的接口,就是我们定义的接口方法
   
    3:把AIDL文件存放在其他客户端应用中,我们这个作为服务端。当然我们也可以方便的把这个应用作为客户端以及服务端。其实根本区别就是为了使调用者与被调用者在不同进程中,于是在服务中添加android:process=":remote"即可。省去了再建立应用客户端调用。

    4:AIDL只是请定义一个契约,我们这里需要一个服务来提供服务。于是建立服务MyService.

二.实战
既然我们了解一些基础知识后,现在我们开始来代码吧。假设我们需要在一个进程中调用其他应用的服务,这个服务提供一个股票价格查询,或者GPS定位的服务。

并且定义一个类,继承我们AIDL生成的Stub内部类,并实现我们AIDL定义的方法

代码如下:



package com.dongzi;

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

public class MyService extends Service {
    static final String TAG="MyService";
    
    //定义内部类MyServiceImpl继承我们的AIDL文件自动生成的内部类,
    //并且实现我们AIDL文件定义的接口方法
    private class MyServiceImpl extends IStockQuoteService.Stub{

        @Override
        public double getPrice(String ticker) throws RemoteException {
            Log.e(TAG, "getPrice");
            return 10.5;
        }
        
    }
    
    @Override
    public IBinder onBind(Intent arg0) {
        //返回AIDL实现
        return new MyServiceImpl();
    }
      
    
    @Override
    public void onDestroy(){
        Log.e(TAG, "Release MyService");
        super.onDestroy();
    }
}


我们需要在onBind方法中返回我们的AIDL接口实现对象,以便其他进程调用。

当然了,现在AIDL,以及Service都定义好了,就需要在mainfest.xml中设置

 <service android:name=".MyService"
            android:process=":remote"
            >
            <intent-filter>
                <action android:name="com.dongzi.IStockQuoteService"/>
            </intent-filter>
        </service>


在客户端服务端在同个App中,android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。

那么现在客户端来调用我们的服务了,代码如下:



package com.dongzi;

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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MYyActivity extends Activity {
      static final String TAG="MYyActivity";
       @Override
       public void onCreate(Bundle savedInstanceState){
           super.onCreate(savedInstanceState);
           setContentView(R.layout.main);
           Button btnCall=(Button)findViewById(R.id.btnCall);
           if(btnCall!=null)
               btnCall.setOnClickListener(new OnClickListener(){
                @Override
                public void onClick(View v) {
                    //绑定一个服务
                    bindMyService();
                }
               }); 
       }
       
       IStockQuoteService iService=null;
       private ServiceConnection  conn=new ServiceConnection(){
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //返回AIDL接口对象,然后可以调用AIDL方法
            iService=IStockQuoteService.Stub.asInterface(service);
            double value=0.0;
            try {
                  value=iService.getPrice("");
            }
            catch (RemoteException e) {
                Log.e(TAG,"调用出错!");
                e.printStackTrace();
            }
            Log.e(TAG, "返回数值为:"+value);
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "释放Service");
        }
       };
       
       private void bindMyService(){
           // Intent intent=new Intent("com.dongzi.IStockQuoteService");
           Intent intent=new Intent(this,MyService.class);
           startService(intent);

           bindService(intent, conn, Context.BIND_AUTO_CREATE);
       } 
}


在按钮点击时候启动service,然后再绑定这个Service.在连接到服务后,我们会发现,调用AIDL中定义的方法成了,打印如下:




项目结构为:

分享到:
评论

相关推荐

    AIDL进程间通信demo

    AIDL(Android Interface Definition Language)是Android提供的一种用于实现进程间通信的工具,它允许开发者定义接口,使得服务能够被其他应用调用,即便这些应用运行在不同的进程中。** ### AIDL简介 AIDL是一种...

    使用 AIDL实现进程间通信

    AIDL(Android Interface Definition Language)是Android提供的一种工具,用于方便开发者实现进程间通信。这篇博客“使用AIDL实现进程间通信”将深入探讨如何利用AIDL进行跨进程的交互。 首先,我们要理解AIDL的...

    AIDL进程间通信

    **AIDL(Android Interface ...总结,AIDL是Android中实现进程间通信的重要工具,它简化了跨进程服务调用的复杂性,提高了应用的交互能力。通过学习和掌握AIDL,开发者可以构建更健壮、功能更丰富的Android应用程序。

    android aidl 不同进程间通信

    下面将详细介绍Aidl在不同进程间通信中的应用及其工作原理。 **1. Android进程通信的重要性** Android系统设计时,每个应用运行在自己的进程中,为了保护应用间的隔离性和安全性。但有时我们需要让一个应用调用另一...

    AIDL进程间通信(含回调)

    使用AIDL实现进程间通信 两个工程即两个APP,实现数据共享 APP1中有个service 不停的对某一个数进行++操作, APP2通过AIDL 获取APP1的Service中的这个值(通过回调) 当然要使用AIDLAPP1中也要做相应处理

    Android AIDL进程间通信

    综上所述,AIDL是Android平台中实现进程间通信的重要手段,通过合理的使用,可以构建出高效、稳定、可扩展的应用程序。通过阅读和理解给定的`MyTestAIDL`代码资源,开发者可以更好地掌握AIDL的工作方式,为今后的...

    aidl进程间通信

    aidl跨进程通信的简单例子,有客户端和服务端。客户端绑定服务,即可发送内容到服务端。如果绑定服务失败,请添加代码:intent.setPackage("com.example.alidservice");即可

    Android AIDL进程间通信例子代码

    需要注意的是,由于进程间通信涉及到数据的序列化和反序列化,因此AIDL支持的基本数据类型有限,如int、String等。对于复杂对象的传递,需要自定义Parcelable或Serializable接口的实现。 总结来说,AIDL在Android中...

    AIDL进程间通信DEMO

    本示例"AIDL进程间通信DEMO"将深入讲解如何使用AIDL来建立两个应用程序组件之间的桥梁。 首先,我们需要了解AIDL的基本概念。AIDL允许开发者定义一个接口,这个接口将在两个进程间被实现和使用。通过AIDL定义的接口...

    学习aidl进程间通信

    **Android进程间通信(IPC):深入理解AIDL** 在Android系统中,应用程序通常运行在各自的进程中,为了实现不同应用程序间的交互,Android提供了多种进程间通信(IPC, Inter-Process Communication)方式,其中之一...

    Android使用AIDL实现进程间通信

    本篇文章将深入探讨如何在Android中使用AIDL来实现进程间通信。 首先,理解AIDL的基本概念。AIDL是一种接口定义语言,类似于Java中的接口,但它的目的是跨越进程边界。通过AIDL,我们可以定义一个接口,该接口会被...

    android aidl进程间通信

    在Android系统中,AIDL(Android Interface Definition Language)是一种用于实现进程间通信(IPC, Inter-Process Communication)的机制。AIDL允许一个应用服务在不同的进程中运行,使得其他应用能够与之交互,共享...

    Android安卓AIDL进程间通信Service简单例子

    总结来说,AIDL是Android系统中用于进程间通信的重要工具,通过它我们可以定义接口并在不同的进程中调用。服务端通过实现AIDL接口并返回`Binder`实例,客户端则通过绑定服务来获取接口并调用方法。理解并熟练掌握...

    AndroidStudio AIDL进程间通信及Binder连接池的实现

    本教程将深入探讨如何使用AIDL和Binder连接池在两个Android应用之间实现进程间通信。 **AIDL基础** AIDL是一种声明式的语言,用于定义服务接口,使得客户端和服务器端可以在不同的进程中调用对方的方法。在Android...

    Android AIDL 进程间通信

    Android进程间通信 AIDL Service 一、服务端结构 服务端需要处理的有: 1.处理对象,对象内方法,注意:AIDL 只能对函数起作用; 2.处理服务; 3.配置文件; 二、客户端 配置 1.对象,切记,与服务端的对象完全一致...

    android根据不同任务创建不同进程,并通过AIDL进行进程间通信

    本文将深入探讨如何在Android中创建多个进程以及如何通过Android Interface Definition Language (AIDL) 实现进程间通信(IPC, Inter-Process Communication)。 首先,创建不同进程主要基于以下两个原因:一是提高...

    android aidl跨进程通信

    标题“android aidl跨进程通信”指的是通过AIDL在Android上进行不同进程间的数据交换和功能调用的过程。在Android中,每个应用默认运行在自己的进程中,当需要不同应用间共享数据或调用对方的功能时,就需要借助IPC...

Global site tag (gtag.js) - Google Analytics