服务简单介绍:
服务是一个应用程序组件,可以在后台执行长时间运行的操作,不提供用户界面。一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切换到另一个应用程序。此外,一个组件可以绑定到一个服务与它交互,甚至执行进程间通信(IPC)。例如,一个服务可能处理网络通信、播放音乐、计时操作或与一个内容提供者交互,都在后台执行。
服务的种类
- 按运行地点分类
类别 | 区别 | 优点 | 缺点 | 应用 |
---|---|---|---|---|
本地服务(Local Service) | 该服务依附在主进程上 | 服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多 | 主进程被Kill后,服务便会终止。 | 如:音乐播放器播放等不需要常驻的服务。 |
远程服务(Remote Service) | 该服务是独立的进程 | 服务为独立的进程,对应进程名格式为所在包名加上你指定android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性 | 该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点 | 一些提供系统服务的Service,这种Service是常驻的。 |
- 按运行类型分类
类别 | 区别 | 应用 |
---|---|---|
前台服务 | 会在通知栏显示onGoing的 Notification | 当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务。 |
后台服务 | 默认的服务即为后台服务,即不会在通知一栏显示 onGoing的 Notification。 | 当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新,日期同步,邮件同步等。 |
- 按使用方式分类
类别 | 区别 |
---|---|
startService启动的服务 | 主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService。 |
bindService启动的服务 | 默认的服务即为后台服务,即不会在通知一栏显示 onGoing的 Notification。 |
同时使用startService、bindService 启动的服务 | 停止服务应同时使用stopService与unbindService |
服务生命周期
通过这个图看到对比,两种启动方式及它们的生命周期,start服务主要是调用onStartCommand()方法处理逻辑。而bind服务主要是调用onBind()方法处理逻辑,还有使用onUnbind()方法进行解绑,service才会被kill掉
我们只要知道不管任何启动服务方式onCreate()生命周期只会被执行一次
- startService建立连接后,onBind()生命周期不管怎样始终都不会被调用,当app关闭之后并没有停止服务,它会一直保存在后台,直到调用stopService或Service自身的stopSelf来停止服务。
- bindService建立连接后,onStartCommand()生命周期不会被调用,app关闭前执行unBindService()解绑服务后会自动调用 onUnbind()生命周期,它的启动周期依附于启动它的Context,如果没有停止Service,会报异常错误
注意:
- 当手机屏幕发生旋转时,如果Activity设置的是自动旋转的话,在旋转的过程中,Activity会被重新创建,如果用bindServie建立连接的话,便会断开服务(之前的Context不存在了),服务会被自动停止
- 如果同时使用startService与bindService方法启动Service,需要终止该Service时,要调用stopService和unbindService方法(unbindService依附于启动它的Context,startServicec并不依附于启动它的Context。如果先调用unbindService,这时服务并不会被终止,当调用stopService后,服务才会被终止;如果先调用stopService,服务也不会被终止,当调用unbindService或者之前调用bindService的Context不存在了(如Activity被finish掉了)服务才会自动停止);
- 当需要停止服务的时候,最好在Activity的onDestory()来进行停止服务
使用
1.新建一个Serivice后,先要在AndroidManifest.xml中注册Service,在application内添加需要注册的Service信息:
<service android:name=".TestService" >
android:exported="true"
</service>
2.Service文件里面有 两种启动方式
public class TestService extends Service{
@Override
public void onCreate() {
super.onCreate();
}
/**
* onBind 是 Service 的虚方法,因此我们不得不实现它。
* 返回 null,表示客服端不能建立到此服务的连接。
*/
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
// 已取代onStart方法--onStart方法是在Android2.0之前的平台使用的.
// 在2.0及其之后,则需重写onStartCommand方法,同时,旧的onStart方法则不会再被直接调用
// (外部调用onStartCommand,而onStartCommand里会再调用 onStart。在2.0之后,
// 推荐覆盖onStartCommand方法,而为了向前兼容,在onStartCommand依然会调用onStart方法。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(tag, "自启动的flags"+flags+" 启动的strtId"+startId);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);//休眠三秒===模仿耗时操作
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String str=intent.getStringExtra("name");
Log.e(tag, str);
}
}).start();
return START_REDELIVER_INTENT;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
}
// IBinder是远程对象的基本接口,是为高性能而设计的轻量级远程调用机制的核心部分。但它不仅用于远程
// 调用,也用于进程内调用。这个接口定义了与远程对象交互的协议。
// 不要直接实现这个接口,而应该从Binder派生。
// Binder类已实现了IBinder接口
class MyBinder extends Binder {
/**
* 获取Service的方法
* @return 返回TestService
*/
public TestService getService(){
return TestService.this;
}
}
}
3.start启动方式
public class TestActivity extends Activity{
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, TestSerice.class);
intent.putExtra("name", "启动了service");
startService(intent);// 启动服务
}
@Override
protected void onDestroy() {
super.onDestroy();
stopService(intent);// 在退出Activity时停止该服务
}
}
4.bind启动方式
1).本地绑定
public class TestActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, TestService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);//绑定目标Service
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);// 解除绑定,断开连接
}
// 在Activity中,我们通过ServiceConnection接口来取得建立连接与连接意外丢失的回调
ServiceConnection serviceConnection = new ServiceConnection() { @Override
public void onServiceConnected(ComponentName name, IBinder service){
// 建立连接
// 获取服务的操作对象
TestService.MyBinder binder = (TestService.MyBinder)service;
binder.getService();// 获取到的Service即TestService
}
@Override
public void onServiceDisconnected(ComponentName name) {
// 连接断开
}
};
}
2).远程绑定
AndroidManifest.xml中Service元素常见属性
- andorid:name:服务类名。可以是完整的包名+类名。也可使用.代替包名。
- adroid:exported:其他应用能否访问该服务,如果不能,则只有本应用或有相同用户ID的应用能访问。默认为false。
- android:enabled:显示给用户的服务名称。如果没有进行服务名称的设置,默认显示服务的类名。
- android:process : 服务所运行的进程名。默认是在当前进程下运行,与包名一致。如果进行了设置,将会包名后加上设置的集成名。 如果名称设置为冒号 :开头,一个对应用程序私有的新进程会在需要时和运行到这个进程时建立。如果名称为小写字母开头,服务会在一个相同名字的全局进程运行,如果有权限这样的话。这允许不同应用程序的组件可以分享一个进程,减少了资源的使用。
- android:icon : 服务的图标。
- android:permission:申请使用该服务的权限,如果没有配置下相关权限,服务将不执行,使用startService()、bindService()方法将都得不到执行。