一:Service的概述
Service是Android四大组件中与Activity最相似的组件。都代表执行的程序,Service与Activity的区别在于:
Service一直在后台运行,它没有用户界面,所以绝不会到前台来。一旦Service被启动起来之后,它就与Activity一样。完全具有自己的生命周期。
关于程序中Activity和service的选择标准:
如果某个程序组件需要在运行时向用户呈现某种界面,或者该程序需要与用户交互,就需要使用Activity,否则就应该考虑使用Service了。
如:下载东西,播放音乐。可以一边下载,一边播放,一边玩其他的事情。但是Activity是无法做到的。只要Activity被关闭或者最小化了,程序就停止了。
二:特点
1.没有UI
2.进行耗时较长或者与用户没有交互的一些功能
3.Service具有较高的优先级,比stop的Activity优先级要高,最高的优先级是前台Activity
4.具有较长的生命周期
三:Service的使用
1)创建:
创建类继承Service,实现OnBind()方法。
Service与Activity都是从Context派生出来的。
因此可以使用Context中的方法,如getResouces()等方法。
2)配置:
在配置文件中配置标签
设置android:name属性,也可以配置元素
3)启动:
Service启动依赖于其他组件,可以使用Activity或者Receiver等作为调用者,调用者可以使用以下两种形式启动Service
(1)startService
startService启动Service涉及生命周期方法:
onCreate()–onStartCommand()/onStart()–onDestory()
a)onCreate()创建Service实例时的回调函数,启动的Service实例如果不存在会触发一次之后不会触发.
b)onStartCommand() 启动Service时的回调函数每次启动都会触发,可以通过参数startId获取其启动次数,第二个参数flags表示启动服务的方式:
c)onStart():启动Service时,已经被淘汰了。
d)onDestory():销毁Service实例
注意:
onStartCommand()的返回值用来指定Service的系统在用户为手动关闭Service前自动回收Service资源了Service资源情况下的重启行为:
a)START_STICKY
如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
b)START_NOT_STICKY
“非粘性的”。如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
c)START_REDELIVER_INTENT
使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
d)START_STICKY_COMPATIBILITY:
START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
该方法用来启动一个独立的Service实例,
该实例与调用者没有关联关系
调用者的生命周期不会影响到Service的生命周期
即使访问者退出了,Service仍然运行。
(2)bindService
该方法用来将一个Service实例与调用者建立关联关系,Service与调用者之间可以进行数据共享,调用者声明周期会影响的Service的生命周期,即使访问者退出了Service也就终止
bindService方法有三个参数:
第一个参数包含要绑定Service信息的Intent对象
第二个参数是一个ServiceConnection对象,该对象用于监听访问者与Service之间的连接情况。当访问者与Service之间链接成功时将回调该ServiceConnection对象的onServiceConnected(ComponentName,IBinder)方法;当Service所在的宿主进程由于异常中止或由于其他原因终止,导致该Service与访问者之间断开连接时回调该ServiceConnection对象的onServiceDisconnected(ComponentName)方法。其中onServiceConnected方法中的IBinder对象,可实现与被绑定Service之间的通信。在开发Service类时,该Service类必须提供一个IBinder onBind()方法,该方法所返回的IBinder对象将会传给ServiceConnection对象里onServiceConnected方法的参数中。这样访问者就
可以通过该IBinder对象与Service进行通信。实际开发时通常会采用继承Binder(IBinder的实现类)的方式实现自己的IBinder对象。
第三个参数指定绑定时是否自动创建Service
(如果Service还未创建),该参数可指定为0(不自动创建)
或BIND_AUTO_CREATE(自动创建)。
bindService启动Service的生命周期方法:
onCreate()--->onBind()--->onUnbind()--->onDestory().
a)onCreate() 同startService
b)onBind() 在Service与调用者建立关联关系时使用,该方法会返回一个IBinder类型的实例给调用者,作为Service在调用者的代理.
c)onUnbind() Service与调用者解除绑定。
d)onDestory() 同startService
e)onRebind() 重新连接
5)停止:针对不同启动方式,可以使用两种方式在调用者中手动关闭Service
stopService(Intent it);
unbindService(ServiceConnection conn)
6)IntentService
Android中的Service是用于后台服务的,当应用程序被挂到后台的时候,问了保证应用某些组件仍然可以工作而引入了Service这个概念,那么这里面要强调的是Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR(Application Not Responding)。那么我们当我们编写的耗时逻辑,不得不被service来
管理的时候,就需要引入IntentService,IntentService是继承Service的,那么它包含了
Service的全部特性,当然也包含service的生命周期,那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去你执行你的耗时操作。该线程保证同一时刻只处理一个Intent.这样IntentService不会阻塞主线程。
IntentService的使用和Service是类似。它需要重写onHandleIntent(Intent intent)方法。
注意:service 没有unbind时was originally bound here错误。
在程序中,如果在activity中绑定了服务,
而没有在destory中,写unbind,会出现这种异常,
解决方式:在Activity的onDestory方法中调用unbindService(sc)
方法,该方法是context中的方法。
package com.xspacing.service;
import com.xspacing.service.SecondService.MyBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private Intent intent;
private Intent intent2;
private BindServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View v) {
intent = new Intent(this, FirstService.class);
// 启动服务
// 通过这个方式启动的服务,这个服务的生命周期不受activity的生命周期的影响
startService(intent);
}
public void stopService(View v) {
stopService(intent);
}
public void startBindService(View v) {
intent2 = new Intent(this, SecondService.class);
conn = new BindServiceConnection();
// 通过这个方式启动的服务,这个服务的生命周期与activity的生命周期息息相关的
bindService(intent2, conn, BIND_AUTO_CREATE);
}
public void stopBindService(View v) {
// stopService(intent);
unbindService(conn);
conn=null;
}
public void intentService(View v) {
Intent intent = new Intent(this, MyItentService.class);
startService(intent);
}
class BindServiceConnection implements ServiceConnection {
private static final String TAG = "BindServiceConnection";
// service与activity进行绑定的时候会回调
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected()");
MyBinder binder=(MyBinder) service;
int count = binder.getCount();
Log.i(TAG, count+"");
}
// service与activity异常解除绑定的时候会回调
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected()");
}
}
@Override
protected void onDestroy() {
if (conn != null) {
unbindService(conn);
}
super.onDestroy();
}
}
package com.xspacing.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
/**
* @ClassName FirstService.java
* @Description Service生命周期
* @author smile
* @version v1.0
* @date 2016年10月8日
*/
public class FirstService extends Service {
private static final String TAG = "FirstService";
private boolean flag;
private int count;
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 开启了再开启只执行一次
*/
@Override
public void onCreate() {
Log.i(TAG, "onCreate()");
flag = true;
new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, count + "");
}
}
}).start();
super.onCreate();
}
/**
* 开启了再开启每次执行一次
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
flag = false;
super.onDestroy();
}
}
package com.xspacing.service;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
public class MyItentService extends IntentService {
private static final String TAG = "MyItentService";
private int count;
private boolean flag = true;
public MyItentService(String name) {
super(name);
}
public MyItentService() {
this("MyItentService");
}
/**
* 底层开辟了一个子线程
*/
@Override
protected void onHandleIntent(Intent intent) {
while (flag) {
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, count + "");
}
}
@Override
public void onDestroy() {
flag = false;
super.onDestroy();
}
}
package com.xspacing.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class SecondService extends Service {
private static final String TAG = "SecondService";
private int count;
boolean flag;
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate()");
Log.i(TAG, "onBind()");
flag = true;
new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, count + "");
}
}
}).start();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
flag = false;
super.onDestroy();
}
// 通常自己实现一个类继承Binder,也间接地实现了IBinder接口
public class MyBinder extends Binder {
public int getCount() {
return count;
}
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.xspacing.service.MainActivity"
android:orientation="vertical">
<Button
android:onClick="startService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="startService" />
<Button
android:onClick="stopService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="stopService" />
<Button
android:onClick="startBindService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="startBindService" />
<Button
android:onClick="stopBindService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="stopBindService" />
<Button
android:onClick="intentService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="intentService" />
</LinearLayout>