service,android四大组件之一,脱离UI在后台运行。特点和具体如何使用无需多言吧。
一,service是个什么鬼
Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。
Started Service生命周期及进程相关
1.onCreate(Client首次startService(..)) >> onStartCommand >> onStartCommand - optional … >> onDestroy(Client调用stopService(..))
注:onStartCommand(..)可以多次被调用,onDestroy()与onCreate()想匹配,当用户强制kill掉进程时,onDestroy()是不会执行的。
2.对于同一类型的Service,Service实例一次永远只存在一个,而不管Client是否是相同的组件,也不管Client是否处于相同的进程中。
3.Service通过startService(..)启动Service后,此时Service的生命周期与Client本身的什么周期是没有任何关系的,只有Client调用stopService(..)或Service本身调用stopSelf(..)才能停止此Service。当然,当用户强制kill掉Service进程或系统因内存不足也可能kill掉此Service。
4.Client A 通过startService(..)启动Service后,可以在其他Client(如Client B、Client C)通过调用stopService(..)结束此Service。
5.Client调用stopService(..)时,如果当前Service没有启动,也不会出现任何报错或问题,也就是说,stopService(..)无需做当前Service是否有效的判断。
6.startService(Intent serviceIntent),其中的intent既可以是显式Intent,也可以是隐式Intent,当Client与Service同处于一个App时,一般推荐使用显示Intent。当处于不同App时,只能使用隐式Intent。
在AndroidManifest.xml文件中注册service。
<!--apk升级,自动备份,监测网络状态-->
<service android:name="com.x x.service.OairService">
<intent-filter>
<action android:name="com.x x.oairService.action"/>
</intent-filter>
</service>
service实现类,继承Service。
/**
* DemoService 生命周期方法
* Created by duqian on 16/5/11.
*/
public class DemoService extends Service {
private Context context;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
二,service一些常用方法
开启和停止service,要注意兼容android 5.0以上版本,服务启动要设置你应用的包名,否则会报错,闪退。
/**
* service 工具类
* Created by duqian on 15/12/28.
*/
public class ServiceUtil {
private static final String TAG =ServiceUtil.class.getSimpleName();
//开启服务:
public static void startService(Context context,Class clazz) {
boolean serviceRunning = SystemUtils.isServiceRunning(context, clazz);
if (serviceRunning){
forceStopService(context,clazz);//先停止再开启:重启服务,防止服务失效。
}
Intent service = new Intent(context, clazz);
//Intent service = new Intent();
//service.setAction("com.oair.oairService.action");
service.setPackage(context.getPackageName());//这里你需要设置你应用的包名,5.0新要求
context.startService(service);//多次调用startService并不会启动多个service 而是会多次调用onStart
}
/**
* 停止service
* @param context
* @param clazz
*/
public static void stopService(Context context,Class clazz) {
boolean serviceRunning = SystemUtils.isServiceRunning(context, clazz);
if (serviceRunning){
forceStopService(context, clazz);
}
}
private static void forceStopService(Context context, Class clazz) {
Intent intent = new Intent(context, clazz);
intent.setPackage(context.getPackageName());//这里你需要设置你应用的包名,5.0新要求
context.stopService(intent);
//LogUtils.debug(TAG,clazz.getSimpleName()+" is stopped");
}
/**
* service中检测本应用是否为前台界面
* @param context
* @return
*/
public static boolean checkAppRunning(Context context) {
boolean isRunning = false;
ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = activityManager.getRunningTasks(1).get(0).topActivity;
String topPackageName = cn.getPackageName();
String myPackageName = context.getPackageName();
if (topPackageName != null && topPackageName.equals(myPackageName)) {
//在这里停止含有定时执行的服务,在停止之前需要先取消该定时器
isRunning = true;
//LogUtils.debug(TAG,"当前栈顶应用:" + topPackageName + ",myPackageName=" + myPackageName);
}else{
isRunning = false;
}
return isRunning;
}
}
三,service相关常识
startService 启动的服务,主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService。
bindService 启动的服务,要进行通信。停止服务使用unbindService。
startService 同时也 bindService 启动的服务,停止服务应同时使用stopService与unbindService。
android中打造不死的service比较麻烦,因为非前台进程会被系统kill。
重点关注下onStartCommand(Intent intent, int flags, int startId)方法。
其中参数flags默认情况下是0,对应的常量名为START_STICKY_COMPATIBILITY。startId是一个唯一的整型,用于表示此次Client执行startService(…)的请求请求标识,在多次startService(…)的情况下,呈现0,1,2….递增。另外,此函数具有一个int型的返回值,具体的可选值及含义如下:
START_NOT_STICKY:当Service因为内存不足而被系统kill后,接下来未来的某个时间内,即使系统内存足够可用,系统也不会尝试重新创建此Service。除非程序中Client明确再次调用startService(…)启动此Service。
START_STICKY:当Service因为内存不足而被系统kill后,接下来未来的某个时间内,当系统内存足够可用的情况下,系统将会尝试重新创建此Service,一旦创建成功后将回调onStartCommand(…)方法,但其中的Intent将是null,pendingintent除外。
START_REDELIVER_INTENT:与START_STICKY唯一不同的是,回调onStartCommand(…)方法时,其中的Intent将是非空,将是最后一次调用startService(…)中的intent。
欢迎交流,杜工,Dusan,Q291902259。