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练习-函数版-锁定三次登陆失败的用户

    代码如下: # 编辑者:闫龙 if __name__ == '__main__': import UserLoginFuncation LoclCount=[]; while True: UserNa ...

  2. iOS学习笔记(4)— UITableView的重用机制

    UITableView中的cell是动态的,在使用过程中,系统会根据屏幕的高度(480)和每个cell的高度计算屏幕中需要显示的cell的个数.比如,cell高度为90.那么480 / 90 = 5  ...

  3. mybatis查询参数为0时无法识别问题

    最近在工作中遇到一个mybatis参数问题,主要是列表查询按照状态进行过滤,其中已完成状态值是0,被退回是1.如图所示 , 然后Mapper里面是和平常一样的写法<if test="s ...

  4. 个性化你的Git Log的输出格式

    git已经变成了很多程序员日常工具之一. git log是查看git历史的好工具,不过默认的格式并不是特别的直观. 很多时候想要更简便的输出更多或者更少的信息,这里列出几个git log的format ...

  5. 2.Centos-Docker-shipyard中文版安装

    1.准备(所有服务器都要执行) a.设置主机名和hosts vi /etc/hosts 192.168.1.2 centos-master 192.168.1.4 centos-minion-2 b. ...

  6. Python生成器-博文读后感

    Windows 10家庭中文版,Python 3.6.4, 上午看过了一篇讲Python生成器的博文: 提高你的Python: 解释‘yield’和‘Generators(生成器)’(英文原文) 这篇 ...

  7. python基础-类的反射

    1)反射是通过字符串方式映射内存中的对象. python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr, 改四个函数分别用于对对象内部执行:检查是 ...

  8. RNN BPTT

    双向LSTM

  9. ioctl()函数获取本机IP、MAC

    #include <sys/ioctl.h> int ioctl(int d, int request, ...); /* Socket configuration controls. * ...

  10. tensorflow高级库

    1.tf.app.flags tf定义了tf.app.flags,用于支持接受命令行传递参数,相当于接受argv.tf.app.flags.DEFINE_xxx()就是添加命令行的optional a ...