WakefulIntentService实现说明

时间:2013-11-19 14:23:02

标签: android android-service intentservice commonsware-cwac

Commonsware的WakefulIntentService工作得很漂亮但有一些我不太了解的东西。以下是该服务的核心 - source的精简版:

class WIS extends IntentService {

    private static final String NAME = WIS.class.getName() + ".Lock";
    private static volatile WakeLock lockStatic = null;

    synchronized private static PowerManager.WakeLock getLock(Context context) {
        if (lockStatic == null) {
            PowerManager mgr = (PowerManager) context
                    .getSystemService(Context.POWER_SERVICE);
            lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
            lockStatic.setReferenceCounted(true);
        }
        return (lockStatic);
    }

    public static void startWIS(Context ctxt, Intent i) {
        getLock(ctxt.getApplicationContext()).acquire();
        ctxt.startService(i);
    }

    public WIS(String name) {
        super(name);
        setIntentRedelivery(true);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        PowerManager.WakeLock lock = getLock(this.getApplicationContext());
        if (!lock.isHeld() || (flags & START_FLAG_REDELIVERY) != 0) { // ?
            lock.acquire();
        }
        super.onStartCommand(intent, flags, startId);
        return (START_REDELIVER_INTENT);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        try {
            // do your thing
        } finally {
            PowerManager.WakeLock lock = getLock(this.getApplicationContext());
            if (lock.isHeld()) lock.release();
        }
    }
}

问题

  • 如果在我们的警报接收器的onReceive()返回后,该进程被终止会怎样?即如果服务onCreate()(如果服务尚未实例化)或onStartCommand()从未运行。 AFAIK一个被杀死的进程会锁定它。或者这是不可能的情况?
  • 鉴于之前应添加(flags & START_FLAG_RETRY)
  • 为什么if (!lock.isHeld())检查?
  • 为什么需要this.getApplicationContext()?是不是this

2 个答案:

答案 0 :(得分:5)

  

AFAIK一个被杀死的进程会锁定它。

正确。

  

或者这是不可能的情况吗?

这是不太可能的,但肯定不是不可能的。

  

鉴于之前应该添加(flags& START_FLAG_RETRY)吗?

这应由START_FLAG_REDELIVERY涵盖。 AFAIK,START_REDELIVER_INTENTRETRY没有REDELIVERY。如果你有相反的证据,我很乐意看到它。

  

为什么if(!lock.isHeld())检查?

在未保留的release()上调用WakeLock会导致异常。这只是一个安全毯,以确保我们不会抛出不必要的例外。从理论上讲,永远不需要它;理论上,我应该有头发。

  

为什么需要this.getApplicationContext()?这还不够吗?

我们创建了一个WakeLock,我们将其保存在静态数据成员中。 可能 getSystemService()来电并不会将Context调用PowerManager。而且,即使它确实如此,可能 Context也不会传递给生成的WakeLock实例。但是,为了安全起见,通过使用getApplicationContext(),我们以一种方式获取WakeLock,以确保我们可能“泄漏”的唯一Context是单例应用程序上下文,单身,有效预先泄露。 : - )

答案 1 :(得分:1)

抱歉没有足够的代表发表评论,但看起来你有两个支票的竞争状态,如果(持有)释放和if(!hold)获得。即使裁判变得不稳定并不足以防守你的比赛。

这些是在不同线程上调用的复合语句。您可能希望在私有最终Object lock = new Object()上为这两个检查输入同步块,以便它们以原子方式完成。非常好的角落,但我想提到它。如果你不同意,请告诉我。感谢。