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. 用Grub4dos引导,硬盘安装ArchLinux

    本来在工作机上用winXP,最近想深入Linux开发,于是决定装个Linux.家里的archLinux + awesome用得很好, 于是决定在工作机上也装一套. 不想刻盘,也不想用U盘,通过Grub ...

  2. java与Excel (.xls文件) ---使用JXL创建,增添表格文件

    由于一些原因要搞一下excel文件,个人感觉poi太难,所以用了JXL(感觉比较简单). 1.添加外部归档 jxl.jar 2. /** 生成的xls文件第一次需要手动选择EXCEL打开* * */ ...

  3. HDU 2722 Here We Go(relians) Again (最短路)

    题目链接 Problem Description The Gorelians are a warlike race that travel the universe conquering new wo ...

  4. STL-map and multimap

    定义 map<int,int> a; map<int,string> a; map<double,int> a; …… 首先要知道的一些 Map是STL的一个关联容 ...

  5. Python练习-不知道弄个什么鬼

    Alex大神,今天丢过来一个PDF,结果就成了这个样子! 1.  执行 Python 脚本的两种方式 交互方式:                   命令行 文件方式:                 ...

  6. 弹性盒模型justify-content属性

    justify-content是应用于父容器上来规定子元素在水平方向上的对齐方式的. flex-start 左对齐 flex-end 右对齐 center 居中 space-betten 两端对齐,两 ...

  7. Dream------Java--ant zip 对压缩文件进行指定位置的修改

    ant zip 对压缩文件进行指定位置的修改 实现功能: 对2中文件进行修改: 需求: 在XX文件中,从二进制流的200字节位置开始,往后的30位字节数量.插入一个值 由于涉及到公司内部,不方便写太多 ...

  8. dump函数

    一.函数标准格式: DUMP(expr[,return_fmt[,start_position][,length]]) 基本参数时4个,最少可以填的参数是0个.当完全没有参数时,直接返回null.另外 ...

  9. 【逆向知识】PE ASLR

    1.知识点 微软从windows vista/windows server 2008(kernel version 6.0)开始采用ASLR技术,主要目的是为了防止缓冲区溢出 ASLR技术会使PE文件 ...

  10. ksh函数

    在不同的shell环境里,shell脚本的写法是不同的 此链接为ksh环境的函数写法: https://blog.csdn.net/shangboerds/article/details/487115 ...