Service是一种能长期在后台运行同一时候不须要与用户进行交互的应用组件。其它组件能够开启service,开启后service能够自行运行及时用户已经切换到其它的应用。此外,组件能够与service进行绑定来进行交互。及时是跨进程的交互(Android的IPC机制)。网络操作、播放音乐、运行文件IO操作或是与内容提供者进行交互,这些操作都能够通过service在后台进行。

Service的两种形式:

Started

通过调用startService()。你能够启动一个service。一旦被启动,service能够独立的运行在后台,即使启动的组件被销毁。

通常,被启动的service用来运行一个单一的操作,而且没有返回值。比如,下载网络上的一个文件。

当操作运行完毕后。service应当自行结束。

Bound

通过调用bindService(),你能够绑定一个service。一个被绑定的service通常会提供一个接口用来与组件进行交互、发送请求、获取结果、甚至进行进程间的交互(IPC)。

被绑定的service的生命周期和其绑定的组件同样。虽然多个组件能够同一时候绑定一个service,可是但全部这些组件进行解绑后。service会被销毁。

虽然文档中通常会对两种形式的service分开介绍,可是你能够同一时候开启和绑定service。

仅仅须要同一时候覆写两个回调-onStartCommand和onBind就可以。

不管是用哪种方式启动service(或是两者都用),你都能够使用Intent来操作service,就想操作Activity一样。

然而。假设你不想让其它应用使用你的service,你能够在manifest文件里将service申明为私有的,详细请看Service在清单文件里的申明

基础介绍

想要使用service,你须要继承Service类或其子类。

你须要覆写一些回调方法同一时候在这些方法中进行一些关键操作。一下是一些较为重要的生命周期回调回调:

onStartCommand()

系统会在你调用了startService后调用该函数。一旦该方法运行,service会被启动并独立运行在后台。假设你实现了该方法,你必须在合适的时机调用stopSelf()或者stopService()来停止service。(假设你仅提供绑定接口。你能够不实现该方法)

onBind()

当有其它组件通过bindService()绑定service后,系统会调用onBind()函数。

你须要在该方法中提供一个实现了IBinder接口的类供给client使用。该方法必须要覆写,假设你不希望你的service提供绑定功能,你能够直接返回null。

Android系统会在内存较低时强制停止service;假设service被绑定在一个拥有焦点的activity上时。其被kill的风险会减少;假设一个service被申明为前台service。那么它差点儿不会被kill。否者的话。假设service被长时间开启。那么随着时间的推移,service在系统中的优先级就会越低。被kill的风险就会越高。假设你的service被启动了,那么你就应该考虑到其被系统kill的情况。

假设系统kill了一个service。那么在资源宽松的情况下。系统会重新启动它(这个须要依据你在onStartCommand()的返回值决定重新启动的策略)。

Service在清单文件里的申明

和activity一样,你须要在清单文件里申明service。

<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>

在service节点中能够申明一些其它的属性。这些属性都是可选的。仅仅有android:name这一属性是必须的——该属性用来描写叙述一个唯一的service类名,你应该确保不去改动该类名。

为了确保你的应用的安全性,应该使用显式意图来启动或者绑定service,而且不在service中申明intent-filters。

此外,你能够通过设置android:exported属性为false来确保你的service仅能够在你自己的应用中被使用。

这能够有效得阻止其它应用使用你的service,即使通过显式意图也不能够。

以启动方式创建service

能够通过startService()来启动service。你能够监听到onStartCommand()回调。

当一个service被启动后,它将拥有独立的生命周期而且独立的运行在后台。即使开启它的组件被销毁。这样的情况下,你须要在合适的时机调用stopSelf()来结束它或者通过调用stopServie()来结束它。

调用startService()时传递的Intent会在onStartCommand()回调时接收到。

注意:service会默认运行在申明service的那个应用进程中。而且会运行在主线程中。

所以假设你的service在运行一些密集或堵塞的操作,那么可能会造成ANR现象。为了避免这样的情况。你须要开启一个新的线程。

一般来说。你能够通过继承IntentService类来加速你的开发。

继承IntentService类

由于大部分的service都不须要处理并发请求。因此你能够通过继承IntentService类来加速你的开发。

IntentService有下面特性:

1.创建了一个工作线程来运行由onStartCommand()中传递的intent。该线程是和主线程分离的。

2.创建了一个工作队列用来依次运行intent,因此你不须要考虑多线程问题。

3.当全部任务运行结束后会自己主动的调用stopSelf()。

4.提供了onBind()的默认实现(return null)

5.提供了onStartCommand()的默认实现,发送任务到任务队列中而且回调onHandleIntent()

上述这些特性使得你仅仅须要实现onHandleIntent()就能够完毕client端的任务(你还须要提供一个简单的构造函数)

下面是IntentService的一个实现:

public class HelloIntentService extends IntentService {

  /**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
} /**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
}
}

对照一下。假设你继承自service要实现同样功能所需写的代码:

public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler; // Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
} @Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start(); // Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg); // If we get killed, after returning from here, restart
return START_STICKY;
} @Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
} @Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}

是不是累觉不爱,果断IntentService好啊。

然而,假设你希望实现并发操作,即不等上一个请求运行完毕就进行下一个请求的话。那么直接继承service是有必要的。

注意到onStartCommand()方法必须返回一个整型变量。这个整型变量用来指定当系统杀死service后应当怎样返回。下面是各个返回值:

START_NOT_STICKY

系统杀死service后不会又一次创建该service。除非须要传递pending intents。适用于当你的程序能够简单的重新启动未完毕任务的service。

START_STICKY

假设系统杀死了service,那么之后会重新启动该service而且调用onStartCommand(),可是不会又一次发送上一个intent。而是返回一个null的intent(除非是一个pending intents。)这样的模式非常适合音乐播放器这样的不须要运行commands。可是须要独立运行而且等待任务的service。

START_REDELIVER_INTENT

假设系统杀死了service,那么之后会重新启动该service而且掉哦那个onStartCommand(),而且会传递上一个intent。这中模式适合那些须要马上返回的service,比例如以下载文件。

以绑定方式启动service

详见Android开发文档翻译之-Bound Services

给用户发送通知

一旦service运行,你能够通过Toast Notifications或者Status Bar Notifications来告知用户某些事件。

Toast Notifications是一种短时间内出如今当前窗体表面的一条消息。Status Bar Notifications是一种提供了图标和消息的通知栏,用户能够通过点击来运行某个动作(比如开启一个activity)

前台Service

前台Service通经常使用来运行一些须要用户意识到正在运行的一些操作,因此系统在低内存状态时也不会kill掉该service。

前台Service须要在状态栏上提供一个通知,该通知不会消失,直到service被停止或者从前台移除。

比如,音乐播放器Service应该是被设置为运行在前台的service,由于用户应该一直意识到这个操作。状态栏应该显示当前正在播放的歌曲,而且当前点击后应该跳转到能和用户进行交互的activity。

通过调用startForeground()函数能够让你的service运行在前台。使用示比例如以下:

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

管理Service的生命周期

Service的生命周期相对Activity要简单的多。可是却更须要你注意。由于通常service是运行在后台的。

Service的生命周期一般而言分为下面两种:

Service的生命周期如上图所看到的。

原文链接:Android API文档之Services

Android开发文档翻译之-Services的更多相关文章

  1. Android 开发环境搭建以及工具(不断更新)

    学习android需要学习的编程知识 https://wiki.cyanogenmod.org/w/Doc:_Development_Resources 从http://source.android. ...

  2. [译]:Xamarin.Android开发入门——Hello,Android Multiscreen深入理解

    原文链接:Hello, Android Multiscreen_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android Multiscreen深入理解. 本 ...

  3. Android开发学习清单

    目录: 第1章 Android应用与开发环境1.1 Android的发展和历史1.1.1 Android的发展和简介1.1.2 Android平台架构及特性1.2 搭建Android开发环境1.2.1 ...

  4. Android开发快速入门(环境配置、Android Studio安装)

    Android是一种激动人心的开源移动平台,它像手机一样无处不在,得到了Google以及其他一些开放手机联盟成员(如三星.HTC.中国移动.Verizon和AT&T等)的支持,因而不能不加以学 ...

  5. Android开发自学笔记(Android Studio1.3.1)—3.Android应用结构解析

    一.R文件是什么?      如上图所示,我们可以通过findViewById方法通过传入R.id.show找到我们的TextView元素,findViewById方法也很好理解,从View中通过Id ...

  6. 一个帖子学会Android开发四大组件

    来自:http://www.cnblogs.com/pepcod/archive/2013/02/11/2937403.html 这个文章主要是讲Android开发的四大组件,本文主要分为 一.Act ...

  7. Android开发-API指南-服务

    Service 英文原文:http://developer.android.com/guide/components/services.html 采集(更新)日期:2014-12-23 原博客:htt ...

  8. Android开发-API指南-应用程序开发基础

    Application Fundamentals 英文原文:http://developer.android.com/guide/components/fundamentals.html 采集(更新) ...

  9. 【Android 应用开发】Android 开发环境下载地址 -- 百度网盘 adt-bundle android-studio sdk adt 下载

    19af543b068bdb7f27787c2bc69aba7f Additional Download (32-, 64-bit) Package r10 STL debug info androi ...

随机推荐

  1. JavaScript设计模式基础之面向对象的JavaScript(一)

    动态语言类型与鸭子类型 此内容取自JavaScript设计模式与开发实践一书 编程语言按照数据类型大体可以分为2类,一类就是静态类型语言,另一类则是动态类型语言 静态类型语言也可以称之为编译语言,而动 ...

  2. 洛谷 P2337 【[SCOI2012]喵星人的入侵】

    这几天一直在刷插头Dp,写了几道入门题后,觉得还比较水,直到我发现了这一题.... 题目大意:给你一个n*m的地图,有些是空地,有些是障碍,还有两个是ST,在给你一个L,代表可以放L个炮台,你要在空地 ...

  3. django--基础操作

    Django基础操作 django常用命令 创建django项目 django-admin startproject mysite 创建项目完成以后,文件目录结构为: 修改settings文件内容 A ...

  4. 查询SYS_ORG_TB树的层级

    WITH N(SYS_ORG_ID,SYS_ORG_NAME,LEVEL) AS( AS LEVEL FROM SYS_ORG_TB WHERE SYS_ORG_UPID IS NULL UNION ...

  5. LeetCode(169)Majority Element

    题目 Given an array of size n, find the majority element. The majority element is the element that app ...

  6. 【BZOJ 2761】 不重复数字 (哈希算法)

    链接 http://www.lydsy.com/JudgeOnline/problem.php?id=2761 Description 给出N个数,要求把其中重复的去掉,只保留第一次出现的数. 例如, ...

  7. POJ 1201 Intervals(差分约束 区间约束模版)

    关于差分约束详情可阅读:http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html 题意: 给定n个区间[L,R], 每个区间至 ...

  8. UI进阶 即时通讯之XMPP环境搭建

    内容中包含 base64string 图片造成字符过多,拒绝显示

  9. 【01】sass基础信息:

    [01]基础信息:   2016年4月16日   最新版本:3.4.22   官网:http://sass-lang.com/(下图)       CSStoSCSS 网站:http://css2sa ...

  10. hdu 2845

    #include<stdio.h> #define N 200100 int f[N]; int  a[N],n; int main() { int m,j,i,suma,sumb,sum ...