Android 开发学习笔记(二)—— Service
2018-04-08 本文已影响0人
isletn
Service 能在后台长期运行而不提供用户界面。由其他组件启动,且可以做到不依赖当前应用运行。组件能绑定 Service,进行交互、执行进程间通信。
Tips
- 一个Service如果被调用startService()启动多次,onCreate()方法也只执行一次
- 对于启动服务,除onStartCommand()方法外,其他生命周期方法只会被调用一次
- onStartCommand()调用次数 == startService()调用次数
- 在服务中启动Activity必须加下面这行代码
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Service

Service 生命周期
- 官方生命周期图 服务生命周期

Service 的两种形式:
- 启动:组件通过startService()启动,无限期运行(不受组件生命周期影响)
- 绑定:组件通过bindService()绑定,提供客户端-服务器接口进行交互、发请求、获取结果甚至进程间通信。仅当与另一个组件绑定时才会运行,组件与服务可以是多对一关系,最后一个绑定组件销毁Service销毁。应用场景:Activity 和其他应用组件中的服务进行交互,或者需要通过进程间通信 (IPC) 向其他应用公开某些应用功能,那么就创建绑定服务。
Service 既可以是启动服务,也可以与其他组件进行绑定。这取决于你是否实现Service的回调方法:onStartCommand()(允许组件启动服务)、onBind()(允许绑定服务)。
创建启动 Service:
应用场景:假设某Activity 需要上传数据到服务器,则可以启动一个协同服务,通过startService()传递一个Intent ,为该服务提供上传的数据。服务通过onStartCommand()接收Intent,进行上传操作。
PS:需要注意的是,默认情况,Service 运行在主线程,因此,如果有耗时操作交给 Service 应该在 Service中启动新的子线程执行该操作。
- 首先,与其他 Android 组件一样,需要在 AndroidManifest.xml 文件里面声明你要用的服务;
...
<application>
<service android:name="xxxx" />
</application>
...
- 使用扩展类创建 Service
-
Service:所有服务的基类,扩展时,必须创建一个用于执行所有服务工作的新线程。
-
IntentService:Service 的子类,一般情况下都用这个。不要求同时处理多个请求就选这个服务。实现onHandleIntent()方法接收每个Intent。
/**
* 使用 IntentService 只需要提供一个构造函数跟实现onHandleIntent()方法就行了
*/
public class HelloIntentService extends IntentService {
public HelloIntentService() {
super("HelloIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
// ...
}
}
- 启动 Service
/**
* Intent可以指定要启动的服务,通过将Intent传给 startService(),
* 从Activity或其他组件中启动Service
*/
Intent intent = new Intent(this, HelloService.class);
startService(intent);
- 这之后Android系统会调用onStartCommand()方法 接收被传递的Intent。千万不要手动去掉onStartCommand();如果服务尚未运行,那系统就会onCreate()->onStartCommand()。
- 通信:如果服务亦未提供绑定,则使用 startService() 传递的 Intent 是应用组件与 Service 之间唯一的通信模式;Service向组件传递消息可以通过:让启动服务的组件创建一个 PendingIntent (使用 getBroadcast())并通过Intent传递给Service,然后Service可以使用广播传递消息
- 多个服务启动请求会导致多次对服务的 onStartCommand()进行相应的调用。但是,要停止服务,只需一个服务停止请求(使用 stopSelf() 或 stopService())即可。
- 停止 Service
- 启动服务必须通过 stopSelf()自行结束,或是其他组件调用stopService()来停止它;
- 通过 stopSelf(startId)来确保停止正确的Service;
- 任务完成后应停止服务节省电量;
在前台运行服务
应用场景:应该将通过服务播放音乐的音乐播放器设置为在前台运行,这是因为用户明确意识到其操作。 状态栏中的通知可能表示正在播放的歌曲,并允许用户启动 Activity 来与音乐播放器进行交互。
前台服务特点:
- 在内存不足时,系统也不会考虑将其终止
- 前台服务必须为状态栏提供通知,放在“正在进行”标题下方,这意味着除非服务停止或从前台移除,否则不能清除通知。
- 让服务运行在前台
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);
// 第一个参数不能为 0
startForeground(ONGOING_NOTIFICATION_ID, notification);
- 从前台移除服务
// true 或 false 代表是否也移除状态栏通知
stopForeground(true);
参考自官方文档
https://developer.android.com/guide/components/services.html?hl=zh-cn