转自 原文

Service的理解

Service是什么?
Service是一种可以在后台运行相关任务的组件。没有界面。其存在的线程是主线程,一般会通过启动子线程来执行耗时操作。
Service有什么用?
可用于在后台执行下载任务。从而不影响用户界面操作。
Service分启动型服务、绑定型服务两种。
绑定服务中的创建Binder的扩展类的目的是什么?
该类主要用于获取Service的实例,以及执行相关的方法。
额外知识
1.不绑定服务,直接点击取消绑定服务会报错。因此需要通过判断Binder对象是否为空来处理。
2.服务可以不定义Action,通过Intent指定要跳转的Service即可。
3.Service的有效范围是所有满足条件的Activity。
4.在Service里执行耗时操作会导致ANR,启动新的线程执行耗时操作可有效避免。

两种服务的区别

Service类型 说明 使用步骤
启动型服务 1.生命周期为onCreate->onStartCommand->onDestroy 
2.服务一旦启动后,需要调用stopService方法或stopSelf方法才能停止。 
3.可常驻系统。
1.通过调用startService启动服务 
2.通过stopService停止服务
绑定型服务 1.生命周期为onCreate->onBind->onUnbind->onDestory 
2.需要返回Binder对象,即定义Binder的子类。
3.通过Binder子类的方法来获取Service对象,用于与Activity交互。 
4.在Activity中需要通过创建ServiceConnection对象来获取service实例。从而调用service里的方法。
1.通过bindService绑定服务 
2.通过unbindService取消绑定服务

Service生命周期

Service的类型及其示例

启动型服务 - StartService

使用
1.创建java类继承Service
2.重写onStart、onCreate等方法。
3.在onCreate中新开子线程,用于执行任务。

示例 - 启动型服务

Service作用
打印0-2000的数字,完毕后停止服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class CalcService extends Service {
private int total;
private boolean openService; //结束服务时的标识 public CalcService() {
} @Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
} @Override
public void onCreate() {
super.onCreate();
LogTool.e("CalcService", "onCreate");
} @Override
public int onStartCommand(final Intent intent, int flags, final int startId) { LogTool.e("CalcService", "onStartCommand");
Functions.toast("Service已启动,请查看LOG");
//启动线程执行耗时操作。通常是下载之类的任务
new Thread(new Runnable() {
@Override
public void run() {
while (!openService) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
LogTool.e("CalcService", total);
total++;
builder.setSubText("total:" + total);
if (total == 2000) {
stopSelf();
}
}
}
}).start();
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
super.onDestroy();
LogTool.e("CalcService", "onDestroy");
Functions.toast("CalcService已停止,请查看LOG");
openService = true;
}
}
1
2
3
4
5
// Activity中的代码
public void startService(View v){
Intent intent = new Intent(this,CalcService.class);
startService(intent);
}

绑定型服务 - BindService

BindService(Intent,ServiceConnection,Context.BIND_AUTO_CREATE)
参数分别为Intent,ServiceConnection,标识号。通常为BIND_AUTO_CREATE。
使用
1.创建java类继承Service
2.创建Java类继承Binder类。用于返回Service实例。
3.重写onBind、onUnBind等方法。
4.在Activity中创建ServiceConnection对象,并获取Binder实例。
ps:为防止未绑定服务,用户点击取消绑定而导致的崩溃。需要对unbindService进行边缘性处理。

示例 - 普通绑定型服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class BindService extends Service {
private BindService service;
private TestBinder binder = new TestBinder();
private int count = 0; public class TestBinder extends Binder {
//通过Binder对象来获取服务对象,从而调用服务里的方法
public BindService getService() {
if (service == null) {
service = new BindService();
}
return service;
}
} private boolean closeThread; public BindService() {
} @Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
@Override
public void run() {
while (!closeThread) {
LogTool.e("BindService", "count:" + count);
count++;
}
}
}).start();
} @Override
public TestBinder onBind(Intent intent) {
LogTool.e("BindService", "onBind");
return binder;
} @Override
public void onDestroy() {
super.onDestroy();
this.closeThread = true;
LogTool.e("BindService", "onDestroy");
Functions.toast("BindService已停止");
} @Override
public boolean onUnbind(Intent intent) {
LogTool.e("BindService", "onUnbind");
return true;
} public void startDownload() {
Functions.toast("开始执行耗时任务,点击UnbindService按钮或返回按钮可取消任务");
} }

Activity中的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (BindService.TestBinder) service;
binder.getService().startDownload();
} @Override
public void onServiceDisconnected(ComponentName name) {
Functions.toast("断开连接");
LogTool.e("BindService", "serviceDisconnected");
}
}; //启动服务
public void BindService(View v) {
Intent intent = new Intent(this, BindService.class);
bindService(intent, connection, Service.BIND_AUTO_CREATE);
} // 取消绑定服务,边缘性处理
public void UnbindService(View v) {
if (binder != null) {
unbindService(connection);
}
}

示例 - 绑定型远程服务

理解
如何定义远程服务?
在配置文件中添加代码android:progress=”:remote”即可
为什么设置了Service为远程Service就不会导致ANR了?
远程服务是指将服务放到另一个进程中执行,所以就不会导致程序的ANR现象。
如何跨进程与Activity进行通信? 见示例
如何实现跨程序通信?

示例 - 实现跨进程与Activity交互

步骤
1.创建aidl文件,定义接口(TestInterface)及相关方法。点击make project,自动生成Stub相关的接口。
2.创建Service类,并在ManiFest文件设置远程属性。android:process=”:remote”
3.在Service中创建接口TestInterface.Stub 对象,重写接口方法。
4.在Activity中通过AIDL接口的asInterface方法来获取AIDL对象。
5.利用接口对象调用相关方法。

1
2
3
4
5
// 创建aidl文件,定义接口。
package io.tanjundang.study.test.service;
interface RemoteAidlInterface {
void calcMsg();
}
1
2
3
4
// 配置服务远程属性
<service
android:name=".test.service.RemoteService"
android:process=":remote" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Service中创建远程接口的Stub对象
public class RemoteService extends Service { RemoteAidlInterface.Stub mBinder = new RemoteAidlInterface.Stub() {
@Override
public void calcMsg() throws RemoteException {
LogTool.e("RemoteService", "66666");
}
}; @Override
public Binder onBind(Intent intent) {
return mBinder;
} }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Activity中调用远程接口的方法
public class RemoteActivity extends AppCompatActivity { private RemoteAidlInterface mBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBinder = RemoteAidlInterface.Stub.asInterface(iBinder);
try {
mBinder.calcMsg();
} catch (RemoteException e) {
e.printStackTrace();
}
} @Override
public void onServiceDisconnected(ComponentName componentName) { }
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_remote);
} public void StartRemoteService(View v) {
Intent intent = new Intent(this, RemoteService.class);
bindService(intent, connection, BIND_AUTO_CREATE);
} public void UnbindRemoteService(View v) {
if (mBinder != null) {
unbindService(connection);
}
}
}

示例 - 实现跨程序与Activity交互

步骤
实现步骤跟上面类似。只是需要为Service定义Action,以及将AIDL接口及其包名复制到另一程序中。即可实现跨程序交互。

IntentService

理解
为什么有这个类?
该类是Service的子类,主要是简化了异步操作繁琐复杂的代码。
有什么特点?
1.不需要自己创建子线程。
2.不需要考虑何时关闭服务。
使用情景是什么?
多次调用startService。
使用
1.Service继承IntentService。
2.以类名为参数调用父类构造方法。
3.重写onHandleIntent核心方法以及其他方法。

前台服务

什么是前台服务?
普通服务在内存不足的情况下会被系统杀掉,而前台服务不会因为内存不足而被杀掉。
前台服务有什么特点?
前台服务有通知栏提示,可设定相关的标题、提示灯。例如天气、播放器等。
前台服务的使用
1.构建Notification对象。
2.通过startForeground方法启动通知栏。
3.通过stopForeground方法关闭通知栏。
注意
Notification的构建中,若不调用setSmallIcon方法设置Icon,其他相关设置(标题、提示)均无效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public int onStartCommand(final Intent intent, int flags, final int startId) {
final NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(getApplicationContext(), MainActivity.class), 0));
builder.setContentTitle("前台服务");
//不知道什么鬼,不设置Icon,其他信息都不显示
builder.setSmallIcon(R.drawable.ic_menu_camera);
builder.setContentText("二级子标题");
builder.setSubText("三级子标题");
Notification notification = builder.build();
//开启通知栏提示
startForeground(startId, notification);
LogTool.e("CalcService", "onStartCommand");
Functions.toast("Service已启动,请查看LOG");
total = intent.getIntExtra("msg", 100);
return super.onStartCommand(intent, flags, startId);
}

Service官方文档
郭林大神ADIL服务
绑定服务

Service的理解的更多相关文章

  1. 【Java】对Web Service的理解

    WSDL(Web Service Description Language)是描述Web Service的语言. 你会怎样向别人介绍你的Web service有什么功能,以及每个函数调用时的参数呢?你 ...

  2. Java Web Action DAO Service层次理解

    参考来源:http://blog.csdn.net/inter_peng/article/details/41021727 1. Action/Service/DAO简介: Action是管理业务(S ...

  3. Springboot的entity,dao,controller,service层级理解

    1.Dao层:持久层,主要与数据库交互 DAO层首先会创建Dao接口,接着就可以在配置文件中定义该接口的实现类:接着就可以在模块中调用Dao的接口进行数据业务的处理,而不用关注此接口的具体实现类是哪一 ...

  4. web service的理解

    http://blog.csdn.net/u011075267/article/details/41522643

  5. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  6. Android组件系列----Android Service组件深入解析

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  7. Android应用开发基础篇(6)-----Service

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/20/2360336.html 一.概述 我们知道,Service是Android的四大组件之一. ...

  8. service and intentservice

    Service是Android中四大组件之一,在Android开发中起到非常重要的作用,先来看一下官方对Service的定义: A Service is an application componen ...

  9. 关于Service中bindService注意的几个问题

    最近有用到Activity需要不断的从Service中获取数据,第一个想法肯定就是通过bind回调机制了,有几点概念模糊特此记录下: 单独使用bindService(),unbindService() ...

随机推荐

  1. null!= xxx 和 xxx!=null有什么区别?

    从意义上将没有区别,从编程规范上讲,第一种写法是为了防止写成:null = xxx

  2. Android Log工具之Luffy

    Luffy Luffy可以在手机端实时显示你App中的logcat输出.并且具有Log等级与Tag过滤功能.另外Luffy还支持收集Log,保存Log和查看本地log功能. 使用方法 1.Gradle ...

  3. 转SpringMVC Controller 返回值的可选类型

    spring mvc 支持如下的返回方式:ModelAndView, Model, ModelMap, Map,View, String, void. ModelAndView @RequestMap ...

  4. 哈哈哈 迫于c#的语言特性java才加的注解

  5. 决策树ID3算法python实现 -- 《机器学习实战》

    from math import log import numpy as np import matplotlib.pyplot as plt import operator #计算给定数据集的香农熵 ...

  6. Powershell About Active Directory Server

    一.获取域控制器服务器清单 (Get-ADForest).Domains | %{ Get-ADDomainController -Filter * -Server $_ } | select hos ...

  7. mvel

    https://en.wikipedia.org/wiki/MVEL import java.util.*; // the main quicksort algorithm def quicksort ...

  8. 模块化之SeaJS(一)

    模块化(之SeaJS) 刚接触的童鞋可能会有很多疑惑,比喻:什么是模块?模块的目的是干嘛呀?怎么样实现模块化呢? 不要急,博主正是带着这三个问题来写这篇文章的. 一,什么是模块化? 在前端开发领域,一 ...

  9. 如何查看python的api

    如何查看python selenium的api   经常发现很多同学装好了python+selenium webdriver开发环境后不知道怎么去查看api文档,在这里乙醇简单介绍一下具体方法,其实非 ...

  10. pip与apt-get

    在ubuntu服务器下安装包的时候,经常会用到sudo apt-get install 包名 或 sudo pip install 包名,那么两者有什么区别呢? 1.区别 pip用来安装来自PyPI( ...