Android 支持服务的概念。服务是在后台运行组件,没有用户界面。可以将这些组件想象为Windows 服务或UNIX服务。 与这些服务类型类似,Android服务始终可用,但无需主动执行某些操作。
Android 支持两种服务类型的服务:本地服务和远程服务。本地服务无法供在设备上运行其他应用程序访问。一般而言,这些服务类型仅支持承载该服务的应用程序。而对于远程服务,除了可以承载服务的应用程序访问,还可以从其他应用程序访问。远程服务使用 AIDL(Android Interface Definition Language, Android接口定义语言)向客户端定义其自身。
Android 中的服务
通过查看 android.app.Service的公共方法,我们可以更深入地理解服务的概念。
Application getApplication();
Abstract IBinder onBind(Intent intent);
void onConfigurationChanged(Configuration newConfig);
void onCreate();
void onDestroy();
void onLowMemory();
void onRebind(Intent intent);
void onStart(Intent intent, int startId);
boolean onUnbind(Intent intent);
final void setForeground(Boolean isForeground);
final void stopSelf();
final void stopSelf(int startId);
final boolean stopSelfResult(int startId);
getApplication()方法返回实现服务的应用程序。
onBind()方法为在同一设备上运行的外部应用程序提供一个接口来与服务通信,此方法在远程服务中特别重要。onConfigurationChanged();支持服务在设备配置更改时重新配置自身。
系统在首次创建服务时调用onCreate(),然后才调用onStart()。此过程类似创建一个Activity的过程,在启动时执行一次初始化。例如,如果创建后台线程,可以在onCreate()方法中进行,在确保在onDestroy()中停止该线程。系统调用 onCreate(),然后调用 onStart(), 最后在关闭服务时调用 onDestroy()。onDestroy()方法为服务提供了一种机制,在关闭之前执行最后的清理。
请注意,onStart()、onCreate()、和 onDestroy()都是由系统调用的,不应该直接调用它们。而且,如果在服务类中重写任何on*()方法,请确保从这些方法调用了超类的方法版本。stopSelf()的各种版本为应用程序提供了一种机制来停止服务。客户端也可以调用 Context.stopService()来停止服务。
Android支持服务的概念有2个原因。第一,简化后台任务的实施,这种服务也就是本地服务;第二,在同一设备上运行的应用程序之间执行进程通信,这种服务也就是远程服务。本地服务与远程服务的一些重要区别。具体来讲,如果服务完全只供同一进程中的组件使用(以运行后台任务),那么客户端必须调用 Context.startService()来启动该服务。这种类型的服务为本地服务,因为它的一般用途是运行承载服务的应用程序的后台任务。如果服务支持onBind()方法,那么它属于远程服务,可通过进程间通信 (Context.bindService())进程调用。我们也将远程服务称为AIDL 支持服务,因为客户端使用 AIDL 与服务通信。
尽管 android.app.Service接口同时支持本地服务和远程服务,但并不建议提供一种服务的实现同时支持两种类型。因为每种服务的类型都有预定义的生命周期,将两种服务合并在一起可能导致错误(尽管允许这么做)。
说明:Android中的第二种服务类型有多种叫法:远程服务、AIDL服务、外部服务和RPC服务。这些名称都是指向同一类型的服务----------可供在设备上运行的其他应用程序远程访问的服务。
本地服务
本地服务由Context.startService()启动。启动以后,这些类型的服务将持续运行,直到客户端调用服务的 Context.stopService()或者服务自己调用 stopSelf()。请注意,当调用Context.startService()时,系统将实例化服务并调用服务的 onStart()方法。请记住,如果在服务启动之后(也就是服务运行时)调用 Context.startService()不会为服务创建另一个实例,但这样做将调用服务的 onStart()方法。下面给出了两个本地服务的实例。
一:定期在网络(比如Intent)上检索数据的服务 (用于上传或下载信息)。
二:任务执行程序服务,让应用程序的活动提交作业并对它们进行排队以供处理。
下面这个例子是一一个本地服务的例子 这里例子是 我们在服务的不同状态,如服务创建、服务启动、服务停止等 定义一个消息 通过状态栏来提醒用户 后台服务的不同状态。
运行效果如下
先来看看我们的Service类
BackgroundService.java
package xiaohang.zhimeng;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class BackgroundService extends Service {
private NotificationManager notificationMgr;
@Override
public void onCreate() {
super.onCreate();
notificationMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
displayNotificationMessage("starting Background Service");
Thread thr = new Thread(null, new ServiceWorker(), "BackgroundSercie");
thr.start();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
class ServiceWorker implements Runnable {
@Override
public void run() {
// do background processing here.....
// stop the service when done...
// BackgroundService.this.stopSelf()
}
}
@Override
public void onDestroy() {
displayNotificationMessage("stopping Background Service");
super.onDestroy();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
private void displayNotificationMessage(String message) {
Notification notification = new Notification(R.drawable.icon, message,
System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, Activity01.class), 0);
notification.setLatestEventInfo(this, "Background Service", message,
contentIntent);
notificationMgr.notify(R.id.app_notification_id, notification);
}
}
Activity01类
package xiaohang.zhimeng;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Activity01 extends Activity {
private static final String TAG = "Activity01";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG, "starting service");
Button bindBtn = (Button) findViewById(R.id.bindBtn);
bindBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startService(new Intent(Activity01.this,
BackgroundService.class));
}
});
Button unbindBtn = (Button) findViewById(R.id.unbindBtn);
unbindBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopService(new Intent(Activity01.this, BackgroundService.class));
}
});
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button android:id="@+id/bindBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bind"/>
<Button android:id="@+id/unbindBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="UnBind"/>
</LinearLayout>
我们需要创建一个图标 并将其放在项目的drawable文件夹内,我用的项目自带的那个。需要为通知管理器NotificationManager提供一个应用程序级唯一ID(整数)。要创建唯一ID,可以向字符串资源文件 /res/values/strings.xml 添加一个项ID。当调用notify()方法时,会将唯一ID 传递给通知管理器。
<item type=”id” name=”app_notification_id”/>
最后,需要向 AndroidManifest.xml 文件添加
<service android:name=”BackgroundService”/>
标记,将其作为<application>的子标签。
BackgroundServie是承载服务的应用程序组件使用服务的一个典型例子。换言之,运行服务的应用程序也是服务的唯一使用者。因为该服务不支持其进程外的客户端,所以它是本地服务。由于本地服务不是远程服务,所以它在bind()方法中返回null。因此,绑定此服务的唯一 方法是调用Context.startService()。本地服务的重要方法包括 onCreate()、onStart()、stop()*和onDestroy()。
在BackgroundService的 onCreate()方法中,我们创建了一个线程来完成服务的主要工作。我们需要应用程序的主线程来处理用户界面,所以将服务的工作委派给一个辅助线程。另请注意,我们在onCreate()而不是onStart()中创建和启动线程。这样做是因为, onCreate()只会被调用一次,我们也希望在服务生命周期内只创建一次该线程。onStart()方法可以调用多次,所以它不符合此处的要求。我们在线程的run()方法实现中没有做任何事情,可以在这里执行HTTP调用、查询数据库等。
BackgroundService还使用NotificationManager类,以在服务启动和停止时向用户发送通知。这是本地服务将信息传递回用户的一种方式。要向用户发送通知,需要调用 getSystemService(NOTIFICATION_SERVICE)来获得通知管理器。来自通知管理器的消息将显示在状态栏中。
源码附件!