简介:介绍Android系统中的本地Service,即Local Service。
什么是 Service
Service即服务,与Activity不同的是,Service是没有界面、不能自己启动的,运行在后台的程序。当我们退出应用时,Service进程并没有结束,而是仍然运行在后台。
什么时候使用Service?举个常见的例子:播放音乐,在播放音乐的同时想要边干些其他事情,就需要隐藏或退出播放音乐的应用,如果没有使用Service,会因为音乐应用将被暂停而听不到音乐,所以这时候就得用到Service了。
在Android系统中,Service分为两种:Local Service
和 Remote Service
。
本地服务, Local Service 用于应用程序内部。在Service可以调用Context.startService()启动,调用Context.stopService()结束。在内部可以调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。无论调用了多少次startService(),都只需调用一次stopService()来停止。
远程服务, Remote Service 用于android系统内部的应用程序之间。可以定义接口并把接口暴露出来,以便其他应用进行操作。客户端建立到服务对象的连接,并通过那个连接来调用服务。调用Context.bindService()方法建立连接,并启动,以调用 Context.unbindService()关闭连接。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。
提供给可被其他应用复用,比如定义一个天气预报服务,提供与其他应用调用即可。
Service和其他组件一样,都是运行在主线程中,因此不能用它来做耗时的请求或者动作。如果需要,可以在服务中开一个新线程,在该线程中做耗时动作。
Service的生命周期
Service的生命周期并不像Activity那么复杂,它只继承了onCreate(), onStart(), onDestroy()三个方法,当我们第一次启动Service时,先后调用了onCreate(),onStart()这两个方法,当停止Service时,则执行onDestroy()方法,这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。
context.startService() ->onCreate()- >onStart()->Service running – 调用context.stopService() ->onDestroy()
context.bindService()->onCreate()->onBind()->Service running – 调用>onUnbind() -> onDestroy()
实例
创建Android项目,创建MainService.java,代码如下:
package com.test.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MainService extends Service {
public class MyBinder extends Binder {
public MainService getService() {
return MainService.this;
}
}
private MyBinder binder;
@Override
public IBinder onBind(Intent vIntent) {
System.out.println("onBind");
return binder;
}
@Override
public boolean onUnbind(Intent vIntent) {
System.out.println("onUnbind");
return super.onUnbind(vIntent);
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("onCreate");
binder = new MyBinder();
}
@Override
public void onStart(Intent vIntent, int vStartId) {
super.onStart(vIntent, vStartId);
System.out.println("onStart");
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("onDestroy");
}
public void next() {
System.out.println("播放下一首");
}
public void end() {
System.out.println("停止");
}
public void play() {
System.out.println("播放");
}
public void pre() {
System.out.println("播放上一首");
}
}
在AndroidManifest.xml中application节点下添加声明:
<service
android:name="com.test.service.MainService"
android:enabled="true" >
</service>
接下来编写主界面布局:
<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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onStarClick"
android:text="Start" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onStopClick"
android:text="Stop" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onBindClick"
android:text="Bind" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onUnbindClick"
android:text="Unbind" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onPreClick"
android:text="Pre" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onNextClick"
android:text="Next" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onPlayClick"
android:text="Play" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onEndClick"
android:text="End" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onNewClick"
android:text="new" />
</LinearLayout>
</LinearLayout>
界面布局中,按钮添加了onClick属性,因此,在代码中必须要实现对应的方法,主界面代码如下:
package com.test.service;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import com.test.service.MainService.MyBinder;
public class MainActivity extends Activity {
private MainService mService = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onStarClick(View v) {
Intent service = new Intent(this, MainService.class);
startService(service);
}
public void onStopClick(View v) {
Intent service = new Intent(this, MainService.class);
stopService(service);
}
public void onBindClick(View v) {
bindService(new Intent(this, MainService.class), sc,
Context.BIND_AUTO_CREATE);
}
public void onUnbindClick(View v) {
if (sc != null) {
unbindService(sc);
sc = null;
}
}
public ServiceConnection sc = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName vName) {
mService = null;
System.out.println("服务断开!");
}
@Override
public void onServiceConnected(ComponentName vName, IBinder vService) {
System.out.println("onServiceConnected");
MyBinder binder = (MainService.MyBinder) vService;
mService = binder.getService();
}
};
public void onPreClick(View v) {
if (mService != null) {
mService.pre();
}
}
public void onNextClick(View v) {
if (mService != null) {
mService.next();
}
}
public void onPlayClick(View v) {
if (mService != null) {
mService.play();
}
}
public void onEndClick(View v) {
if (mService != null) {
mService.end();
}
}
public void onNewClick(View v) {
startActivity(new Intent(this, NewActivity.class));
}
}
在绑定服务的时候,需要一个服务连接对象,ServiceConnection,服务一旦连接,就会调用onServiceConnected方法,我们可以在这个方法里面返回我们的本地服务对象,具体看代码;而在服务断开时候会调用onServiceDisconnected方法,我们可以清理一些服务资源。
界面上第一排有四个按钮:Start(启动服务)、Stop(停止服务)、Bind(绑定服务)和Unbing(解除绑定)。
第二排有四个按钮,分别对应播放器的几个功能,具体实现在MainService中。
最后有个new按钮,该按钮启动一个新的页面-New界面,用来测试新界面与Service的链接情况。
New界面的布局如下:
<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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onPreClick"
android:text="Pre" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onNextClick"
android:text="Next" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onPlayClick"
android:text="Play" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onEndClick"
android:text="End" />
</LinearLayout>
</LinearLayout>
New界面的代码如下:
package com.test.service;
import com.test.service.MainService.MyBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
public class NewActivity extends Activity {
private MainService mService = null;
@Override
protected void onCreate(Bundle vSavedInstanceState) {
super.onCreate(vSavedInstanceState);
setContentView(R.layout.activity_new);
Intent service = new Intent(this, MainService.class);
startService(service);
bindService(service, sc, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(sc);
}
public ServiceConnection sc = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName vName) {
mService = null;
System.out.println("服务断开!");
}
@Override
public void onServiceConnected(ComponentName vName, IBinder vService) {
System.out.println("onServiceConnected");
MyBinder binder = (MainService.MyBinder) vService;
mService = binder.getService();
}
};
public void onPreClick(View v) {
if (mService != null) {
mService.pre();
}
}
public void onNextClick(View v) {
if (mService != null) {
mService.next();
}
}
public void onPlayClick(View v) {
if (mService != null) {
mService.play();
}
}
public void onEndClick(View v) {
if (mService != null) {
mService.end();
}
}
}