Serveric 四大组件之一
运行于后台。定义方式:创建Java类继承Service,在清单文件中注册该类。
两种启动方式:
1.startService
生命周期:onCreate->onStartCommond->onDeStroy
重复的startService不会调用onCreate只会调用onStartCommand
该服务所在进程会变成服务进程,启动他的Activity不再与它有任何联系。
2.bindService
生命周期:onCreate->onBind->onUnBind->onDeStroy
绑定的服务与启动他的Activity同生共死,Activity销毁了,服务也销毁。不过服务销毁了,Activity不会销毁。
ps:由于Service 的onStart()方法只有在startService()启动Service的情况下才调用,故使用onStart()的时候要注意这点。
与 Service 通信并且让它持续运行
如果我们想保持和 Service 的通信,又不想让 Service 随着 Activity 退出而退出呢?你可以先 startService() 然后再 bindService() 。当你不需要绑定的时候就执行 unbindService() 方法,执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。
这样就可以既保持和 Service 的通信,也不会随着 Activity 销毁而销毁了。
关于怎样让服务不被杀死
这个倒是有点流氓软件的意思,但有些特定情况还是需要服务能保持开启不被杀死,当然这样做我还是在程序里添加了关闭服务的按钮,也就是开启了就杀不死,除非在软件里关闭。服务不被杀死分3种来讨论
1.系统根据资源分配情况杀死服务
2.用户通过settings
->Apps
->Running
->Stop
方式杀死服务
3.用户通过settings
->Apps
->Downloaded
->Force Stop
方式杀死服务
第一种情况:
用户不干预,完全靠系统来控制,办法有很多。比如onStartCommand()方法的返回值设为START_STICKY
,服务就会在资源紧张的时候被杀掉,然后在资源足够的时候再恢复。当然也可设置为前台服务,使其有高的优先级,在资源紧张的时候也不会被杀掉。
StartCommond几个常量参数简介:
1、START_STICKY
在运行onStartCommand后service进程被kill后,那将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建 service后将保证调用onstartCommand。如果没有传递任何开始命令给service,那将获取到null的intent。
2、START_NOT_STICKY
在运行onStartCommand后service进程被kill后,并且没有新的intent传递给它。Service将移出开始状态,并且直到新的明显的方法(startService)调用才重新创建。因为如果没有传递任何未决定的intent那么service是不会启动,也就是期间onstartCommand不会接收到任何null的intent。
3、START_REDELIVER_INTENT
在运行onStartCommand后service进程被kill后,系统将会再次启动service,并传入最后一个intent给onstartCommand。直到调用stopSelf(int)才停止传递intent。如果在被kill后还有未处理好的intent,那被kill后服务还是会自动启动。因此onstartCommand不会接收到任何null的intent。
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- flags = START_STICKY;
- return super.onStartCommand(intent, flags, startId);
- }
第二种情况:
用户干预,主动杀掉运行中的服务。采用broadcast+service的方式。这个过程杀死服务会通过服务的生命周期,也就是会调用onDestory()方法,这时候一个方案就是在onDestory()中发送广播开启自己。这样杀死服务后会立即启动。如下:
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
mBR = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent a = new Intent(ServiceA.this, ServiceA.class);
startService(a);
}
};
mIF = new IntentFilter();
mIF.addAction("listener");
registerReceiver(mBR, mIF);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Intent intent = new Intent();
intent.setAction("listener");
sendBroadcast(intent);
unregisterReceiver(mBR);
}
当然,从理论上来讲这个方案是可行的,实验一下也可以。但有些情况下,发送的广播在消息队列中排的靠后,就有可能服务还没接收到广播就销毁了(这是我对实验结果的猜想,具体执行步骤暂时还不了解)。所以为了能让这个机制完美运行,可以开启两个服务,相互监听,相互启动。服务A监听B的广播来启动B,服务B监听A的广播来启动A。经过实验,这个方案可行,并且用360杀掉后几秒后服务也还是能自启的。到这里再说一句,如果不是某些功能需要的服务,不建议这么做,会降低用户体验。
还有一种做法就是监听手机重启、界面唤醒、应用状态改变等并捕获,然后判断我们的Service是否还存活,(记得加权限)
- <receiver android:name="com.dbjtech.acbxt.waiqin.BootReceiver" >
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <action android:name="android.intent.action.USER_PRESENT" />
- <action android:name="android.intent.action.PACKAGE_RESTARTED" />
- <action android:name="com.dbjtech.waiqin.destroy" />
- </intent-filter>
- </receiver>
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
- System.out.println("手机开机了....");
- startUploadService(context);
- }
- if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
- startUploadService(context);
- }
- }
【结论】这也能算是一种措施,不过感觉监听多了会导致Service很混乱,带来诸多不便
第三种情况:
强制关闭就没有办法。这个好像是从包的level去关的,并不走完整的生命周期。所以在服务里加代码是无法被调用的。处理这个情况的唯一方法是屏蔽掉force stop
和uninstall
按钮,让其不可用。方法自己去找吧。当然有些手机自带的清理功能就是从这个地方清理的,比如华为的清理。所以第三种情况我也没有什么更好的办法了。
还有就是提高
提升service进程优先级
Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
1.前台进程( FOREGROUND_APP)
2.可视进程(VISIBLE_APP )
3. 次要服务进程(SECONDARY_SERVER )
4.后台进程 (HIDDEN_APP)
5.内容供应节点(CONTENT_PROVIDER)
6.空进程(EMPTY_APP)
当service运行在低内存的环境时,将会kill掉一些存在的进程。因此进程的优先级将会很重要,可以使用startForeground将service放到前台状态。这样在低内存时被kill的几率会低一些。
本文参考了:http://blog.csdn.net/mad1989/article/details/22492519
http://www.cnblogs.com/rossoneri/p/4530216.html