Day14 Service
- IntentService
- BindService
- AIDL实现跨进程服务
- MediaPlayer
- Timer
IntentService
IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。
另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。
- 关键方法
- 注意事项
关键方法
除其他Service生命周期方法外:
* ==
onHandleIntent(Intent)
==
在该方法中进行耗时操作,由IntentService中封装的异步任务完成
处理异步请求的IntentService,其内有一个工作线程来处理耗时操作
内部使用了单线程池模式(所以每次只执行一个任务,完成后再进行第二个)
注意事项
创建IntentService子类时,需要提供一个==无参==的构造方法且调用:
==
super(null)
==
BindService
基于IBinder方式将两个组件进行绑定,然后相互传值.
如果以绑定的方式启动的服务,在解除绑定时也会自动停止服务.
需创建自定义Binder子类并通过onBind()返回
- 生命周期方法
- 使用步骤
- 绑定类型
生命周期
除其他Service生命周期方法外:
- ==
==IBinder onBind(Intent)
- 返回自定义的Binder的子类
- 返回Messenger的getBinder()
- ==
==onUnBind(Intent)
- 解除绑定时回调
- ==
==onReBind(Intent)
- 重新绑定时回调
使用步骤
bindService的过程:
* 在Service组件中,声明Binder类的子类(公共),在其子类中声明组件之间的接口方法
* 在onBind()方法中,实例化Binder子类的对象,并返回
* 在绑定服务组件端(Activity),实例化ServiceConnection接口对象
* 在ServiceConnection接口对象的onServiceConnected()方法中,将方法的第二个参数IBinder对象强转成Binder子类对象
* 在适当的位置 调用 Context.bindService()来绑定服务。
创建类,继承Service,并现实onBind()方法
在Service组件中,声明Binder类的子类(公共),在其子类中声明组件之间的接口方法
public class MyService extends Service{
public IBinder onBind(Intent intent) {
...
}
public class MyBinder extends Binder{
public void MyMethod1(){
...
}
public void MyMethod2(){
...
}
...
}
}
在onBind()方法中,实例化Binder子类的对象,并返回
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();//实例化Binder的子类,并返回
}
在绑定服务组件端(Activity),实例化ServiceConnection接口对象
在ServiceConnection接口对象的onServiceConnected()方法中,将方法的第二个参数IBinder对象强转成Binder子类对象
ServiceConnection conn=new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 绑定成功的方法
myBinder=(MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
// 与绑定服务组件断开连接(发生的时机:由于系统原因造成了服务组件停止或销毁)
myBinder=null;
}
};
在适当的位置 调用 Context.bindService()来绑定服务。
//绑定服务组件
bindService(new Intent(getApplicationContext(),TimerService.class),
conn, BIND_AUTO_CREATE);
//BIND_AUTO_CREATE标识表示:绑定的服务组件如果不存,则会自动创建,
//注:由bindService方式启动的Service,其生命周期会受到绑定组件的影响,即当绑定组件Activity销毁时,Service也会停止
解除绑定
//解除绑定
Context.unBindService(Intent)
绑定类型
绑定服务的类型:
* ==
BIND_AUTO_CREATE
==
- 绑定的service不存在时,会自动创建
* ==
BIND_ADJUST_WITH_ACTIVITY
==
- service的优先级别与根据所绑定的Activity的重要程度有关,Activity处于前台,service的级别高
* ==
BIND_NOT_FOREGROUND
==
- Service永远不拥有运行前台的优先级
* ==
BIND_WAIVE_PRIORITY
==
- Service的优先级不会改变
* ==
BIND_IMPORTANT | BIND_ABOVE_CLIENT
==
- 所绑定的Activity处于前台时,Service也处于前台
- BIND_ABOVE_CLIENT 指定内存很低的情况下,运行时在终止绑定的Service之前终止Activity
AIDL实现跨进程服务
一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码
个人理解:
为了能使两个进程(应用)之间通信,二者需要持有同一个通讯工具,即通过AIDL文件定义的接口
当一个应用使用AIDL文件时,会自动生成其定义的java接口,通过这个接口实现与目标服务的通信接驳
- AIDL支持的数据类型
- 使用方法案例
AIDL支持的数据类型
AIDL默认支持的类型:
- java基本类型:==
==、==int
==、==long
==、==boolean
==、==float
==、==double
==char
- 引用类型及集合:==
==、==String[]
==、==List
==Map
使用方法案例
使用步骤概览
服务端:
- 服务端创建.aidl文件和声明接口
- 创建类,继承Service,并实现onBind方法
- 在Service类中定义aidl中声明接口的Stub对象,并实现aidl接口中声明的方法
- 在onBind方法中返回Stub对象
- 在AndroidManifest.xml中注册Service并声明其Action
客户端:
- Context.bindService(new Intent(接口的类名,ServiceConnection,int)
- 定义ServiceConnection对象
onServiceConnected(ComponentName,IBinder)
onServiceDisconnected()
//aidl接口对象=AIDLService.Stub.asInterface(server)
- 在Activity定义aidl接口对象
样例
IRemoteService.AIDL
package com.qf.aidl;
interface IRemoteService{
void print(String msg);
String getName();
}
- RemoteService.java
public class RemoteSerice extends Service {
//2.1 实例化.aidl接口的Stub对象
private IRemoteService.Stub stub=new IRemoteService.Stub() {
@Override
public void print(String msg) throws RemoteException {
Log.i("debug", "--RemoteSerice---"+msg);
}
@Override
public String getName() throws RemoteException {
return "RemoteSerice";
}
};
@Override
public IBinder onBind(Intent intent) {
return stub;//2.2 返回aidl接口的Stub对象
}
}
- (Client)
//声明aild接口对象
IRemoteService remoteService;
//实例化绑定组件之间的通信接口
ServiceConnection conn=new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//将第二个参数转化为.aidl接口对象
remoteService=IRemoteService.Stub.asInterface(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定其它应用的Service组件,在绑定成功之后,将返回的Stub对象转化为aidl接口对象
bindService(new Intent("com.qf.serivce04_aidl_server.RemoteSerice"),
conn, BIND_AUTO_CREATE);
}
MediaPlayer
用于播放音乐和视频文件
构造方法:==
MediaPlayer()
==
通过静态方法(create)构造会直接进入prepared状态
通过静态方法构造:==
MediaPlayer create(Context context, int resid)
==
常用方法
- ==
== 设置媒体源setDataSource(String path)
- ==
== 设置是否循环播放setLooping(boolean)
- ==
== 预处理,调用start()前必须先调用此方法prepare()
- ==
== 开始播放start()
- ==
==暂停播放pause()
- ==
== 停止播放stop()
- ==
== 是否正在播放isPlaying()
- ==
== 重置播放器,进入idle空闲状态reset()
- ==
== 释放资源release()
- ==
== 获取播放文件的总时长,单位:毫秒getDuration()
- ==
== 获取当前播放的位置getCurrentPosition()
- ==
== 定位到指定的播放时间seekTo(int position)
Timer定时器
按排一段定时任务在指定的时间执行,对于提醒相关的任务,应该设置重复间隔时间
关键方法
- ==
== 按排任务在指定时间执行schedule(TimerTask task, Date when)
- ==
== 按排任务延迟多少毫秒之后执行schedule(TimerTask task, long delay)
- ==
== 按排任务在延迟多个毫秒后执行,并间隔多少毫秒后重复schedule(TimerTask task, long delay, long period)
- ==
== 取消定时器cancel()
TimerTask 定时任务
TimerTask 定时任务类,是实现Runnable接口的抽象类
样例
timer.schedule(new TimerTask(){
@Override
public void run() {
// TODO 在指定的时间执行的任务
NotificationCompat.Builder builder=
new NotificationCompat.Builder(getApplicationContext());
builder.setSmallIcon(android.R.drawable.ic_menu_today)
.setContentTitle("提醒")
.setContentText("时间了,该起床了....")
.setTicker("时间了,该起床了....")
.setDefaults(Notification.DEFAULT_SOUND)
.setOngoing(true);
notifyMgr.notify(, builder.build());
}
},*, *);