android service,服务的正确姿势

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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值