一、服务概述
Service是一个应用程序组件,它能够在后台执行一些耗时较长的操作,并且不提供用户界面。服务能被应用程序的其它组件启动,即使用户切换到另外的应用时还能保持后台运行。此外,应用程序组件还能与服务绑定,并与服务进行交互,甚至能进行进程间通信(IPC)。例如,服务可以处理网络传输、音乐播放、执行文件I/O、或者与content provider进行交互,所有这些都是后台进行的。
二、服务的两种基本类型
①Started
如果一个应用程序组件(比如一个activity)通过调用startService()来启动服务,则该服务就是被“started”了。一旦被启动,服务就能在后台一直运行下去,即使启动它的组件已经被销毁了。 通常,started的服务执行单一的操作并且不会向调用者返回结果。比如,它可以通过网络下载或上传文件。当操作完成后,服务应该自行终止。
②Bound
如果一个应用程序组件通过调用bindService()绑定到服务上,则该服务就是被“bound”了。bound服务提供了一个客户端/服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至可以利用进程间通信(IPC)跨进程执行这些操作。绑定服务的生存期和被绑定的应用程序组件一致。多个组件可以同时与一个服务绑定,不过所有的组件解除绑定后,服务也就会被销毁。无论你的应用程序是started、bound、还是两者都支持,任何应用程序组件都可以使用此服务(即使是从另一个独立的应用程序中)。不过,也可以在manifest文件中把服务声明为私有private的,以便阻止其它应用程序的访问。
三、started和bound两种方式的特点
①started
服务被开启后 会在设置页面里面的 running里面找得到这个服务
startService方式开启服务,服务就会在后台长期运行,直到用户手工停止或者调用stopService方法服务才会被销毁
开启服务:服务生命周期执行顺序onCreate()、onStartCommand(),销毁服务执行onDestroy()
②bound
通过bind方式绑定服务,服务不能再设置页面里面找到,相当于是一个隐形的服务
当activity销毁的时候,在onDestroy()方法中也要解绑服务
开启服务:服务生命周期执行顺序onCreate()、onBind(),销毁服务执行onDestroy()
四、服务的实现
(1)为了创建一个服务,你必须新建一个Service的子类(或一个已有Service的子类)。在你的实现代码中,请按需重写一些回调方法,用于对服务生命周期中的关键节点进行处理,以及向组件提供绑定机制。 最重要的需要重写的回调方法包括:
①onStartCommand()
当其它组件,比如一个activity,通过调用startService()请求started方式的服务时,系统将会调用本方法。 一旦本方法执行,服务就被启动,并在后台一直运行下去。 如果你的代码实现了本方法,你就有责任在完成工作后通过调用stopSelf()或stopService()终止服务。(如果你只想提供bind方式,那就不需要实现本方法。)
②onBind()
当其它组件需要通过bindService()绑定服务时(比如执行IPC),系统会调用本方法。 在本方法的实现代码中,你必须返回IBinder来提供一个接口,客户端用它来和服务进行通信。 你必须确保实现本方法,不过假如你不需要提供绑定,那就返回null即可。
③onCreate()
当服务第一次被创建时,系统会调用本方法,用于执行一次性的配置工作。如果服务已经运行,则本方法就不会被调用。
④onDestroy()
当服务用不上了并要被销毁时,系统会调用本方法。 你的服务应该实现本方法来进行资源的清理工作,诸如线程、已注册的侦听器listener和接收器receiver等等。 这将是服务收到的最后一个调用。
如果组件通过调用startService()(这会导致onStartCommand()的调用)启动了服务,那么服务将一直保持运行,直至自行用stopSelf()终止或由其它组件调用stopService()来终止它。
如果组件调用bindService()来创建服务(那onStartCommand()就不会被调用),则服务的生存期就与被绑定的组件一致。一旦所有客户端都对服务解除了绑定,系统就会销毁该服务。
(2)在manifest中声明服务
与activity(及其它组件)类似,你必须在应用程序的manifest文件中对所有的服务进行声明。
要声明你的服务,把<service>元素作为子元素加入到<application>元素中去即可。例如:
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
五、实例演示
①项目目录结构
②activity_main.xml界面
③activity_main.xml代码
<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"
android:orientation="vertical"
tools:context="com.zgs.TwoServiceStyle.MainActivity" >
<Button
android:onClick="click1"
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="startservice" />
<Button
android:onClick="click2"
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stopservice" />
<Button
android:onClick="click3"
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bindservice" />
<Button
android:onClick="click4"
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="unbindservice" />
</LinearLayout>
④FirstService.java代码
package com.zgs.TwoServiceStyle;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class FirstService extends Service {
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return null;
}
//当服务第一次被开启的时候调用
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
}
//通过调用startService()请求started方式的服务时,系统将会调用本方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
//服务销毁的时候执行
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
}
⑤MainActivity.java代码
package com.zgs.TwoServiceStyle;
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.view.View;
public class MainActivity extends Activity {
private MyConn conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// 点击开启服务:started方式
public void click1(View v) {
Intent intent = new Intent(this, FirstService.class);
startService(intent);
}
// 点击结束服务:started方式
public void click2(View v) {
Intent intent = new Intent(this, FirstService.class);
stopService(intent);
}
// 点击开启服务:bound方式
public void click3(View v) {
Intent intent = new Intent(this, FirstService.class);
conn = new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);
}
// 点击关闭服务:bound方式
public void click4(View v) {
unbindService(conn);
}
//用来监听服务的状态
private class MyConn implements ServiceConnection{
//连接成功后调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
//失去连接调用
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
//当activity销毁的时候调用来取消绑定服务
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
}
⑥AndroidManifest.xml代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zgs.TwoServiceStyle"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.zgs.TwoServiceStyle.FirstService"></service>
</application>
</manifest>
⑦操作演示