Android Service 服务(三)—— bindService与remoteService

一、bindService简介

 

bindService是绑定Service服务,执行service服务中的逻辑流程。

service通过Context.startService()方法开始,通过Context.stopService()方法停止;也可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己。只要调用一次stopService()方法便可以停止服务,无论之前它被调用了多少次的启动服务方法。

 

客户端建立一个与Service的连接,并使用此连接与Service进行通话,通过Context.bindService()方法来绑定服务,Context.unbindService()方法来关闭服务。多个客户端可以绑定同一个服务,如果Service还未被启动,bindService()方法可以启动服务。

 

上面startService()和bindService()两种模式是完全独立的。你可以绑定一个已经通过startService()方法启动的服务。例如:一个后台播放音乐服务可以通过startService(intend)对象来播放音乐。可能用户在播放过程中要执行一些操作比如获取歌曲的一些信息,此时activity可以通过调用bindServices()方法与Service建立连接。这种情况下,stopServices()方法实际上不会停止服务,直到最后一次绑定关闭。

 

二、bindService启动流程

context.bindService()  ——> onCreate()  ——> onBind()  ——> Service running  ——> onUnbind()  ——> onDestroy()  ——> Service stop
 

onBind()将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出。 

所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。

在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。详见:Android Service 服务(一)—— Service

 

三、bindService生命周期

 

像一个activity那样,一个service有些可以用来改变状态的生命周期方法,但是比activity的方法少,service生命周期方法只有三个public

   void onCreate()

   void onStart(Intent intent)

   void onDestroy()

通过实现这三个生命周期方法,你可以监听service的两个嵌套循环的生命周期:

1、整个生命周期

 service的整个生命周期是在onCreate()和onDestroy()方法之间。和activity一样,在onCreate()方法里初始化,在onDestroy()方法里释放资源。例如,一个背景音乐播放服务可以在onCreate()方法里播放,在onDestroy()方法里停止。

 

2、活动的生命周期

 service的活动生命周期是在onStart()之后,这个方法会处理通过startServices()方法传递来的Intent对象。音乐service可以通过开打intent对象来找到要播放的音乐,然后开始后台播放。注: service停止时没有相应的回调方法,即没有onStop()方法,只有onDestroy()销毁方法。

 

onCreate()方法和onDestroy()方法是针对所有的services,无论它们是否启动,通过Context.startService()和Context.bindService()方法都可以访问执行。然而,只有通过startService()方法启动service服务时才会调用onStart()方法。

 

如果一个service允许别人绑定,那么需要实现以下额外的方法:

       IBinder onBind(Intent intent)

       boolean onUnbind(Intent intent)

       void onRebind(Intent intent)

onBind()回调方法会继续传递通过bindService()传递来的intent对象

onUnbind()会处理传递给unbindService()的intent对象。如果service允许绑定,onBind()会返回客户端与服务互相联系的通信句柄(实例)。

如果建立了一个新的客户端与服务的连接,onUnbind()方法可以请求调用onRebind()方法。

 

记住: 任何服务无论它怎样建立,默认客户端都可以连接,所以任何service都能够接收onBind()和onUnbind()方法

 

 

四、bindService示例

Activity

 

[java]  view plain copy print ?
 
  1. public class PlayBindMusic extends Activity implements OnClickListener {  
  2.   
  3.     private Button playBtn;  
  4.     private Button stopBtn;  
  5.     private Button pauseBtn;  
  6.     private Button exitBtn;  
  7.   
  8.     private BindMusicService musicService;  
  9.   
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.   
  14.         setContentView(R.layout.bind_music_service);  
  15.   
  16.         playBtn = (Button) findViewById(R.id.play);  
  17.         stopBtn = (Button) findViewById(R.id.stop);  
  18.         pauseBtn = (Button) findViewById(R.id.pause);  
  19.         exitBtn = (Button) findViewById(R.id.exit);  
  20.   
  21.         playBtn.setOnClickListener(this);  
  22.         stopBtn.setOnClickListener(this);  
  23.         pauseBtn.setOnClickListener(this);  
  24.         exitBtn.setOnClickListener(this);  
  25.   
  26.         connection();  
  27.     }  
  28.   
  29.     private void connection() {  
  30.         Intent intent = new Intent("com.homer.bind.bindService");  
  31.         bindService(intent, sc, Context.BIND_AUTO_CREATE);          // bindService  
  32.     }  
  33.   
  34.     @Override  
  35.     public void onClick(View v) {  
  36.         switch (v.getId()) {  
  37.         case R.id.play:  
  38.             musicService.play();  
  39.             break;  
  40.         case R.id.stop:  
  41.             if (musicService != null) {  
  42.                 musicService.stop();  
  43.             }  
  44.             break;  
  45.         case R.id.pause:  
  46.             if (musicService != null) {  
  47.                 musicService.pause();  
  48.             }  
  49.             break;  
  50.         case R.id.exit:  
  51.             this.finish();  
  52.             break;  
  53.         }  
  54.     }  
  55.   
  56.     private ServiceConnection sc = new ServiceConnection() {  
  57.   
  58.         @Override  
  59.         public void onServiceConnected(ComponentName name, IBinder service) {       //connect Service  
  60.             musicService = ((BindMusicService.MyBinder) (service)).getService();  
  61.             if (musicService != null) {  
  62.                 musicService.play();        // play music  
  63.             }  
  64.         }  
  65.           
  66.         @Override  
  67.         public void onServiceDisconnected(ComponentName name) {                 //disconnect Service  
  68.             musicService = null;  
  69.         }  
  70.     };  
  71.       
  72.     @Override  
  73.     public void onDestroy(){  
  74.         super.onDestroy();  
  75.           
  76.         if(sc != null){  
  77.             unbindService(sc);  
  78.         }  
  79.     }  
  80. }  


Service

 

 

[java]  view plain copy print ?
 
  1. public class BindMusicService extends Service {  
  2.   
  3.     private MediaPlayer mediaPlayer;  
  4.   
  5.     private final IBinder binder = new MyBinder();  
  6.   
  7.     public class MyBinder extends Binder {  
  8.         BindMusicService getService() {  
  9.             return BindMusicService.this;  
  10.         }  
  11.     }  
  12.   
  13.     @Override  
  14.     public IBinder onBind(Intent intent) {  
  15.         return binder;  
  16.     }  
  17.   
  18.     @Override  
  19.     public void onCreate() {  
  20.         super.onCreate();  
  21.           
  22.         Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show();  
  23.     }  
  24.   
  25.     @Override  
  26.     public void onDestroy() {  
  27.         super.onDestroy();  
  28.           
  29.         Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT);  
  30.         if(mediaPlayer != null){  
  31.             mediaPlayer.stop();  
  32.             mediaPlayer.release();  
  33.         }  
  34.     }  
  35.   
  36.       
  37.     public void play() {  
  38.         if (mediaPlayer == null) {  
  39.             mediaPlayer = MediaPlayer.create(this, R.raw.tmp);  
  40.             mediaPlayer.setLooping(false);  
  41.         }  
  42.         if (!mediaPlayer.isPlaying()) {  
  43.             mediaPlayer.start();  
  44.         }  
  45.     }  
  46.   
  47.     public void pause() {  
  48.         if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  49.             mediaPlayer.pause();  
  50.         }  
  51.     }  
  52.   
  53.     public void stop() {  
  54.         if (mediaPlayer != null) {  
  55.             mediaPlayer.stop();  
  56.             try {  
  57.                 mediaPlayer.prepare();      // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数  
  58.             } catch (IOException ex) {  
  59.                 ex.printStackTrace();  
  60.             }  
  61.         }  
  62.     }  
  63. }  


AndroidManifest.xml

 

 

[css]  view plain copy print ?
 
  1. <service  
  2.     android:name=".bind.BindMusicService"  
  3.     android:enabled="true" >  
  4.     <intent-filter>  
  5.         <action android:name="com.homer.bind.bindService" />  
  6.     </intent-filter>  
  7. </service>  



 

五、代码解析

1、 Activity中,Intent intent = new Intent("com.homer.bind.bindService"); 构建一个service的action,然后bindService(intent, sc, Context.BIND_AUTO_CREATE);绑定服务

2、 Activity中,通过private ServiceConnection sc = new ServiceConnection() 建立一个Service连接,onServiceConnected()获取Service实例,onServiceDisconnected()释放连接

3、 Service中,重载onBind(Intent intent)方法,返回Service实例(即BindMusicService)给Activity,然后执行onCreate()函数(注:bindService不执行onStart()函数)

4、 Activity中,通过返回的Service实例musicService,执行音乐播放的操作(play、pause、stop等)

 

 

六、Remote Service拓展

通常每个应用程序都在它自己的进程内运行,但有时需要在进程之间传递对象(IPC通信),你可以通过应用程序UI的方式写个运行在一个不同的进程中的service。在android平台中,一个进程通常不能访问其它进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。编写这种伪装代码相当的枯燥乏味,好在android为我们提供了AIDL工具可以来做这件事。
 
AIDL(android接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如在一个Activity中)访问另一个进程中(例如一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。
 
要使用AIDL,Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:

IMusicControlService.aidl

 

[css]  view plain copy print ?
 
  1. package com.homer.remote;  
  2.   
  3. interface IMusicControlService{  
  4.         void play();   
  5.         void stop();   
  6.         void pause();  
  7. }  
 
使用eclipse的Android插件,会根据这个aidl文件生成一个Java接口类,生成的接口类中会有一个内部类Stub类,Service来继承该Stub类:
Service
[java]  view plain copy print ?
 
  1. public class RemoteMusicService extends Service {  
  2.   
  3.     private MediaPlayer mediaPlayer;  
  4.   
  5.     @Override  
  6.     public IBinder onBind(Intent intent) {  
  7.         return binder;  
  8.     }  
  9.   
  10.     private final IMusicControlService.Stub binder = new IMusicControlService.Stub() {  
  11.   
  12.         @Override  
  13.         public void play() throws RemoteException {  
  14.             if (mediaPlayer == null) {  
  15.                 mediaPlayer = MediaPlayer.create(RemoteMusicService.this, R.raw.tmp);  
  16.                 mediaPlayer.setLooping(false);  
  17.             }  
  18.             if (!mediaPlayer.isPlaying()) {  
  19.                 mediaPlayer.start();  
  20.             }  
  21.         }  
  22.   
  23.         @Override  
  24.         public void pause() throws RemoteException {  
  25.             if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  26.                 mediaPlayer.pause();  
  27.             }             
  28.         }  
  29.   
  30.         @Override  
  31.         public void stop() throws RemoteException {  
  32.             if (mediaPlayer != null) {  
  33.                 mediaPlayer.stop();  
  34.                 try {  
  35.                     mediaPlayer.prepare();      // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数  
  36.                 } catch (IOException ex) {  
  37.                     ex.printStackTrace();  
  38.                 }  
  39.             }  
  40.         }  
  41.     };  
  42.       
  43.     @Override  
  44.     public void onDestroy() {  
  45.         super.onDestroy();  
  46.           
  47.         if(mediaPlayer != null){  
  48.             mediaPlayer.stop();  
  49.             mediaPlayer.release();  
  50.         }  
  51.     }  
  52. }  

客户端(Activity)应用连接到这个Service时,onServiceConnected方法将被调用,客户端就可以获得IBinder对象。参看下面的客户端onServiceConnected方法:

 

Activity

 

[java]  view plain copy print ?
 
  1. public class PlayRemoteMusic extends Activity implements OnClickListener {  
  2.   
  3.     private Button playBtn;  
  4.     private Button stopBtn;  
  5.     private Button pauseBtn;  
  6.     private Button exitBtn;  
  7.   
  8.     private IMusicControlService musicService;  
  9.   
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.remote_music_service);  
  14.   
  15.         playBtn = (Button) findViewById(R.id.play);  
  16.         stopBtn = (Button) findViewById(R.id.stop);  
  17.         pauseBtn = (Button) findViewById(R.id.pause);  
  18.         exitBtn = (Button) findViewById(R.id.exit);  
  19.   
  20.         playBtn.setOnClickListener(this);  
  21.         stopBtn.setOnClickListener(this);  
  22.         pauseBtn.setOnClickListener(this);  
  23.         exitBtn.setOnClickListener(this);  
  24.   
  25.         connection();  
  26.     }  
  27.   
  28.     private void connection() {  
  29.         Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");  
  30.         bindService(intent, sc, Context.BIND_AUTO_CREATE);              // bindService  
  31.     }  
  32.   
  33.     @Override  
  34.     public void onClick(View v) {  
  35.   
  36.         try {  
  37.             switch (v.getId()) {  
  38.             case R.id.play:  
  39.                 musicService.play();  
  40.                 break;  
  41.             case R.id.stop:  
  42.                 if (musicService != null) {  
  43.                     musicService.stop();  
  44.                 }  
  45.                 break;  
  46.             case R.id.pause:  
  47.                 if (musicService != null) {  
  48.                     musicService.pause();  
  49.                 }  
  50.                 break;  
  51.             case R.id.exit:  
  52.                 this.finish();  
  53.                 break;  
  54.             }  
  55.         } catch (RemoteException e) {  
  56.             e.printStackTrace();  
  57.         }  
  58.     }  
  59.   
  60.     private ServiceConnection sc = new ServiceConnection() {  
  61.         @Override  
  62.         public void onServiceConnected(ComponentName name, IBinder service) {       //connect Service  
  63.             musicService = IMusicControlService.Stub.asInterface(service);  
  64.         }  
  65.   
  66.         @Override  
  67.         public void onServiceDisconnected(ComponentName name) {                 //disconnect Service  
  68.             musicService = null;  
  69.         }  
  70.   
  71.     };  
  72.       
  73.     @Override  
  74.     public void onDestroy(){  
  75.         super.onDestroy();  
  76.           
  77.         if(sc != null){  
  78.             unbindService(sc);              // unBindService  
  79.         }  
  80.     }  
  81. }  


Remote Service流程总结:

1、 Activity(客户端)中,Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");构建intent,然后bindService(intent, sc, Context.BIND_AUTO_CREATE);绑定服务

2、 Activity(客户端)中,通过ServiceConnection()重载onServiceConnected()建立连接,获取Service.Stub实例;onServiceDisconnected()释放连接(与bindService类似)

3、 Service中,通过重载onBind(Intent intent) 返回Service.Stub实例,但Service.Stub类是由aidl文件生成的接口类中的一个内部类Stub类,Service来继承该Stub类

4、 Activity中,通过操作Service实例(musicService),执行音乐播放操作(play、pause、stop等)

 

源码下载

 

 

参考推荐:

Service (android developer)

Android Service 服务(一)—— Service

Android Service 服务(二)—— BroadcastReceiver

android中service和aidl详细整理

Android Service AIDL

android笔记--Service与AIDL

Android service(服务)中的绑定服务(binderService)详解与使用 前两篇文章中介绍了普通的后台服务及前台服务,这些服务有个共同的特点就是,启动服务的组件和服务之间没有任何关系。要想两者之间发生点关系,那就需要将两者之间绑定起来,这就用到了绑定服务。应用组件(客户端)可通过调用绑定到服务。然后,Android 系统会调用服务的onBind()方法,该方法会返回用于与服务交互的IBinder。绑定是异步操作,并且可立即返回,无需将IBinder返回给客户端。如要接收IBinder,客户端必须创建一个实例,并将其传递给。 阅读详情

相关推荐

Android入门第41天-Android中的Service(bindService)

在前一天我们介绍了Android中有两种启动Service的方法。并擅述了startService和bindService的区别。同时我们着重讲了startService。因此今天我们就来讲bindService。bindService大家可以认为它是和Android的一个共生体。即这个service所属的activity如果消亡那么bindService也会消亡。因此今天我们以一个比较复杂的例子,activityservice间互相传值来讲透这个bindService的使用。

打造全国最全的AI Agent开发知识领域的博客 1331

展开说说:Android服务之bindService解析

前面两篇文章我们分别总结了Android四种Service的基本使用以及源码层面总结一下startService的执行过程,本篇继续从源码层面总结bindService的执行过程。 本文依然按着是什么?有什么?怎么用?啥原理?的步骤来分析。 bindService使用方法和调用流程都与startService时有很多相似之处,方便的话请先阅读上一篇《展开说说:Android服务之startService解析》。

Hidanchaofan的博客 3276

移动端抓包实战指南:从HTTPS解密到QUIC协议与证书绑定破解

HTTPS作为保障网络通信安全的核心协议,其工作原理基于TLS/SSL加密与证书信任链验证。在移动应用开发与测试中,抓包是调试接口、分析性能、排查问题的关键技术手段。然而,随着移动端安全性的提升,传统的代理抓包方法常因证书绑定、HTTP/3/QUIC协议等挑战而失效。这要求开发者掌握分层诊断思维,协同使用代理工具、协议分析工具及底层流量捕获工具。例如,面对证书绑定导致的流量不可见,需借助Wireshark进行协议层分析;针对基于UDP的QUIC协议,则需使用支持该协议的抓包工具或临时禁用特性。本文聚焦移动端

weixin_27722377的博客 299

android 独立服务,【Android】远程服务(Remote Service)的使用

1.远程服务简介什么是远程服务远程服务(Remote Service)也被称之为独立进程,它不受其它进程影响,可以为其它应用程序提供调用的接口——实际上就是进程间通信IPC(Inter-Process Communication),Android提供了AIDL(Android Interface Definition Language,接口描述语言)工具来帮助进程间接口的建立。在Android中,...

weixin_39564368的博客 1483

InSAR数据获取实战指南:Sentinel-1、精密轨道与ALOS PALSAR DEM的下载与应用

本文详细介绍了InSAR数据获取的实战指南,重点解析Sentinel-1数据、精密轨道数据(OPOD)和ALOS PALSAR DEM的下载与应用技巧。通过实际案例和代码示例,帮助读者掌握数据筛选、下载加速、校验及多源数据协同使用的关键方法,提升地面形变监测的精度与效率。

weixin_29215815的博客 433

全网最全的AItium Designer 16下载资源与安装步骤

Altium Designer 除了全面继承包括Protel 99SE、Protel DXP在内的先前一系列版本的功能和优点外,还增加了许多改进和很多高端功能。该平台拓宽了板级设计的传统界面,全面集成了FPGA设计功能和SOPC设计实现功能,从而允许工程设计人员能将系统设计中的FPGA与PCB设计及嵌入式设计集成在一起。...

WQ的博客 1万+

Android Service 服务 三 bindService与remoteService

Android Service 服务 三 bindService与remoteService

dghggij的博客 220

GB28181安防平台未授权访问漏洞:原理、复现与修复指南

未授权访问漏洞是Web安全中常见的访问控制缺陷,其本质在于应用在提供对敏感功能或数据的访问前,未能对请求者的身份和权限进行充分验证。从技术原理上看,这类漏洞常源于拦截器配置错误、安全注解遗漏或自定义校验逻辑缺陷,导致本应受保护的API接口被意外暴露。在工程实践中,此类漏洞危害巨大,攻击者无需登录即可直接访问系统核心接口,可能引发敏感信息泄露、权限提升甚至系统接管。尤其在安防监控、物联网管理平台等场景中,一旦涉及用户管理接口(如`/api/user/**`),风险会急剧放大。本文以GB28181视频监控管理平

weixin_30271335的博客 441

android c++服务,Android Service 服务(三)—— bindService与remoteService (转载)

一、bindService简介bindService是绑定Service服务,执行service服务中的逻辑流程。service 通过Context.startService()方法开始,通过Context.stopService()方法停止;也可以通过 Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己。只要调用一次 stopService...

weixin_39829236的博客 559

Windows10检查Cuda和cuDNN是否安装成功?

简介:根据上篇博客已经完成了CUDA和cuDNN的安装步骤,完成对其的安装。下面将来检查它们是否安装成功。 1 .首先win+R进入CMD,在命令行输入nvcc -V,如下图所示,则表示cuda已经安装成功。 2 .进入到cuda的安装路径,C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\extras\demo_suite,找到如下两个.exe文件: 首先执行:deviceQuery.exe,查看是否出现如下界面: 然后执行bandwid

jhsignal的博客 14万+

疲劳容器的定义_FKM规范针对非焊接构件疲劳强度评估实例介绍(下篇)

一、写在前面FKM Inside ANSYS软件,该软件是在FKM 规范的基础上,在ANSYS Workbench内开发的进行非焊接构件及焊缝静强度和疲劳强度评估的工具包。基于ANSYS计算模型的信息,在图形用户界面定义相关设置,利用有限元分析计算结果,自动嵌入FKM规范要求的静强度计算和疲劳强度计算流程和方法,自动将应力结果和相关物理量传递给工具包,无须手动预先选择评估的热点区域,可以...

weixin_35925298的博客 1885
上一篇: Android Service 服务(二)—— BroadcastReceiver
下一篇: Android中Context
whatsyourname
博客等级 码龄23年 13粉丝 326原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值