android编程需注意(第二话)如何让service不被kill掉

第一话地址:http://blog.csdn.net/programmersun/article/details/9849835

//本文会持续更新,希望大家能提出项目中遇到的问题和自己的观点与大家分享,让大家少走弯路。微笑

//注意:提出的内容需要以 观点/问题--->原因--->解决方案--->扩展的方式编写


观点:service可能会被系统杀掉,如何使他长时间活着呢?

原因:一个service默认是background的,这意味着当系统资源紧缺的时候,系统可能会杀掉service以此获取更多的资源空间。


解决方案:

1)在api level 5 之后可以使用startForeground去将service设置成foreground

      在api level 5之前可以使用以下代码去达到同样效果

private static final Class<?>[] mSetForegroundSignature = new Class[] {
    boolean.class};
private static final Class<?>[] mStartForegroundSignature = new Class[] {
    int.class, Notification.class};
private static final Class<?>[] mStopForegroundSignature = new Class[] {
    boolean.class};

private NotificationManager mNM;
private Method mSetForeground;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mSetForegroundArgs = new Object[1];
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];

void invokeMethod(Method method, Object[] args) {
    try {
        method.invoke(this, args);
    } catch (InvocationTargetException e) {
        // Should not happen.
        Log.w("ApiDemos", "Unable to invoke method", e);
    } catch (IllegalAccessException e) {
        // Should not happen.
        Log.w("ApiDemos", "Unable to invoke method", e);
    }
}

/**
 * This is a wrapper around the new startForeground method, using the older
 * APIs if it is not available.
 */
void startForegroundCompat(int id, Notification notification) {
    // If we have the new startForeground API, then use it.
    if (mStartForeground != null) {
        mStartForegroundArgs[0] = Integer.valueOf(id);
        mStartForegroundArgs[1] = notification;
        invokeMethod(mStartForeground, mStartForegroundArgs);
        return;
    }

    // Fall back on the old API.
    mSetForegroundArgs[0] = Boolean.TRUE;
    invokeMethod(mSetForeground, mSetForegroundArgs);
    mNM.notify(id, notification);
}

/**
 * This is a wrapper around the new stopForeground method, using the older
 * APIs if it is not available.
 */
void stopForegroundCompat(int id) {
    // If we have the new stopForeground API, then use it.
    if (mStopForeground != null) {
        mStopForegroundArgs[0] = Boolean.TRUE;
        invokeMethod(mStopForeground, mStopForegroundArgs);
        return;
    }

    // Fall back on the old API.  Note to cancel BEFORE changing the
    // foreground state, since we could be killed at that point.
    mNM.cancel(id);
    mSetForegroundArgs[0] = Boolean.FALSE;
    invokeMethod(mSetForeground, mSetForegroundArgs);
}

@Override
public void onCreate() {
    mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    try {
        mStartForeground = getClass().getMethod("startForeground",
                mStartForegroundSignature);
        mStopForeground = getClass().getMethod("stopForeground",
                mStopForegroundSignature);
        return;
    } catch (NoSuchMethodException e) {
        // Running on an older platform.
        mStartForeground = mStopForeground = null;
    }
    try {
        mSetForeground = getClass().getMethod("setForeground",
                mSetForegroundSignature);
    } catch (NoSuchMethodException e) {
        throw new IllegalStateException(
                "OS doesn't have Service.startForeground OR Service.setForeground!");
    }
}

@Override
public void onDestroy() {
    // Make sure our notification is gone.
    stopForegroundCompat(R.string.foreground_service_started);
}

2)相信大家看了上面两种方法的差异,都体会了andorid碎片化带来的麻烦。好在还有一种比较简单的方法,但是该方法只能在某些特定场合使用,如后台断点下载,推送服务之类的,如果用在音乐播放,就可能出现突然一卡的现象,这样很大的影响用户体验。该方法主要是在service的oncreate方法中新建一个计时器(使用alarmManager)这样每过一段时间就可以去启动一次service,当然如果service本身在running,那么就从onstartCommand开始,这样就可以达到和上面两种方法相同的效果。


扩展:service默认运行在主线程,所以不要在主线程中作耗时操作。


好啦,说到这里我提出一个疑问,举个例子,如一个service在播放音乐,为什么这个service没有影响我们的操作呢,或者说,为何我们感觉不到他的存在?



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值