Android四大组件-服务
Android服务
android 的服务有点类似windows的服务,没有界面,在后台长时间运行,如果我们这种需求的话我们就可以使用服务来实现。
服务的典型应用场景: 播放音乐,下载等,如果要在一个广播接收者中执行一些耗时的操作,可以将此操作转交给服务来执行。
服务也有自己的生命周期,但是要是相对Activity要少了许多。
服务的生命周期
图片来自于官方文档
使用服务
如果你想要使用服务,那么必须要有一个来继承【Service 】类,并且在清单文件中配置他。
配置服务:在清单文件中对服务进行配置
<!--配置一个服务,与Activity的配置基本相同,都可以具有Intent-Filter-->
<service android:name=".MyService">
<intent-filter>
<action android:name="MyAction" />
</intent-filter>
</service>
建立服务类: 新建一个类继承自Service
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
startService 的方式开始服务
- 一旦开启就会长久的存在,就算是没有界面了那么也会在后台运行,没有界面的时候就会是一个服务进程,如果没有特殊的情况下次进程是不会被结束的,除非 用户手动停止或者调用onStop() 方法。
- 可以多次开启,如果点击按钮开启服务多次点击按钮的话就会执行多次的onStartCommand方法,但是onCreate方法仅仅执行一次。
- 用户可以再设置中查看通过此方式开启的服务
public class MainActivity extends AppCompatActivity {
private Intent intentService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentService = new Intent(this, PhoneListenerService.class);
}
//开启个服务
public void click(View v) {
this.startService(this.intentService);
}
//停止服务
public void click2(View v) {
this.stopService(this.intentService);
}
bindService 的方式开启服务
- 一般在Activity中开启,如果activity销毁了那么通过此方式绑定服务也会跟着销毁在activity销毁之前要先解绑服务。
- 这种方式开启的服务用户在设置中是无法看到的。
public class Main1Activity extends AppCompatActivity {
private Intent serviceIntent;
private MyServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
serviceIntent = new Intent(this, MyService.class);
conn = new MyServiceConnection();
}
//绑定一个服务
public void click3(View v) {
this.bindService(this.serviceIntent, this.conn, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(this.conn);
}
}
class MyServiceConnection implements ServiceConnection {
//当服务连接成功后会调用此方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogHelper.Logi("连接到服务");
}
//当失去连接的时候回调用此方法
@Override
public void onServiceDisconnected(ComponentName name) {
LogHelper.Logi("取消连接");
}
}
为什么要有Bind方式开启服务
下面我们有这么个需求,我要调用服务里面的方法。
正常的调用方式
服务代码
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
LogHelper.LogI("onBind");
return null;
}
@Override
public void onCreate() {
super.onCreate();
LogHelper.LogI("onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogHelper.LogI("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
LogHelper.LogI("onDestory");
}
//我想在activity中调用的方法
public void showToast() {
Toast.makeText(this.getApplicationContext(), "Toast", Toast.LENGTH_SHORT).show();
}
}
调用代码
public class Main1Activity extends AppCompatActivity {
private Intent serviceIntent;
private MyServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
serviceIntent = new Intent(this, MyService.class);
conn = new MyServiceConnection();
//绑定服务
bindService(this.serviceIntent, conn, BIND_AUTO_CREATE);
}
/*
* 直接通过new出来对象的方式来调用服务中的方法
* */
public void click(View v) {
new MyService().showToast();
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(this.conn);
}
}
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
总结
这样的方式调用service中的方法,就会直接挂掉.....,因为如果这样直接new出来的服务类的话,系统就会将他当成一个普通的java类来处理,在普通的java类中是不能获得上下文对象的,所以就不能弹出吐司,如果没有涉及的上下文的方法,那么这样是可以执行的。
解决办法
通过一个中间人来调用我们想要调用的方法
服务端代码
public class MyService extends Service {
/*
* 通过bind方式开启服务 会执行onCreate()->onBind()方法
* 此方法返回我们需要的中间人,来调用服务中的方法
* */
@Nullable
@Override
public IBinder onBind(Intent intent) {
LogHelper.LogI("onBind");
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
LogHelper.LogI("onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogHelper.LogI("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
LogHelper.LogI("onDestory");
}
//我们想要调用的方法
public void showToast() {
Toast.makeText(this.getApplicationContext(), "Toast", Toast.LENGTH_SHORT).show();
}
/*
* 定义中间人
* 间接的调用我们想要调用的方法
* */
public class MyBinder extends Binder {
public void callShowToast() {
showToast();
}
}
}
Activity代码
public class Main1Activity extends AppCompatActivity {
private Intent serviceIntent;
private MyServiceConnection conn;
private MyService.MyBinder callBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
serviceIntent = new Intent(this, MyService.class);
conn = new MyServiceConnection();
//绑定服务
bindService(this.serviceIntent, conn, BIND_AUTO_CREATE);
}
/*
* 通过定义的中间人来调用方法
* */
public void click(View v) {
this.callBinder.callShowToast();
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(this.conn);
}
public class MyServiceConnection implements ServiceConnection {
/*
* 当连接到服务的时候就会执行此方法,在这个方法拿到我们的中间人用来调用我们想要调用的方法
* service参数就是我们想要的中间人
* */
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
callBinder = (MyService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
混合方式绑定服务
现在有一种情况,如果我要做一个音乐盒的功能那么我必须在所有界面都退出了还能播放那么这时候,我们一定是要有一个startService方式开启的服务来一直播放音乐, 但是我得需要调用服务中的方法来控制音乐的播放和暂停等,这就需要混合方式开启服务了。
混合方式开启服务的步骤
- startService()
- bindService()
- unbiasedServices()
- stopService()
Demo 音乐播放器 案例
服务的代码
public class MusicService extends Service {
private boolean isPlay = true;
private boolean isDestroy = false;
public MusicService() {
}
@Override
public IBinder onBind(Intent intent) {
LogHelper.LogI("onBind");
return new MyBinder();
}
@Override
public void onCreate() {
LogHelper.LogI("onCreate!");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogHelper.LogI("onStart");
playMusic();
return super.onStartCommand(intent, flags, startId);
}
//在服务被销毁的时候,结束线程
@Override
public void onDestroy() {
LogHelper.LogI("onDestory");
this.isDestroy = true;
super.onDestroy();
}
//开启线程不停的播放音乐
public void playMusic() {
new Thread(new Runnable() {
@Override
public void run() {
while (!isDestroy)
if (isPlay) {
LogHelper.LogI("Play Music!");
SystemClock.sleep(1000);
}
}
}).start();
}
//暂停音乐播放
public void stopMusic() {
this.isPlay = false;
LogHelper.LogI("暂停播放音乐!");
}
//继续播放音乐
public void continueMusic() {
this.isPlay = true;
LogHelper.LogI("继续播放音乐!");
}
//用来调用服务的方法的中间人
private class MyBinder extends Binder implements IMusicControlAble {
@Override
public void callStopMusic() {
stopMusic();
}
@Override
public void callContinueMusic() {
continueMusic();
}
}
}
IMusicControlAble接口代码
public interface IMusicControlAble {
//暂停音乐播放
public void callStopMusic();
//继续播放音乐
public void callContinueMusic();
}
MainActivity的代码
public class Main1Activity extends AppCompatActivity {
private Intent intentMusicService;
private MyServiceConnection connMusicService;
private IMusicControlAble musicControl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
intentMusicService = new Intent(this, MusicService.class);
connMusicService = new MyServiceConnection();
this.bindService(this.intentMusicService, this.connMusicService, BIND_AUTO_CREATE);
this.startService(this.intentMusicService);
}
public void click(View v) {
Button btn = (Button) v;
switch (btn.getText().toString()) {
case "暂停":
this.musicControl.callStopMusic();
btn.setText("播放");
break;
case "播放":
this.musicControl.callContinueMusic();
btn.setText("暂停");
break;
}
}
//接触对服务的绑定
@Override
protected void onDestroy() {
this.unbindService(this.connMusicService);
super.onDestroy();
}
public class MyServiceConnection implements ServiceConnection {
//拿到用来控制音乐状态的接口
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
musicControl = (IMusicControlAble) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
Android四大组件-服务的更多相关文章
- 入职小白随笔之Android四大组件——服务(Service)
Service Android多线程编程 当我们在程序中执行一些耗时操作时,比如发起一条网络请求,考虑到网速等原因,服务器未必会立刻响应我们的请求,此时我们就需要将这些操作放在子线程中去运行,以防止主 ...
- Android四大组件--服务(Service)
1. startService和bindService的区别 1. startService: 生命周期: onCreate---onStartCommand---onDestory 与服务的通讯: ...
- Android四大组件之一“广播”
前言 Android四大组件重要性已经不言而喻了,今天谈谈的是Android中的广播机制.在我们上学的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要的通知,就 ...
- Android 四大组件 与 MVC 架构模式
作为一个刚从JAVA转过来的Android程序员总会思考android MVC是什么样的? 首先,我们必须得说Android追寻着MVC架构,那就得先说一下MVC是个啥东西! 总体而来说MVC不能说是 ...
- android四大组件(简单总结)
activity 一个Activity通常就是一个单独的屏幕(窗口) Activity之间通过Intent进行通信 android应用中每一个Activity都必须要在AndroidManifest. ...
- Android 四大组件之再论service
service常见的有2种方式,本地service以及remote service. 这2种的生命周期,同activity的通信方式等,都不相同. 关于这2种service如何使用,这里不做介绍,只是 ...
- Android四大组件及activity的四大启动模式
Android四大组件 1. 广播接收者的两种类型: (1)系统广播接收者,就是继承BroadcastReceiver这个类,然后还要在清单文件中注册,注册之后给他一个action.当系统发生了这个a ...
- Android成长日记-Android四大组件之Service组件的学习
1.什么是Service? Service是Android四大组件中与Activity最相似的组件,它们都代表可执行的程序,Service与Activity的区别在于:Service一直在后台运行,它 ...
- Android四大组件之Service
Android四大组件之Service Android支持服务的概念,服务是在后台运行的组件,没有用户界面,Android服务可用有与活动独立的生命周期.Android支持两种类型的服务: 本地服务: ...
随机推荐
- Linux日志文件/var/log详解
更多内容推荐微信公众号,欢迎关注: 如果愿意在Linux环境方面花费些时间,首先就应该知道日志文件的所在位置以及它们包含的内容.在系统运行正常的情况下学习了解这些不同的日志文件有助于你在遇到紧急情况时 ...
- [Openwrt 扩展上篇]USB挂载&U盘启动&Samba共享
最近偷懒,没学习,反想起自己的路由刷了Openwrt,正好闲置了一个硬盘想拿来做个网络硬盘,于是开始了折腾....这里将不谈论如何刷Openwrt,如何ssh,如何添加PPOE,如何添加相对应服务的包 ...
- js面向对象编程思想
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- RPC简介与hdfs读过程与写过程简介
1.RPC简介 Remote Procedure Call 远程过程调用协议 RPC——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些 ...
- codepage 和 charset
codepage:简单地说,这是程序用于对字符进行编码的一个表.代码页是服务器的事情. 常见的三种codepage 简体中文 : 936 繁体中文 : 950 UTF-8 : 65001 如果你不想用 ...
- #ifdef __cplusplus extern "C" { #endif”的定义的含义
看一些程序的时候老是有“#ifdef __cplusplusextern "C" {#endif”的定义,搞搞清楚是怎么回事: Microsoft-Specific Predefi ...
- C# 执行固定个数任务自行控制进入线程池的线程数量,多任务同时但是并发数据限定
思路来源:http://bbs.csdn.NET/topics/390819824,引用该页面某网友提供的方法. 题目:我现在有100个任务,需要多线程去完成,但是要限定同时并发数量不能超过5个. 原 ...
- C# 日文网址转punnycode
Uri uri = new Uri(url); IdnMapping idn = new IdnMapping();url= url.Replace(uri.Host, idn.GetAscii(ur ...
- 使用postman做接口测试(一)
参考大神的总结:https://www.cnblogs.com/Skyyj/p/6856728.html 一,先了解一下基础知识,虽然工作中没什么卵用,但背会了,可以显摆自己很专业的样子,以下内容来自 ...
- 24 The Go image package go图片包:图片包的基本原理
The Go image package go图片包:图片包的基本原理 21 September 2011 Introduction The image and image/color packag ...