文章目录

  • Android Service服务的相关介绍
    • 创建方式
    • 启动方式
    • 生命周期
      • onStartCommand参数及返回值的理解
    • ServiceConnection
    • 场景说明
    • 前台服务
    • 问答
      • startService和bindService顺序的影响
      • 如果你的服务也想让其他应用启动那该怎么办
      • service被系统杀死后会执行到Service.onDestroy吗
    • 其他
    • 参考

Android Service服务的相关介绍

  • 服务概览 | Android 开发者 | Android Developers
  • android service是一种运行在后台,不需要与用户交互的任务
  • service不是运行在单独的进程中的(当然,如果你想的话也是可以在单独的进程中的),本身还是运行在主线程中,因此如果后台服务是个耗时任务,那么必须得开启线程去执行(因此出现了IntentService
  • 当进程被杀死,依赖该进程的服务也会被杀死,也就是说当app应用进程被杀死时,服务也停止了,因此不存在说app挂了而它的服务还在跑的情况
  • 实际上service可以理解为一个没有界面的activity,它可以默默地在后台处理一些任务

创建方式

  • 在android中使用service其实很简单,就是继承Service即可,然后在相应的生命周期函数里实现一些功能
  • 当然,作为四大组件之一的service,别完了在清单文件中配置一下servic,不然服务是跑不起来的
  • 生命周期里有个onBind方法,这个onBind是干嘛的呢
  • 一般情况下,如果我们的服务启动后就只是默默地做它自己的任务,不想与外界有任何交流,那么就可以在onBind这个方法里返回null
  • 但假如我们的服务可以对外开放自己的一些能力(在代码里就是开放一堆方法供外界调用),那么就可以把这些要开放的东西写在一个类里,而这个类要实现IBinder接口,然后我们可以在Service类里实例这个IBinder对象,在onBind这个方法里返回这个实例对象
  • 这样客户端连接到这个服务时,就可以拿到这个实例对象,然后就可以愉快地调用服务开放的能力了

启动方式

  • 当服务都写好了,那么该怎么启动这个服务呢
  • service有两种启动方式,startServicebindService
  • 这两种方式的区别是bindService方式可以被多个Activity绑定,当所有绑定的都解绑后服务才有可能会销毁,之所以说可能,是因为假如服务在bindService之前已经startService了,那么即使后面都解绑了,服务依然会存在
  • startService一旦跑起来,除非调用stopService或stopSelf或者应用被杀死,否则服务会一直存在,即使中间有人通过unbindService解绑,服务也不会销毁
  • 这里再强调一次,startService启动后服务销毁的条件只能是调用stopService或在服务里stopSelf或者服务所在进程被杀死
  • 既然有了startService,那么bindService是干嘛的呢
  • bindService主要有两个作用,一个是临时与服务建立本地通信,另一个就是跨进程通信(IPC)了
  • bindService的生命周期比较短,比如在activity里bindService的话,那么activity销毁时服务也停止了(你在logcat里应该能看到一个异常has leaked ServiceConnection/was originally bound here,这个异常不会导致应用奔溃,但其实就是在提醒你要在适当时机调用unbindService),当然,为了消除这个异常,你完全可以在Activity的onDestroy里调用unbindService,如果你没手动调用unbindService,activity销毁时也会帮你解绑,解绑后如果发现服务不是startService启动的,而且已经没有其他人与之绑定了,那么就会销毁这个服务,只要还有其他人与之绑定,那么服务还是继续存在

生命周期

  • 服务的生命周期与启动方式有一定的联系
  • startService启动服务的话一般会经历 onCreate --> onStartCommand -> onStart(已经标记过时) -> onDestroy
  • bindService分为两种,
  • 一种是bindService之前服务还不存在: onCreate --> onBind --> onUnbind --> onDestroy
  • 一种是bindService之前服务已经存在: onBind --> onUnbind --> onDestroy
  • 不管怎么样,反正服务的onCreate只会执行一次,onBind也只会执行一次,这一点牢记即可
  • 当你多次调用startService的话,你会发现onStartCommand和onStart就会被多次调用
  • 当你多次调用bindService,onBind只会执行一次
  • stopService调用多少次都无所谓,而unbindService与bindService要成对的,否则会引发异常,即调用unbindService时发现之前根本就没有绑定,那么就会抛出异常
  • 为了解决unbindService这个异常,你可以在bindService的ServiceConnection的onServiceConnected的时候设置一个标记,然后根据这个标记来决定是否调用unbindService

onStartCommand参数及返回值的理解

  • 以下是android的默认实现
 public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {onStart(intent, startId);return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;}
  • onStartCommand有三个参数,第一个就是启动这个服务的Intent,这个似乎没什么好说的,需要注意的是这个intent有可能为空,因为服务可能被异常终止,然后被系统重新启动,此时intent为不为空得看之前onStartCommand的返回值
  • 第二个参数flags总共有三个值,0和START_FLAG_REDELIVERY和START_FLAG_RETRY;其中0就是我们正常startService时这个flags就是0,如果我们的服务由于某些异常由android系统重启,那么flags才会是另外两个值;START_FLAG_RETRY表示onStartCommand方法没正常返回时系统进行的重试,START_FLAG_REDELIVERY就是onStartCommand能正常返回,但后边服务遇到异常被系统重启
  • 第三个参数就是每次startService都会进行自增的一个id,这个id的唯一性由系统保证,为啥要有这个id呢,主要是为了防止服务在需要的时候被终止了,试想一下,如果你通过stopSelf()去终止服务的时候,可能有其他人正在执行onStartCommand,说明他正需要这个服务,但却被你终止了
  • 如果你使用stopSelfResult(int starId),那么由于其他人执行到onStartCommand已经产生了新的startId,那么你的这个终止服务的操作就会失效,这样其他人就可以正常使用服务了
  • 看到这里, 推荐你使用stopSelfResult(int starId)而不是stopSelf()
  • 终止服务有stopSelfResult和stopSelf两个方法,如下
  • 参数了解完了,让我们看看返回值,其实返回值就是告诉系统在服务被异常终止时该如何重新启动此服务,一般情况下直接用super即可,如果想知道详细的,可以看下这篇文章: Service的onStartCommand方法的返回值和参数详解_风行天下-CSDN博客_startcommand

ServiceConnection

  • 通过bindService这种方式需要一个ServiceConnection对象,这个对象主要有两个回调
new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {            }@Overridepublic void onServiceDisconnected(ComponentName componentName) {}};
  • 在绑定成功后onServiceConnected就会被回调,而且只会回调一次,也就是说你即使多次调用bindService,onServiceConnected也只会执行一次,只有当unbindService后再次bindService,onServiceConnected才会又被调用一次

  • onServiceDisconnected这个只有在服务崩溃或被终止时才会被调用,unbindService是不会调用到onServiceDisconnected的

  • onServiceConnected方法里的第二个参数就是我们在Service类里onBind方法返回的对象

场景说明

  • 下载任务的场景非常适合服务,因为你不可能在一个activity里启动下载,然后activity销毁就停止下载了吧,或者你启动下载后去干别的事了,干别的事的过程中又想知道下载的进度等等,那么结合使用startService和bindService就非常有用
  • 假如你有一个任务,这个任务没有界面,也不与任何activity有关系,那么你就可以使用startService,即使是在某个activity里调用startService的,但当activity销毁时service也不会停止,像下载任务这类就比较合适
  • 假如你已经运行到某个activity了,而且你知道后台有个服务在跑,你在某个activity里想知道这个服务的一些信息,那么就可以使用bindService,如果这个服务不存在,那么bindService会创建一个,但activity销毁时这个服务会销毁(如果有多个activity bind的话,那么当最后一个activity销毁时服务才会停止)
  • 假如你知道另外一个进程的服务,想与之交互,那么也可以通过bindService进行跨进程通信

前台服务

  • 服务几乎都是在后台运行的,但是服务的系统优先级还是比较低的,当系统出现内存不足的情况时,就有可能会回收正在后台运行的服务
  • 如果你希望可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,就可以考虑使用前台服务
  • 前台服务和普通服务最大的区别就在于,他会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果
  • 前台服务最重要的几个api就是
//这表明将要开启的是一个前台服务,用户必须自己在5秒内调用startForeground方法,否则就会产生奔溃
startForegroundService(...)
//启动前台服务,前面是一个id,只要不与其他人相同即可,后面的参数是一个Notification 对象,就是会在通知栏显示的那个
startForeground(NOTIFICATION_DOWNLOAD_PROGRESS_ID,notification);
//停止前台服务,参数表示是否需同时移除状态栏通知
stopForeground(true);
  • 另外,如果api在28(android9)及以上,则需要声明android.permission.FOREGROUND_SERVICE权限,这是个普通权限,在xml里声明一下即可,否则会抛SecurityException
  • 还有你可能想知道Service是否是前台服务(即是否调用过startForeground),则可以使用android.app.Service#getForegroundServiceType接口,不过此接口需要api29及以上才能调用

问答

startService和bindService顺序的影响

  • startService启动服务的优先级比较高,就是说当你bindService后再startService,那么当你unbindService后服务还是存在的

如果你的服务也想让其他应用启动那该怎么办

  • 可以使用隐式启动方式在清单文件中给服务一个过滤器,如
<service  android:name="com.example.myjavaexample.MyService"  android:enabled="true" >  <intent-filter android:priority="1000" >  <action android:name="com.abc.xxx.myservice" />  </intent-filter>  </service>
  • 然后其他应用就可以如下启动你的服务了
Intent intent=new Intent();
intent.setAction("com.abc.xxx.myservice");
intent.setPackage("com.example.myjavaexample");//设置应用的包名
startService(intent);

service被系统杀死后会执行到Service.onDestroy吗

  • 在不同的手机设备上这个行为不确定,经测试,通过开发者选项杀死正在运行的服务,有的能执行到onDestroy,有的并没有

其他

  • 当在activity里bindService而在activity销毁时没有手动调用unbindService时,会抛出类似异常
com.example.myjavaexample.MainActivity has leaked ServiceConnection com.example.myjavaexample.MainActivity$1@d26642d that was originally bound here
  • 这个异常只会打印在日志中,并不会导致你app挂掉

  • 当你bindService成功后在后台任务里把app杀掉,是不会调用onUnbind和onDestroy的

  • 有时发现调用unbindService时并没执行到onUnbind,概率性会这样,不知为何

  • 关于IntentService可以查看这篇文章:Android开发–IntentService的用法,你错过了什么 - 中国人醒来了 - 博客园

参考

  • (11条消息)Android Service介绍和使用_yh18668197127的博客-CSDN博客_android service
  • (12条消息)务必知道的Android service的完全详解_林一末的博客-CSDN博客_android service详解
  • (4条消息)Service的onStartCommand方法的返回值和参数详解_风行天下-CSDN博客_startcommand

Android Service服务的相关介绍相关推荐

  1. android开启服务应用禁止被杀死,Android Service服务如何不被杀死

    第一章 Service介绍 service服务是一个应用程序的四大组件之一,可以再后台执行长时间运行的操作,不提供用户界面.一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切到另一个应用 ...

  2. Android Service服务保活

    基于Android 10.11 实现的Service服务保活 最近公司要实现app程序不被杀死 实现持续定位,在网上看了很多个文章 也看到双进程保活,我忘了在那看到这篇文章了 下面 具体显现 创建 M ...

  3. Android Google 服务框架相关问题

    为什么80%的码农都做不了架构师?>>>    两年没发文了~ 先说现象: 1.定制 ROM,打包时在 /system/priv-app 目录下添加了谷歌服务框架相关 apk(Gms ...

  4. Android Service 服务(二)—— BroadcastReceiver

    一. BroadcastReceiver简介 BroadcastReceiver,用于异步接收广播Intent,广播Intent是通过调用Context.sendBroadcast()发送.Broad ...

  5. 【Android】Android Service 服务

    参考网址:http://blog.csdn.net/ithomer/article/details/7364024 一. Service简介 Service是android 系统中的四大组件之一(Ac ...

  6. Android Service 服务(一)—— Service

    一. Service简介 Service是android 系统中的四大组件之一(Activity.Service.BroadcastReceiver.ContentProvider),它跟Activi ...

  7. 学习笔记16 window service 服务的相关内容

    好久没使用window service 了 一同事问倒安装的问题.我突然不知道具体的步骤了. 于是转载别人的一篇blog 表示备用: 或者是用: WINDOW服务程序---制作安装全过程 链接是:ht ...

  8. Android中的sdk相关介绍

    简介 Sdk(software development kit)是指被软件工程师用于为特定的软件包.框架.硬件平台等建立应用软件的开发工具集,即软件开发工具包.就像前面配置java环境中的jdk类似, ...

  9. Android Binder ProcessState IPCThreadState相关介绍

    之前几篇博客我们介绍了传统Binder的使用方法,包括c层和java层,这篇博客我们主要介绍下ProcessState和IPCThreadState类的相关方法. 一.正常demon binder调用 ...

最新文章

  1. 存储组和数据库的区别?
  2. BTS3410G参数
  3. Docker 启动 nacos
  4. ListBox之随手放个控件
  5. mysql写php木马_PHP一句话木马小总结与SQL语句写一句话木马
  6. js代码 设为首页 加入收藏
  7. DALSA相机开发记录(01)
  8. vue中的组件重定向
  9. java如何实现容器_Java的容器都有哪些,怎么实现的
  10. Vensim建模--基于系统动力学的私人小汽车出行特征建模分析
  11. qq表情包html插件,jQuery QQ表情插件jquery.qqFace.js
  12. 查询2021高考成绩位次,2021年江苏高考位次表及高考个人成绩排名查询
  13. UMail轻松搭建linux邮件服务器(一体盘安装)
  14. 计算机中最小值的公式,用数组公式在数值列中查找大于指定值的最小值
  15. Linux关闭防火墙
  16. 小明打游戏(Java)
  17. 细数最近三年我的租房经历
  18. delete 和 delete []的真正区别
  19. html5css3选择题,web前端技术(HTML5+CSS3)答案试题题目及答案,期末考试题库,章节测验答案...
  20. VLC 0.1.99 源码分析

热门文章

  1. php实现上传图片功能,php实现上传图片功能
  2. Python 列表List处理
  3. AngularJS 实践:应用开发 :: ENA13 价格条码-(三)
  4. aspera 下载ENA 数据报错Error: Client unable to connect to server (check UDP port and firewall
  5. Linux下使用CURL Post文件+入参
  6. 老年机能玩的java游戏_情怀满满!教你如何用安卓机玩JAVA老游戏
  7. nginx yum安装后的文件路径
  8. 在ubuntu上为android系统编写Linux驱动程序【转】
  9. pgsql中distinct on的用法
  10. c/c++开发,无可避免的自定义类类型(篇三).类与虚函数