2009-07-01 1 views
13

Я создал приложение, которое использует камеру и во время выполнения приложения экран всегда включен.Android: Как освободить ресурсы, когда приложение завершается?

В методе OnCreate() Я добавил замок:

final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag"); 
this.mWakeLock.acquire(); 

И это переопределенный метод OnStop():

@Override 
protected void onStop() { 

    if(mWakeLock.isHeld()) 
    { 
     mWakeLock.release(); 
    } 

    super.onStop(); 
} 

Но после окончания приложения экрана остается на все и если я запускаю приложение камеры, он обнаруживает ошибку, которая, очевидно, появляется, потому что ресурсы камеры не освобождаются.

Кто-нибудь знает, как освободить все ресурсы при завершении приложения?

ответ

13

Я бы передвинул замок от OnCreate() до OnResume(). Вы хотите блокировку в течение видимого времени жизни Activity, а не всего срока действия Activity. Вы, возможно, все еще будете работать с другим действием, выполняющимся перед ним.

Я бы переместил выпуск на OnPause(). OnPause() - это самый ранний момент, когда ваше приложение обычно должно быть убито ОС.

Кроме того, я не проверял, есть ли у меня замок перед выпуском. Если вы используете OnResume() для приобретения замка; isHeld всегда должно быть правдой в OnPause().

+1

Ваше предложение для не проверки состояния блокировки нормально, если расцепитель() является операцией идемпотентная. Если нет, это плохо. Что делать, если приложение не удалось получить блокировку и хочет закрыть приложение? – Thushan

+1

Отличный комментарий. Я посмотрел исходный код Android. Похоже, что единственный способ, которым вы не можете получить блокировку, - это нарушение вашего вызова, и в этом случае он регистрирует ошибку, но не делает исключение. Если вы вызываете release(), не приобретая блокировки, он будет генерировать исключение «Wake-Lock under-locked». Документация по покупке() ведет к мысли, если вы попросите замок, вы получите замок. Но если вы должны проверить, то вы должны проверить сразу после получения(), а не после того, как программа была запущена, и вы собираетесь выйти. – Will

1

Где вы называете finish()?

Вы должны освобождать свои ресурсы в onPause, а не onStop. Нет никакой гарантии, что onStop всегда будет вызван до того, как ваша деятельность будет убита. Если системе нужны ресурсы, тогда она может убить активность до вызова onStop.

Попробуйте поместить отладочные журналы и отслеживать путь выполнения, если считаете, что ваше приложение завершено.

3

Звучит так, как будто ваше приложение никогда не вызывает выпуск на Wakelock - возможно ли, что оно выбрасывает исключение раньше в onStop или onPause? Я бы включил некоторые протоколы, в которых вы вызываете выпуск, чтобы подтвердить, что он выполняется.

В любом случае, вы обязательно захотите переместить методы acquire и release в onResume и onPause соответственно. Код, который у вас есть, только приобретет WakeLock при первом запуске приложения.

Благодаря фоновой обработке Android ваш код имеет потенциальный дисбаланс. Если пользователь нажимает клавишу «домой» для переключения приложений, блокировка будет отпущена. Если они вернутся к вашему приложению, то CreateCreate не будет вызываться, поэтому блокировка никогда не будет получена.

Лучше всего построить WakeLock в onCreate (как есть), получить блокировку в onResume и отпустить ее в onPause (включая вызов isHeld). Это гарантирует, что блокировка будет храниться всякий раз, когда ваше приложение находится на переднем плане.

2

У меня были проблемы с выпуском данных, когда я использовал OpenGL. Итак, теперь с android.os.Process.killProcess (android.os.Process.myPid()); он работает так, как я хочу!

Благодаря Арт

3

Я использую mWakelock.setReferenceCounted (ложь), до сих пор не знаю, что это значит, но это решает мой «Wakelock под автоподстройки» проблемы.

Init: OnStart() приобретают: onResume() релиз: OnStop()