Почему метод onPause вызывается сразу после onCreate
Я пишу приложение, которое показывает активность в определенное время.
Я запускаю действие из службы с таким кодом:
intent.setClass(context, FakeAction.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
в методе onCreate FakeAction Мне требуется пробуждение устройства и запуск звукового сообщения:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
В onCreate есть много кода, чтобы отображать информацию на экране и запускать звуковое сообщение.
Вот метод onPause:
@Override
protected void onPause()
{
Log.i(TAG, "onPause");
//Stop mediaPlayer
if(mp != null)
{
if(mp.isPlaying())mp.stop();
mp.release();
mp = null;
}
//Restore volume
if(audioManager != null)
{
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, savedVolume, 0);
}
//Stop minute timer
handler.removeCallbacks(minuteReceiver);
super.onPause();
}
К сожалению, метод onPause() вызывается сразу после onCreate. Поэтому мое звуковое сообщение немедленно прекращается.
Но если действие запускается, когда экран не заблокирован, onPasue() не вызывается сразу после onCreate();
Даже если я комментирую все строки getWindow(). addFlags(), то onPause() вызывается после onCreate(), когда экран заблокирован.
Вопрос в том, почему onPause вызывается сразу после onCreate?
Как я могу отличить немедленный вызов метода onPause() и вызова onPause(), когда пользователь нажимает кнопку "Назад"?
Ниже приведен код действия. Я использую шаблон MVP, поэтому основной код находится в презентаторе.
Но даже если я прокомментирую все вызовы ведущего (как в этом примере), onPause() вызывается сразу после onCreate()
Возможно ли, что я начал работу в AsyncTask? AsyncTask запускает сервис формы. Служба прекращается после завершения AsyncTask.
public class FakeAction extends RoboActivity
implements
View.OnClickListener
,AlarmAction
{
private static final String TAG = "TA FakeAction";
@InjectView(R.id.aa_btn_Stop) Button btnStop;
@InjectView(R.id.aa_btn_Snooze) Button btnSnooze;
@InjectView(R.id.aa_tv_CurTime) TextView tvCurTime;
@InjectView(R.id.aa_tv_CurDate) TextView tvCurDate;
@InjectView(R.id.aa_tv_AlarmName) TextView tvAlarmName;
@Inject public AlarmActionPresenter presenter;
private Exception ex;
@Override
public void onCreate(Bundle savedInstanceState)
{
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
setContentView(R.layout.alarm_action);
try
{
//presenter.onCreate(this);
}
catch(Exception ex)
{
this.ex = ex;
Log.e(TAG, "onCreate", ex);
}
btnStop.setOnClickListener(this);
btnSnooze.setOnClickListener(this);
}
@Override
protected void onPause()
{
Log.i(TAG, "onPause");
//presenter.onPause();
super.onPause();
}
@Override
public void onClick(View v)
{
Log.i(TAG, "onClick");
//presenter.onClick(v.getId());
}
@Override
public Bundle getIntentBundle()
{
return getIntent().getExtras();
}
@Override
public void setAlarmName(String alarmName)
{
tvAlarmName.setText(alarmName);
}
@Override
public String getAlarmName()
{
return tvAlarmName.getText().toString();
}
@Override
public void setCurTime(String curTime)
{
tvCurTime.setText(curTime);
}
@Override
public String getCurTime()
{
return tvCurTime.getText().toString();
}
@Override
public void setCurDate(String curDate)
{
tvCurDate.setText(curDate);
}
@Override
public String getCurDate()
{
return tvCurDate.getText().toString();
}
@Override
public IAssetFileDescriptorMockable openFd(String assetName) throws IOException
{
Log.i(TAG, "openFd");
return new AssetFileDescriptorMockable(getAssets().openFd(assetName));
}
}
Ответы
Ответ 1
Я нашел решение моей проблемы.
Причиной, по которой onPause вызывается после onCreate, является ActivityManager.
В журнале я нашел строку сразу после onCreate: "Тайм-аут паузы активности для HistoryRecord"
Итак, следующие события произошли в моей деятельности:
- OnCreate()
- OnStart()
- onResume()
- Тайм-аут приостановки активности для HistoryRecord
- OnPause()
- onResume()
Я не знаю, как предотвратить "Тайм-аут паузы активности для HistoryRecord", но я изменил свое приложение, чтобы оно запускало звуковое сообщение в onResume(). Даже если он остановлен в onPause(), он снова запускается в следующем onResume().
Ответ 2
Вот что, я думаю, происходит, тогда: ваш сервис создает вашу активность, и ваша деятельность делает несколько вещей, например, пробуждение экрана и отказ от блокировки клавиатуры. Но это не мгновенно, а это значит, что активность keyguard, вероятно, разбудилась до того, как ее уволили, тем самым приостановив вашу деятельность на короткое время.
Я думаю, что вы должны это сделать: http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
Справьтесь с этим, используя намерение. Вы поймете намерение сказать, что экран включен, и намерение выключить экран.
Цикл будет работать так, я думаю:
- Вы создадите свою активность.
- Ваша деятельность будет продолжаться. При попытке отклонить блокировку клавиатуры и настроить несколько вещей.
- Ваша активность снова проснется.
- Ваша активность будет получать экран при намерении
Это означает: когда вызывается onPause, экран выключен! Значение: вам нужен только флаг, и если этот флаг говорит, что экран по-прежнему выключен, вы не приостанавливаете музыку.
Это немного грязно, но должно отлично работать.
Ответ 3
Я решил свою проблему, проверив, включен ли экран с помощью следующего кода:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if (!powerManager.isScreenOn()){
return;
}
Используйте код, если прекращаете звуковую активность, когда нажимаете кнопку домой. onPause
не активен, пока экран не включен.
@Override
protected void onPause() {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if (powerManager.isScreenOn()){
Log.e("Test two", "****");
Intent i = new Intent(this, RingtonePlayingService.class);
stopService(i);
finish();
}
super.onPause();
}
Таким образом, код в методе onPause
выполняется только при включенном экране. Когда экран включается и вызывается onPause
, метод isScreenOn
из PowerManager
возвращает false.
Ответ 4
Запустите намерение, которое проверит, выходит ли пользователь и привязывает его к вашей кнопке выхода.
Я все еще не уверен, что вы хотите, поскольку код является неполным.
Ответ 5
You can distinguish onPause() call between Acticity itself and back button press.
onBackPressed(){
// set isBackPressed = true;
}
onPause(){
if(isBackPressed ){
// exit due to back pressed.
}else{
// normal exit.
}
}
Ответ 6
Если у вас есть ES File Explorer
, тогда FORCE STOP. Так или иначе, они прерывают жизненный цикл вашего приложения (комментарии предполагают какое-то наложение).
Моя проблема с тем, что onResume
вызывался дважды, была из-за того, что onPause
как-то вызывали после создания действия... что-то прерывало мое приложение.
И это происходит только после первого открытия после установки или сборки из студии.
Я получил подсказку из другого поста и узнал, что это из-за ES File Explorer. Почему onResume(), кажется, вызывается дважды?
Как только я принудительно прекращаю работу ES File Explorer, такой сбой больше не происходит... расстраивает, когда узнает много других предложенных решений. Так что остерегайтесь любых других прерывающих приложений, таких как это.