`
Jonathan樊
  • 浏览: 74985 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类
最新评论

Android开发——Service的学习(下)

阅读更多

        Bound Service 是客户端-服务器模式的服务,它允许允许组件(比如activity)对其进行绑定、发送请求、接收响应、甚至进行进程间通信(IPC)。为了提供绑定,开发人员必须实现onBind()毁掉方法,该方法返回IBinder对象,它定义了客户端用来与服务交互的程序接口。

        客户端通过bindService()方法绑定到服务。此时,客户端必须提供ServiceConnection接口的实现类,它监视客户端和服务之间的连接。多个客户端能够同时连接服务器。然而仅当第一个客户端绑定时,系统调用服务的onBind()方法来获取IBinder对象。然后,系统会向后续请求绑定的客户端传送这同一个 IBinder ,而不再调用 onBind() 。

        当最后一个客户端解除绑定后,系统会销毁服务(除非服务同时是通过 startService() 启动的)。

 

       一:创建Bound服务

        当你实现自己的bound服务时,最重要的工作就是定义 onBind() 回调方法所返回的接口。 有一下三种方式:

        (1)继承Binder类

        如果服务是你的应用程序所私有的,并且与客户端运行于同一个进程中(通常都是如此),你应该通过j继承 Binder 类来创建你的接口,并从 onBind() 返回一个它的实例。客户端接收该 Binder 对象并用它来直接访问 Binder 实现类或者 Service 中可用的公共(public)方法。

        如果服务只应用于私有应用程序,那这就是首选的技术方案。如果服务要被其它应用程序使用或者访问独立进程时,则不能使用该技术。

        仅当客户端与服务位于同一个应用程序和进程时,才可以。例如音乐播放我绑定activity到自己的服务来在后台播放音乐。

        

        实现步骤如下:

  • 在你的服务中,创建一个 Binder 的实例,实现以下三者之一:

             (1)包含客户端能调用的公共方法

             (2)返回当前service实例,其中包含客户端能够调用的公共方法

             (3)返回服务管理的其他类的实例,其中包含客户端能够调用的公共方法

 

  • 从回调方法 onBind() 中返回 Binder 类的实例。
  • 在客户端中,在回调方法 onServiceConnected() 中接收 Binder 类实例并用所提供的方法对绑定的服务进行调用。

      以下是一个服务的示例,它通过实现一个 Binder 来为客户端访问它内部的方法提供支持:

 

public class LocalService extends Service {
    // 给客户端的Binder
    private final IBinder mBinder = new LocalBinder();
    // 产生随机数
    private final Random mGenerator = new Random();


    public class LocalBinder extends Binder {
        LocalService getService() {
            // 返回LocalService 的实例,其中包含客户端可以调用的方法
            return LocalService.this;
        }
    }

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

    /**客户端可以调用的方法 */
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}

         LocalBinder为客户端提供了getService()方法,用于返回当前LocalService的实例。 这就让客户端可以调用服务中的公共方法。比如,客户端可以调用服务中的getRandomNumber()。

 

 

        以下是一个绑定到LocalService的activity,当点击按钮时,它会调用getRandomNumber():

 

public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // 绑定到 LocalService
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 解除绑定的服务
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    /** 点击Button时,调用此方法 */
    public void onButtonClick(View v) {
        if (mBound) {
            // 调用LocalService中的方法。
            // 不过,如果该调用会导致某些操作的挂起,那么调用应该放入单独的线程中进行,
            // 以免降低activity的性能。
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }

    /** 定义服务绑定的回调方法,将其传给bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // 我们已经绑定了服务, 将IBinder转型获得LocalService实例
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

       上述例子展示了客户端如何利用 ServiceConnection 和 onServiceConnected() 回调方法绑定到服务。

 

       

       (2)使用Messenger类

        如果你的服务需要与远程进程进行通信,那你可以使用一个 Messenger 来提供服务的接口。这种技术能让你无需使用AIDL就能进行进程间通信(IPC),这是执行进程间通信(IPC)最为简便的方式。

       

        以下是使用方法:

  •  服务实现一个 Handler ,用于客户端每次调用时接收回调。
  • 此 Handler 用于创建一个 Messenger 对象(它是一个对 Handler 的引用)。
  • 此 Messenger 对象创建一个 IBinder ,服务在 onBind() 中把它返回给客户端。
  • 客户端用 IBinder 将 Messenger (引用服务的 Handler )实例化,客户端用它向服务发送消息对象 Message 。
  • 服务接收 Handler 中的每个消息 Message ——确切的说,是在 handleMessage() 方法中接收。

        通过这种方式,客户端不需要调用服务中的“方法”。取而代之的是,客户端发送“消息”( Message 对象),服务则接收位于 Handler 中的这个消息。

 

public class MessengerService extends Service {
   
    static final int MSG_SAY_HELLO = 1;

    /**
     * 服务处理客户端发来的消息
     * 服务实现了一个Handler
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    /**
     * 给客户端使用的用来发送消息给 IncomingHandler.即为,第二步。
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());

    /**
     * 返回一个接口用来给服务发送消息,即为,第三步
     */
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}

        客户端要做的全部工作就是根据服务返回的 IBinder 创建一个 Messenger ,并用 send() 方法发送一个消息。例如,以下是一个activity示例,它绑定到上述服务,并向服务发送 MSG_SAY_HELLO消息:

        

public class ActivityMessenger extends Activity {
    /** 和service沟通的Messenger. */
    Messenger mService = null;

    /** 是否已经绑定 */
    boolean mBound;

    /**
     * 与服务进行交互
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // 与服务建立联接后将会调用本方法,
            // 给出用于和服务交互的对象。
            // 我们将用一个Messenger来与服务进行通信,
            // 因此这里我们获取到一个原始IBinder对象的客户端实例。
            mService = new Messenger(service);
            mBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            // 当与服务的联接被意外中断时——也就是说服务的进程崩溃了,
            // 将会调用本方法。
            mService = null;
            mBound = false;
        }
    };

    public void sayHello(View v) {
        if (!mBound) return;
        //  创建并向服务发送一个消息,用到了已约定的'what'值
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        //绑定到服务
        bindService(new Intent(this, MessengerService.class), mConnection,
            Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 解除绑定
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

         二:绑定到服务

 

 

        应用程序组件(客户端)可以通过调用 bindService() 来绑定服务。然后Android系统会调用服务的 onBind() 方法,返回一个用于和服务进行交互的 IBinder 。

       绑定是异步进行的。 bindService() 将立即返回,并不会向客户端返回 IBinder 。为了接收 IBinder ,客户端必须创建一个 ServiceConnection 的实例,并把它传给 bindService() 。 ServiceConnection 包含了一个回调方法,系统将会调用该方法来传递客户端所需的那个 IBinder 。

       注意: 只有activity、service和content provider才可以绑定到服务上——broadcast receiver不能绑定服务。

      因此,要把客户端绑定到服务上,你必须:

  • 实现 ServiceConnection 。你的实现代码必须重写两个回调方法:onServiceConnected()系统调用该方法来传递服务的 onBind() 方法所返回的 IBinder 。onServiceDisconnected()当与服务的联接发生意外中断时,比如服务崩溃或者被杀死时,Android系统将会调用该方法。客户端解除绑定时,不会调用该方法。
  • 调用 bindService() ,传入已实现的 ServiceConnection 。
  • 当系统调用你的 onServiceConnected() 回调方法时,你可以利用接口中定义的方法开始对服务的调用。
  • 要断开与服务的联接,请调用 unbindService()

        当客户端被销毁时,与服务的绑定也将解除。但与服务交互完毕后,或者你的activity进入pause状态时,你都应该确保解除绑定,以便服务能够在用完后及时关闭。 

LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
    // 与服务的联接建立之后将会调用
    public void onServiceConnected(ComponentName className, IBinder service) {
        // 因为我们已经与明显是运行于同一进程中的服务建立了联接,
        // 我们就可以把它的IBinder转换为一个实体类并直接访问它。
      LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    // 与服务的联接意外中断时将会调用
    public void onServiceDisconnected(ComponentName className) {
        Log.e(TAG, "onServiceDisconnected");
        mBound = false;
    }
};

 利用这个 ServiceConnection ,客户端就能够把它传入 bindService() 完成与服务的绑定。

Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

 

1
0
分享到:
评论

相关推荐

    《Google Android开发入门与实战》

    第10章 一切为用户服务——Service应用实例 第12章 Android综合案例一——RSS阅读器实例 第14章 Android综合案例三——基于Android的豆瓣网(Web2.0)移动客户端开发 第15章 Android综合案例四——在线音乐播放器 第16...

    android开发入门与实战(下)

    第10章 一切为用户服务——Service应用实例 10.1 认识Service 10.2 使用Service 10.3 Service的生命周期 10.4 实例学习Service 10.4.1 精彩实例一——定时提醒 10.4.2 精彩实例二——音乐播放器 10.5 本章小结 第11...

    Android开发与应用——张荣,原书配套课件

    这是Android开发与应用,原书配套的课件,作者张荣,目录如下。 第1章 Android简介 1.1 手机操作系统 1.2 Android起源 1.3 Android特征 1.4 Android体系结构 1.4.1 应用层 1.4.2 应用框架层 1.4.3 ...

    Android应用开发详解

    Android开发基础,讲述了Android开发环境的搭建、Android常用工具的使用和第一个Android应用程序的开发 第二篇 技术篇 第3章 Android中的资源访问 Android 中的资源访问,讲述了如何定义和访问Android中的外部...

    《Google Android开发入门与实战》.pdf

    第10章 一切为用户服务——service应用实例 187 10.1 认识service 187 10.2 使用service 188 10.3 service的生命周期 194 10.4 实例学习service 194 10.4.1 精彩实例一——定时提醒 194 10.4.2 ...

    老罗android开发视频教程全集百度网盘下载

    Android 是Google开发的基于Linux平台的开源手机操作系统。它包括操作系统、用户界面和应用程序—— 移动电话工作所需的全部软件,而且不存在任何...【第一版第十五章】老罗Android开发视频--百度地图实战开发(10集)

    android开发入门与实战(上)

    第10章 一切为用户服务——Service应用实例 10.1 认识Service 10.2 使用Service 10.3 Service的生命周期 10.4 实例学习Service 10.4.1 精彩实例一——定时提醒 10.4.2 精彩实例二——音乐播放器 10.5 本章小结 第11...

    安卓学习教材经验Android进阶学习资料安卓面试资料等文档资料合集(22个).zip

    安卓学习教材经验Android进阶学习资料安卓面试资料等文档资料合集(22个): Android For OpenCV的环境搭建 Android Glide框架 二次封装 ...初中级Android开发社招面试之Service及BroadcastReceiver.p

    Google Android SDK开发范例大全(PDF完整版4)(4-4)

    6.4 开始与停止系统服务——Service与Runnable整合并用 6.5 通过短信发送email通知——BroadcastReceiver与Intent整合 6.6 手机拨接状态——PhoneStateListener之onCallStateChanged 6.7 有来电,发送邮件通知——...

    Google Android SDK开发范例大全(PDF高清完整版1)(4-1)

    6.4 开始与停止系统服务——Service与Runnable整合并用 6.5 通过短信发送email通知——BroadcastReceiver与Intent整合 6.6 手机拨接状态——PhoneStateListener之onCallStateChanged 6.7 有来电,发送邮件通知——...

    Google.Android开发入门与实战

    第10章 一切为用户服务——Service应用实例 10.1 认识Service 10.2 使用Service 10.3 Service的生命周期 10.4 实例学习Service 10.4.1 精彩实例一——定时提醒 10.4.2 精彩实例二——音乐播放器 10.5 本章小结 第11...

    android开发入门教程

    第10章 一切为用户服务——Service应用实例 10.1 认识Service 10.2 使用Service 10.3 Service的生命周期 10.4 实例学习Service 10.4.1 精彩实例一——定时提醒 10.4.2 精彩实例二——音乐播放器 10.5 本章小结 第11...

    Google Android SDK开发范例大全(PDF高清完整版3)(4-3)

    6.4 开始与停止系统服务——Service与Runnable整合并用 6.5 通过短信发送email通知——BroadcastReceiver与Intent整合 6.6 手机拨接状态——PhoneStateListener之onCallStateChanged 6.7 有来电,发送邮件通知——...

    android开发资料大全

    android开发教程合集(推荐新手看下这一季教程) 新手入门 会员贡献电子图书整理(内含PDF下载) Android平板开发需要注意的几点 Android3D游戏开发付费视频教程共享(更新第四集) 史上最全示例Android教学视频,...

    Google Android SDK开发范例大全的目录

    6.4 开始与停止系统服务——Service与Runnable整合并用 6.5 通过短信发送email通知——BroadcastReceiver与Intent整合 6.6 手机拨接状态——PhoneStateListener之onCallStateChanged 6.7 有来电,发送邮件通知——...

    Google Android开发入门与实战的代码

    第10章 一切为用户服务——Service应用实例 187 10.1 认识Service 187 10.2 使用Service 188 10.3 Service的生命周期 194 10.4 实例学习Service 194 10.4.1 精彩实例一——定时提醒 194 10.4.2 ...

Global site tag (gtag.js) - Google Analytics