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四大组件-服务的更多相关文章

  1. 入职小白随笔之Android四大组件——服务(Service)

    Service Android多线程编程 当我们在程序中执行一些耗时操作时,比如发起一条网络请求,考虑到网速等原因,服务器未必会立刻响应我们的请求,此时我们就需要将这些操作放在子线程中去运行,以防止主 ...

  2. Android四大组件--服务(Service)

    1. startService和bindService的区别 1. startService: 生命周期: onCreate---onStartCommand---onDestory 与服务的通讯: ...

  3. Android四大组件之一“广播”

    前言 Android四大组件重要性已经不言而喻了,今天谈谈的是Android中的广播机制.在我们上学的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要的通知,就 ...

  4. Android 四大组件 与 MVC 架构模式

    作为一个刚从JAVA转过来的Android程序员总会思考android MVC是什么样的? 首先,我们必须得说Android追寻着MVC架构,那就得先说一下MVC是个啥东西! 总体而来说MVC不能说是 ...

  5. android四大组件(简单总结)

    activity 一个Activity通常就是一个单独的屏幕(窗口) Activity之间通过Intent进行通信 android应用中每一个Activity都必须要在AndroidManifest. ...

  6. Android 四大组件之再论service

    service常见的有2种方式,本地service以及remote service. 这2种的生命周期,同activity的通信方式等,都不相同. 关于这2种service如何使用,这里不做介绍,只是 ...

  7. Android四大组件及activity的四大启动模式

    Android四大组件 1. 广播接收者的两种类型: (1)系统广播接收者,就是继承BroadcastReceiver这个类,然后还要在清单文件中注册,注册之后给他一个action.当系统发生了这个a ...

  8. Android成长日记-Android四大组件之Service组件的学习

    1.什么是Service? Service是Android四大组件中与Activity最相似的组件,它们都代表可执行的程序,Service与Activity的区别在于:Service一直在后台运行,它 ...

  9. Android四大组件之Service

    Android四大组件之Service Android支持服务的概念,服务是在后台运行的组件,没有用户界面,Android服务可用有与活动独立的生命周期.Android支持两种类型的服务: 本地服务: ...

随机推荐

  1. 一个愚蠢的python逻辑语法错误

    这个事情再次佐证了一个莫名其妙的现象背后一定会有一个愚蠢到无以复加的错误的真理. 写python单元测试的时候发现一个莫名其妙的问题: def xmlStandander(self,s): retur ...

  2. 基本控件文档-UISwitch属性

    CHENYILONG Blog 基本控件文档-UISwitch属性 Fullscreen     UISwitch属性 技术博客http://www.cnblogs.com/ChenYilong/ 新 ...

  3. laravel更新某一个或几个字段

    //更新会员状态status $ary_where = array(); $ary_where[] = ['id', '=', $int_id]; $result = $this->obj_ad ...

  4. mysql 时间戳

    需求:记录表中每条记录创建时间和最新修改时间 一.界面操作 工具:mysql-front 右键添加字段createTime和updateTime,字段类型为timestamp 完成,在表中添加一条新纪 ...

  5. 20155303 2016-2017-2 《Java程序设计》第四周学习总结

    20155303 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 第六章 继承与多态 6.1 何谓继承 继承避免多个类间重复定义共同行为,使用关键字exten ...

  6. win10安装

    1.启动盘制作 首先我们需要登陆“微软中国下载中心”,从中下载一款名为“MediaCreationTool”的工具,利用该工具可以制作Win10安装U盘.直接通过以下地址快速进入“Windows下载中 ...

  7. flask基础之蓝图的使用(七)

    前言 关于蓝图是什么?或为什么使用蓝图的详细介绍,官方文档讲的很详细,不再赘述.简单来说,在大型的应用中,我们不想视图函数显得杂乱无章,难以维护,将众多的视图函数按照Api的设计规则进行切割是一个好方 ...

  8. 如何用Percona XtraBackup进行MySQL从库的单表备份和恢复【转】

    前提 应该确定采用的是单表一个表空间,否则不支持单表的备份与恢复. 在配置文件里边的mysqld段加上 innodb_file_per_table = 1 环境说明: 主库:192.168.0.1 从 ...

  9. Tomcat的JVM设置和连接数设置

    Windows环境下修改“%TOMCAT_HOME%\bin\catalina.bat”文件,在文件开头增加如下设置:set JAVA_OPTS=-Xms256m -Xmx512m Linux环境下修 ...

  10. java 一个函数如何返回多个值

    在开发过程中,经常会有这种情况,就是一个函数需要返回多个值,这是一个问题!! 网上这个问题的解决方法: 1.使用map返回值:这个方法问题是,你并不知道如何返回值的key是什么,只能通过doc或者通过 ...