服务(Service)是Android系统中的四大组件之一,与Activity不同,它是不能与用户交互的。它是一种长生命周期、没有可视化界面、运行于后台的服务程序。比如我们播放音乐的时候,有可能想干其他事情,当退出播放音乐的应用,如果不用Service,我们就听不到歌;又比如一个应用的数据是通过网络获取的,不同时间(一段时间)的数据是不同的,这时候可以用Service在后台定时更新,而不用在打开应用的时候去获取。

1.本地服务

本地服务(Local Service)用于应用程序内部,可以实现应用程序的一些耗时任务,比如查询升级信息、网络传输,或者需要在后台执行,比如播放音乐并不占用应用程序的线程,而是在后台单开线程执行,从而使用户体验比较好。

1.2两种启动方式

Service有两种启动方式:Context.bindService()和Context.startService()。这两种方式对Service生命周期的影响是不同的。

1.通过Context.bindService(Intent intent,ServiceConnection conn,int flags)启动

(1)绑定时,bindService→onCreate()→onBind();绑定Service需要3个参数。

①intent:Intent对象,需要定义执行服务类。

②conn:ServiceConnection接口对象,创建该对象要实现它的onServiceConnected()和onServiceDisconnected()来判断是连接成功还是断开连接。

onServiceConnected(ComponentName name,IBinder service):系统调用该函数来传递由service的onBind()方法返回的IBinder。

onServiceDisconnected(ComponentName name):如果对service的连接意外丢失,比如当service奔溃或被杀死时,系统就会调用该函数。

bindService方法执行之后会自动调用ServiceConnection接口里的onServiceConnected方法;如果执行unbindService方法,则不会自动调用ServiceConnection接口里的onServiceDisconnected方法。因为ServiceConnection接口的onServiceDisconnected方法只会在Service被停止或者被系统杀死后调用,也就是说,执行unbindService只是告诉系统已经和这个服务没有关系了。在内存不足的时候,系统可以优先杀死这个服务。

这里需要注意一点的是,Service和需要绑定的Activity需要放在同一个包内,否则将无法调用ServiceConnection接口中的上述方法。

③flags:创建Service模式,一共有以下三种模式。

  • Service.BIND_AUTO_CREATE:指定绑定的时候自动创建Service,这是最常使用的模式。
  • Service.BIND_DEBUG_UNBIND:测试绑定的时候创建创建Service,这里进行调试所用的模式。
  • Service.BIND_NOT_FOREGROUND:不在前台进行绑定时创建Service。(例如后台播放音乐)

(2)解绑定时,unbindService→onUnbind()→onDestroy()。

此时如果调用者(如Activity)直接退出,Service由于与调用者绑定在一起,就会随着调用者一同停止。

用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。此时如果调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用Context.bindService()方法并不会导致多次创建服务及绑定(也就是说,onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用Context.unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()和onDestroy()方法。

下面以播放一首歌为例,新建一个工程项目,

音乐类(Music.java)的代码如下。

package com.example.demo_test_for_service_music;import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;import androidx.annotation.Nullable;public class Music extends Service {private MediaPlayer mediaPlayer;@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();this.mediaPlayer = MediaPlayer.create(this,R.raw.liekkas);this.mediaPlayer.start();}@Overridepublic void onDestroy() {super.onDestroy();this.mediaPlayer.stop();}
}

Music类继承自Service,它是一个服务,在创建的时候开始播放一首歌,在销毁的时候停止播放。在AndroidManifest.xml中进行配置并声明Action,配置文件如下。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.demo_test_for_service_music"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><service android:name=".Music"><intent-filter><action android:name="com.example.demo_test_for_service_music.Music"/></intent-filter></service></application></manifest>

播放类代码如下。

package com.example.demo_test_for_service_music;import androidx.appcompat.app.AppCompatActivity;import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}private  void initView(){Button playButton = findViewById(R.id.start);Button stopButton = findViewById(R.id.stop);}private View.OnClickListener clickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.start:bindService(new Intent("com.example.demo_test_for_service_music.Music"),null, Service.BIND_AUTO_CREATE);break;case R.id.stop:unbindService(null);default:break;}}};}

当点击播放时进行播放,当点击停止时音乐停止。当播放的时候退出程序,音乐也随之停止了。这就是用绑定方法启动服务产生的效果。有时候我们的需求并非这么简单,比如我们希望在播放音乐的时候,可以干其他事情,退出音乐播放界面后还要求音乐还能够继续在后台播放。第二种启动方式将有助于解决这一问题。

2.通过Context.startService(Intent intent)启动

(1)启动时,startService→onCreate()→onStart()

(2)停止时,stopService→onDestroy()

此时如果调用者(Activity)直接退出而没有停止Service,则Service会一直在后台运行。Context.startService() 方法启动服务,在Service未被创建时,系统会先调用Service的onCreate()方法,接着调用onStart()方法。如果调用Context.startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用Context.startService()启动的服务,只能调用Context.stopService()方法结束,服务结束时会调用onDestroy()方法。

在上一个例子中,如果退出程序后还能够播放音乐,我们只需改变它的启动方式即可,代码如下。

package com.example.demo_test_for_service_music;import androidx.appcompat.app.AppCompatActivity;import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}private  void initView(){Button playButton = findViewById(R.id.start);Button stopButton = findViewById(R.id.stop);}private View.OnClickListener clickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.start:startService(new Intent("com.example.demo_test_for_service_music.Music"));break;case R.id.stop:stopService(new Intent("com.example.demo_test_for_service_music.Music"));default:break;}}};}

1.2生命周期

Service生命周期一般有两种运行模式。

(1)在程序没有停止Service或者Service自己停止的情况下,Service将一直在后台运行。

在该模式下,Service通过Context.startService()方法开始,并通过Context.stopService()方法停止。当然,它也可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自身。stopService()方法只须调用一次便可停止服务。

(2)Service可以通过接口被外部程序调用。外部程序建立一个到Service的连接,并通过这个连接来操作Service。建立连接开始于Context.bindService(),结束于Context.unbindService()。多个客户端可以绑定到同一个Service。如果Service没有启动,可以通过Context.bindService()启动它。

这两种模式并不是完全分离,可以被绑定到一个通过Context.startService()启动的服务上。比如一个Intent想要播放音乐,就通过Context.startService()方法启动在后台播放音乐的Service。如果用户想要操作播放器或者获取当前正在播放的音乐的信息,一个新的Activity就会通过Context.bindService()建立一个到此Service的连接。举例如下。

//每一次进入该界面,都要绑定这个服务,这样才能查看在该服务器中所播放的音乐的信息
//而多次调用startService方法并不会每次都创建一个新的服务实例
bindService(new Intent(this,MusicService.class),conn,Context.BIND_AUTO_CREATE);
startService(new Intent(this,MusicService.class));
//像Activity一样,Service也有可以监视生命周期状态的方法,如下所示。
void onCreate()
void onStart(Intent intent)//由Context.startService()启动的服务所具有的方法
void onBind()//由Context.bindService()启动的服务所具有的方法
void onUnBind()//由Context.bindService()启动的服务所具有的方法
void onReBind()//由Context.bindService()启动的服务所具有的方法
void onDestroy

通过实现这几个方法,我们看一下Service的生命周期。

1.整个生命周期

Service的生命周期从onCreate()开始,到onDestroy()结束,跟Activity很类似。Service生命周期在onCreate()中执行初始化操作,在onDestroy()中释放所有用到的资源。如后台播放音乐可以在onCreate()创建一个播放音乐的线程,在onDestroy中销毁这个线程。

2.活动生命周期

Service的活动生命周期开始于onStart(),或者开始于onBind()方法。在音乐播放器中,使用Context.startService()方法启动,音乐服务会通过Intent来查看要播放哪首歌曲并开始播放。注意:onCreate()和onDestroy()用于所有通过Context.startService()或者Context.bindService()启动的Service,而onStart()只用于通过Context.startService() 开始的Service,onBind()则用于通过Context.bindService()启动的Service。

绑定的Service能触发以下的方法。

IBinder onBind(Intent intent)

boolean onUnbind(Intent intent)

void onRebind(Intent intent)

onBind()被传递给调用Context.bindService()的Intent,onUnbind被Context.unbindService()中的Intent使用。如果服务允许被绑定,那么onBind()方法返回客户端和Service的连接通道。如果一个新的客户端连接到服务,onUnbind()会触发onRebind()的调用。

2.远程服务

远程服务(Remote Service)用于Android系统内部的应用程序之间。

远程服务可以通过自己定义并暴露出来的接口进行程序操作。连接以调用Context.bindService()方法建立,以调用Context.unbindService()关闭。多个应用程序可以绑定至同一个服务。此时如果服务还没有加载,Context.bindService会先加载它。远程服务可被其他应用程序复用,比如天气预报服务,其他应用程序不再写这样的服务,调用已有的即可。

在Android系统中,一个进程通常不能直接访问其他进程的内存空间。如果要在不同的进程间传递对象,需要把对象解析成操作系统能够理解的数据格式,Android采用AIDL(Android Interface Definition Language,接口定义语言)的方式实现这个操作。

具体案例操作可以参考:https://blog.csdn.net/yancr/article/details/88978448?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161698224816780255221369%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=161698224816780255221369&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-88978448.first_rank_v2_pc_rank_v29&utm_term=aidl

3.服务小程序

在综合案例中,客户端需要定时与服务器进行交互,以获得最新的话题、私信以及好友的信息,并在界面中进行提示、刷新。MsgService类可以完成这些功能。

MsgService类继承自Service类,实现了其中的onCreate() 、onStar()、onBind()与onDestroy()方法,同时也实现了接口Runnable和其中的run()方法。

onCreate()方法初始化Service,并获得当前登录用户的用户名与密码信息,为请求服务器的参数设置做好准备。

onStart()方法利用Runnable开启一个线程,并运行run()方法,进行服务器的数据请求。在线程中请求是为了防止程序过多地占用内存。在run()方法中对所需要的数据进行不同的请求,通过调用request()方法来连网实现,并在request()方法中对结果进行判别,最后对返回的数据进行解析以完成数据库的更新和修改操作,run()方法中根据request()方法的返回结果进行判断是否有新数据插入数据库,是否需要刷新界面,若有,则要进行界面刷新,刷新UI界面的工作通过Handler来实现。在onStart()方法中,setNextRequestTime是设置定时启动服务的方法,因为涉及定时器类AlarmManager类,在此不多做叙述。

onBind()方法用来绑定服务。

onDestroy方法用来销毁此后台服务。

服务(Service)相关推荐

  1. linux 进程间通信 dbus-glib【实例】详解三 数据类型和dteeth(类型签名type域)(层级结构:服务Service --> Node(对象、object) 等 )(附代码)

    linux 进程间通信 dbus-glib[实例]详解一(附代码)(d-feet工具使用) linux 进程间通信 dbus-glib[实例]详解二(上) 消息和消息总线(附代码) linux 进程间 ...

  2. android打开位置服务,Android - 位置定位(Location)服务(Service)类的基本操作

    位置定位(Location)服务(Service)类的基本操作 本文地址: http://blog.csdn.net/caroline_wendy 定位服务(Location Service),能够确 ...

  3. Windows服务(Service)安装及启动停止方案

    目录 一.创作背景 二.问题解决 2.1 安装Windows service服务 2.2 主方法Main()主方法改写 2.3 安装service服务/卸载service服务 2.4 服务启停 2.5 ...

  4. 开机启动一个服务Service,启动后没有界面后台暗暗运行

    原文来自:http://blog.163.com/shaocpa@126/blog/static/553577572012418103732417/ 如果开机启动一个Activity,开机首先看的界面 ...

  5. 服务Service的基本用法

    作为 Android四大组件之一, 服务也少不了有很多非常重要的知识点,那自然要从最基本的用法开始学习了. 定义一个服务: public class MyService extends Service ...

  6. ubuntu启动、关闭、重启服务service命令

    查看当前所有服务 service --status-all 结果如下: zwl@zwl-NB50TJ1-TK1:~$ service --status-all[ + ] acpid[ - ] alsa ...

  7. android创建标题栏,【Android】利用服务Service创建标题栏通知

    创建标题栏通知的核心代码 public void CreateInform() { //定义一个PendingIntent,当用户点击通知时,跳转到某个Activity(也可以发送广播等) Inten ...

  8. [云原生专题-33]:K8S - 核心概念 - 服务Service管理、服务发现、负载均衡

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:https://blog.csdn.net/HiWangWenBing/article/detai ...

  9. ROS基础(二):ros通讯之服务(service)机制

    上一章内容链接: ROS基础(一):ROS通讯之话题(topic)通讯 目录 一.概念 二.实例 1. 小乌龟例程中的service 2. 自定义service 3. 创建服务器节点与客户端节点(c+ ...

  10. java message bus_【Microsoft Azure学习之旅】消息服务Service Bus的学习笔记及Demo示例...

    今年项目组做的是Cloud产品,有幸接触到了云计算的知识,也了解并使用了当今流行的云计算平台Amazon AWS与Microsoft Azure.我们的产品最初只部署在AWS平台上,现在产品决定同时支 ...

最新文章

  1. 安卓开发30:AsyncTask的用法
  2. 关于软件产品服务有感
  3. Java递归基础案例-回文字符串的判断
  4. nginx配合python_人生苦短我用python[0x02] nginx与python结合
  5. java爬取button_学习使用Java的webmagic框架爬取网页内容
  6. java中412是什么错_HTTP 412 错误 – 先决条件失败 (Precondition failed)
  7. 同一路由器下两台电脑ping不通_复杂网络环境下路由器配置问题导致业务故障处理案例分享...
  8. 专注于分布式存储计算技术及其应用url http://www.nosqlnotes.net/
  9. ssh隧道(通过跳板机)连接mysql
  10. Yii框架上传后展示图片
  11. 企业微信打卡统计员工考勤
  12. python 录制网易云登陆_Github获8300星!用Python开发的一个命令行的网易云音乐
  13. Wincc 7.5 SP1使用VBS创建Excel日报表并显示在画面
  14. c# 在word文件指定位置 插入图片
  15. 平头哥RVB2601开发板实现LED彩灯
  16. 手游堡垒之夜服务器没响应,堡垒之夜国际服点启动没反应 | 手游网游页游攻略大全...
  17. __getattr__和__setattr__
  18. Dell Precision7920工作站装双系统
  19. 对泛型上下限(协变,逆变)理解的拙见
  20. hive的自定义函数以及自定义加密函数

热门文章

  1. MySQL 8 复制(一)——异步复制
  2. gpg4win使用教程_使用gpg4win生成密钥对
  3. mashang6.edu.cn
  4. Synopsys工具安装之二【SCL License】
  5. 职场必备:十句外企 office 常用英语
  6. HTML为图片添加Alt描述,图片标签alt
  7. 《数据结构》第十一篇、线性表中的链式存储结构--循环链表
  8. [含lw+源码等]S2SH+mysql的报刊订阅系统[包运行成功]Java毕业设计计算机毕设
  9. html设计判断闰年,html5闰年判断函数
  10. 代码查重——LCS、Levenshtein距离、Jaro-Whinkle距离和变量代换