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

    原文地址

    http://miloisbadboy.com/archives/109

    这是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的用法做了一个小小总结,算是抛砖引玉吧。

     

     

  • 相关阅读:
    strcpy
    Apple Swift中英文开发资源集锦[apple swift resources]
    c/c++指针总结[pointer summary]
    TestPointer
    66. 有序数组构造二叉搜索树[array to binary search tree]
    HDU 2112 HDU Today
    HDU 3790 最短路径问题
    HDU 2544 最短路
    模拟赛 Problem 3 经营与开发(exploit.cpp/c/pas)
    模拟赛 Problem 2 不等数列(num.cpp/c/pas)
  • 原文地址:https://www.cnblogs.com/angrycode/p/2660077.html
Copyright © 2011-2022 走看看