zoukankan      html  css  js  c++  java
  • 一个简单的demo学习Android远程Service(AIDL的使用)

    这是milo很早之前写在论坛上的一个帖子,现在整理出来,milo也复习一下
    一般来说Android 的四大组件都是运行在同一个进程中的,但远程Service运行在不同的进程里。这进程间的通信是使用了Android Binder机制。Android 中Service 有本地Service和远程Service之分,本地Service用法比较简单,而远程Service用法稍微要复杂一些。下面就是一个使用AIDL的用法。

    AIDL即android 接口定义语言,概念不多说,网上有太多的帖子介绍概念。本文只想说明一下aidl的用法。由于最近开发一个播放器的项目使用了aidl。aidl是解决进程间通信用的。在本例中就是Activity(即client端)与Service(即服务端)的通信。
    首先,定义Aidl文件,如Service中暴露给Activity的接口可以定义在aidl文件中,反之也一样。本文中,Service给Activity使用接口文件是ServiceAIDL.aidl
    <pre lang="LANGUAGE" line="1">
    package com.miloisbadboy.aidl;
    import com.miloisbadboy.aidl.ActivityAIDL;
    /**
    * Service中暴露给Activity的接口可以定义在aidl文件中
    */
    interface ServiceAIDL{
    void callService();
    /**
    * 在Activity中注册ActivityAIDL到Service中,使Service中可以调用ActivityAIDL中的方法
    **/
    void registActivityCallBack(ActivityAIDL callBack);
    }
    </pre>
    Activity给Service中使用的ActivityAIDL.aidl
    <pre lang="LANGUAGE" line="1">
    package com.miloisbadboy.aidl;
    /**
    * Activity中暴露给Service的接口可以定义在aidl文件中
    */
    interface ActivityAIDL{
    void callActivity();
    }
    </pre>
    上面两个aidl在会自动在gen目录下生成对应的java文件。
    第二步,写Service。写一个MyService继承于Service类,并在onBind()方法中 返回ServiceAidl.Stub对象
    具体看下面代码
    MyService.java
    <pre lang="LANGUAGE" line="1">
    package com.miloisbadboy;

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

    import com.miloisbadboy.aidl.ActivityAIDL;
    import com.miloisbadboy.aidl.ServiceAIDL;

    /**
    * 远程服务
    */
    public class MyService extends Service {
    public static final String SERVICE_NAME = "com.miloisbadboy.start.MyService";
    public static final String TAG = "MyService";

    private ActivityAIDL activityAIDL;

    @Override
    public IBinder onBind(Intent intent) {
    return mBinder;
    }

    private ServiceAIDL.Stub mBinder = new ServiceAIDL.Stub() {

    @Override
    public void callService() throws RemoteException {
    Log.i(TAG, "Activity Call Service's method ****** callService()");
    Toast.makeText(getApplicationContext(), "Call Service's method ****** callService()",
    1000).show();

    activityAIDL.callActivity();
    }

    @Override
    public void registActivityCallBack(ActivityAIDL callBack) throws RemoteException {
    activityAIDL = callBack;
    }

    };
    }

    </pre>
    MyService中有ActiviyAIDL的一个引用,此类型的实例是在ServiceAIDL.Stud这个代理中得到的,即是在registActivityCallBack(ActivityAIDL callBack)方法中对其赋值,这个方法是在Activity中将ActivityAIDL的接口注册到Service中去的。
    在ServiceAidl.Stub mBinder = new ServiceAidl.Stub(){}里面的callService() 和registActivityAidl(ActivityAidl activityAidl)方法就是在Activity将会被调用到的。
    最后看一个Activity类
    <pre lang="LANGUAGE" line="1">
    package com.miloisbadboy;

    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;
    import android.widget.Toast;

    import com.miloisbadboy.aidl.ActivityAIDL;
    import com.miloisbadboy.aidl.ServiceAIDL;
    /**
    * 测试远程Service
    */
    public class TestAIDLActivity extends Activity implements OnClickListener{

    private static final String TAG = "TestAIDLActivity";

    private Button start;
    private Button stop;
    private Button callService;
    /**
    * service call back
    */
    private ServiceAIDL serviceAIDL;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    start = (Button)findViewById(R.id.start_service);
    stop = (Button)findViewById(R.id.stop_service);
    callService = (Button)findViewById(R.id.call_service);

    start.setOnClickListener(this);
    stop.setOnClickListener(this);
    callService.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
    if(v == start){
    Intent service = new Intent(MyService.SERVICE_NAME);
    //绑定Service 并将ServiceConnection的实例传入
    bindService(service, serviceConn, Context.BIND_AUTO_CREATE);
    stop.setVisibility(View.VISIBLE);
    }else if(v == stop){
    unbindService(serviceConn);
    }else{
    try {
    if(serviceAIDL!=null){
    serviceAIDL.callService();
    }else {
    Toast.makeText(this, "Service is not started!", 1000).show();
    }
    } catch (RemoteException e) {
    e.printStackTrace();
    }
    }
    }
    private ServiceConnection serviceConn = new ServiceConnection() {

    @Override
    public void onServiceDisconnected(ComponentName name) {
    serviceAIDL = null;
    Toast.makeText(getApplication(), "Service is unbind!", 1000).show();
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    serviceAIDL = ServiceAIDL.Stub.asInterface(service);
    //在此将Activity暴露给Service的接口实现注册到Service中去
    try {
    serviceAIDL.registActivityCallBack(activityAidl);
    } catch (RemoteException e) {
    e.printStackTrace();
    }
    }
    };
    /**
    * 在activity中实现ActivityAIDL接口
    */
    private ActivityAIDL activityAidl = new ActivityAIDL.Stub() {

    @Override
    public void callActivity() throws RemoteException {
    Log.i(TAG, "callActivity()");
    Toast.makeText(getApplicationContext(), "service call activity", 1000).show();
    }
    };
    }
    </pre>
    在activity中有三个按钮分别为 start service ; stop service ;callService
    各个按钮的动作顾名思义啦。特别注意到。在Activity ServiceConnection中 会通过ServiceAIDL.Stub.asInterface(service)得到ServiceAIDL的实例,并且将activityAidl的引用注册到了Service中。
    在start service 按钮事件里,通过bindService(service, serviceConn, Context.BIND_AUTO_CREATE)将Service 与Activity绑定。

    这个程序跑起来的顺序是,启动Activity后,并start service后 点击callServiceBtn,就会调用MyService中实现的callService()接口,而在callService中又调用了activityAidl即Activity的回调callActivity()方法
    这样就模拟了 Activity 与Service两个进程间的通信,即相互调用了对方的对象。
    本文只是对Aidl的用法做了一个小小总结,算是抛砖引玉吧。

  • 相关阅读:
    java.lang.NoSuchMethodError: org.springframework.beans.factory.annotation.InjectionMetadata.<init>(Ljava/lang/Class;)V
    tomcat下jndi的三种配置方式
    使用@RequestParam绑定请求参数到方法参数
    IE下easyui 缓存问题
    many to one could not resolve property
    aop郁闷错误
    Spring 运用 pointcut 和 advisor 对特定的方法进行切面编程
    放大改进版~
    cocos2d-x嵌入移动MM短代支付IAP2.4的SDK,点击支付崩溃的解决的方法
    在 Android* 商务应用中实施地图和地理围栏特性
  • 原文地址:https://www.cnblogs.com/chenliyang/p/6633495.html
Copyright © 2011-2022 走看看