美文网首页
三十一、跨进程调用Service(AIDL服务)

三十一、跨进程调用Service(AIDL服务)

作者: 清梦星河哈 | 来源:发表于2019-08-28 15:45 被阅读0次
AIDL服务简介

Android的远程Service调用与Java的RMI基本相似,一样都是先定义一个远程调用接口,然后为该接口提供一个实现类即可。

与RIM不同的是,客户端访问Service时,Android并不是直接返回Service对象给客户端——这一点绑定本地Service时已经看到,Service只是将一个回调对象(IBinder对象)通过onBind()方法返回给客户端。因此Android的AIDL远程接口的实现类就是那个IBinder实现类。

与绑定本地Service不同的是,本地Service的onBind()方法会直接把IBinder对象本身传给客户端的ServiceConnention的onServiceConnected方法的第二个参数。但远程Service的onBind()方法只是将IBinder对象的代理传给客户端的ServiceConnection的onServiceConnected方法的第二个参数。

当客户端获取了远程Service的IBinder对象的代理之后,接下来就通过该IBinder对象去调用远程Service的属性或方法了。

创建AIDL文件

AIDL的语法与Java接口很相似,但存在如下差异:

1.AIDL定义接口的源代码必须以.aidl结尾
2.AIDL接口中用到的数据类型,除了基本类型、String、List、Map、CharSequence之外,其他类型全部都需要导包,即使他们在同一个包中也需要导包。

开发人员定义的AIDL接口只是定义了进程之间的通信接口,Service端、客户端都需要使用Android SDK安装目录下的platform-tools子目录下的aidl.exe工具为该接口提供实现。如果开发者使用ADT工具进行开发,那么ADT工具会自动为该AIDL接口生成实现。

Android Studio直接右键--new--AIDL--AIDL File

package com.hello.myandroidtest.service;

interface ICat {

    String getColor();

    double getWeight();
}

定义好上面的接口后,ADT工具会自动生成一个ICat.Java接口,在该接口里包含一个Stub内部类,该内部类实现了IBinder、ICat两个接口,这个Stub类将会作为远程Service的回调类——它实现了IBinder接口,因此可作为Service的onBinder()方法返回值。

将接口暴露给客户端

上一步定义好AIDL接口之后,接下来就可定义一个Service实现类了,该Service的onBind()方法所返回的IBinder对象应该是应该是ADT所生成的ICat.Stub的子类的实例。至于其他部分,则与开发本地Service完全一样。

public class AidlService extends Service {

    private CatBinder catBinder;

    Timer timer = new Timer();

    String[] colors = new String[]{
        "红色",
        "黄色",
        "黑色"
    };

    double[] weights = new double[]{
         2.3,
         3.1,
         1.58
    };

    private String color;

    private double weight;

    //继承Stub,也就是实现了ICat接口,并实现了IBinder接口
    public class CatBinder extends ICat.Stub{

        @Override
        public String getColor() throws RemoteException {
            return color;
        }

        @Override
        public double getWeight() throws RemoteException {
            return weight;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        catBinder = new CatBinder();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                //随机地改变Service组件内color、weight属性值
                int rand = (int) (Math.random() * 3);
                color = colors[rand];
                weight = weights[rand];
                System.out.println("------" + rand);
            }
        }, 0, 800);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        /* 
         * 返回catBinder对象
         * 
         * 在绑定本地Service的情况下,该catBinder对象会直接
         * 传给客户端的ServiceConnection
         * 的onServiceConnected方法的第二个参数
         * 
         * 在绑定远程Service的情况下,只将catBinder对象的代理
         * 传给客户端的ServiceConnection对象
         * 的onServiceConnected方法的第二个参数
         */
        return catBinder;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        timer.cancel();
    }
}

清单配置文件

<service android:name=".service.AidlService">
     <intent-filter>
           <action android:name="com.myandroid.service.AIDL_SERVICE"/>
     </intent-filter>
</service>
客户端访问AIDLService
public class Activity27 extends BaseActivity {

    private ICat catService;
    
    Button get;
    
    TextView color, weight;
    
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //获取远程Service的onBind方法返回的对象的代理
            catService = ICat.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            catService = null;
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity27);
        get = findViewById(R.id.get);
        color = findViewById(R.id.color);
        weight = findViewById(R.id.weight);
        /*
         * 服务意图必须是显性声明。 这是为了防止造成冲突(有多个Service用同样的intent-filter的情况)
         * 这是Android 5.0 (Lollipop) 之后的规定。不能用包名的方式定义Service Intent, 而要用显
         * 性声明:new Intent(context, xxxService.class);
         *
         * 如果想继续使用隐式意图的话,加上包名信息即可
         */
        //创建绑定服务的Intent
        Intent intent = new Intent();
        intent.setAction("com.myandroid.service.AIDL_SERVICE");
        intent.setPackage(context.getPackageName());//兼容Android 5.0
        bindService(intent, conn, Service.BIND_AUTO_CREATE);
        get.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try{
                    color.setText(catService.getColor());
                    weight.setText(String.valueOf(catService.getWeight()));
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        this.unbindService(conn);
    }
}

相关文章

  • 三十一、跨进程调用Service(AIDL服务)

    AIDL服务简介 Android的远程Service调用与Java的RMI基本相似,一样都是先定义一个远程调用接口...

  • Android中AIDL使用案例

    创建辅助文件 [日志文件、进程文件]创建 aidl 文件创建独立进程的远程服务 service启动远程服务 ser...

  • 通过service分析安卓binder机制的进程间通信

    安卓中进程间通信大家可能都非常了解,我们知道service可以使用aidl方法,远程调用服务实现两个不同app的通...

  • IPC进程间通信源码流程

    一、进程间通信的一个小事例1、编写aidl文件 2、新建一个服务Service 3、应用客户端调用 二、应用层的流...

  • AIDL跨进程调用服务

    一,创建服务端 新建一个项目并创建AIDL文件夹 在AIDL文件夹里面创建aidl格式文件(包名一定要有) 基于a...

  • Android多进程机制(三)AIDL的使用

    使用AIDL AIDL可以处理并发请求并且可以实现跨进程调用服务端的方法。 实现步骤 服务端 创建一个Servic...

  • 2018-07-06

    service和AIDL service执行与UI进程中,所以不要在service中执行耗时操作。 service...

  • 死磕AIDL

    AIDL:一种IPC跨进程调用远程服务方式,如果是同一个进程之内,没必要使用AIDL; 如下例子一步步揭开AIDL...

  • Android AIDL 使用

    最好用两个app来练习,一个提供service,一个调用。 服务端提供service的代码 1.创建aidl文件 ...

  • Binder方法调用

    Service Stub实现类 客户端调用类 getBookList和addBook这两个AIDL方法是在服务端的...

网友评论

      本文标题:三十一、跨进程调用Service(AIDL服务)

      本文链接:https://www.haomeiwen.com/subject/ryqisctx.html