android – Why the onPause method is called immediately after onCreate-ThrowExceptions

Exception or error:

I’m writing an application that show an activity at fixed time.

I start the activity from service with such code:

intent.setClass(context, FakeAction.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

in the onCreate method of FakeAction I require wake up of device and start sound message:

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);

There is a lot of code in onCreate to show information on screen and start the sound message.

Here is an onPause method:

@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();
}

Unfortunately the onPause() method is called immediately after onCreate. So my sound message is immediately stopped.

But if the activity is started when the screen is not locked then the onPasue() is not called immediately after onCreate();

Even though I comment all of “getWindow().addFlags()” strings the onPause() is called after onCreate() when the screen if locked.

The question is why onPause is called immediately after onCreate?
How can I distinguish immediate call of onPause() method and call of onPause() when user press the back button?

Below is the code of the activity. I use the MVP pattern, so, the main code is in presenter.
But even if I comment all presenter’s calls (like I done in this example) the onPause() is called immediately after onCreate()

Can it have a sence that I start activity in AsyncTask? The AsyncTask is started form service. The service is stopped after the AsyncTask if finished.

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));
    }

}
How to solve:

I found out the solution of my problem.

The reason why the onPause called after onCreate is the ActivityManager.
In the log I’ve found the line immediately after onCreate: “Activity pause timeout for HistoryRecord”
So, next events happened in my Activity:

  1. onCreate()
  2. onStart()
  3. onResume()
  4. Activity pause timeout for HistoryRecord
  5. onPause()
  6. onResume()

I don’t know how to prevent the “Activity pause timeout for HistoryRecord” but I changed my application so it starts the sound message in onResume(). Even though it is stopped in onPause() it is started again in next onResume().

###

Here is what I think happens, then : your service creates your activity, and your activity does several things, such as waking up the screen and dismissing the keyguard. But it’s not instant, which means that the keyguard activity is probably woken up before being dismissed, thus pausing your activity for a short while.

I think what you should is this : http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/

Deal with it using intent. You catch the intent saying that the screen is on, and the intent that the screen is off.

The cycle will work like that, I think :

  • You’ll create your activity
  • Your activity will go onPause while trying to dismiss the keyguard and tuning a few things up
  • Your activity will wake again
  • Your activity will receive the screen on intent

That means : when the onPause is called, the screen is off ! Meaning : you just need a flag, and if this flag says that the screen is still off, you don’t pause the music.

It’s a bit dirty, but should work perfectly.

###

I solved my problem by testing wheter the screen is on or off with this code:

    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);  
    if (!powerManager.isScreenOn()){
       return;
    }

Use code if stop sound activity when press home button. onPause not acive until screen is not on.

  @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();
    }

So the code in the onPause method is only done if the screen is On. When the screen is turning on and onPause is called the isScreenOn method of PowerManager returns false.

###

Start an intent that will check if the user is exiting and tie that to your exit button.
I am still unsure what you want as the code is incomplete

###

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.
}
}

###

If you have ES File Explorer then FORCE STOP it. Somehow, they interrupt your app’s lifecycle (comments suggest some kind of overlay).

My issue with onResume being caused twice was because onPause was somehow being called after the activity was created.. something was interrupting my app.

And this only happens after being opened for the first time after installation or built from studio.

I got the clue from another post and found out it was because of ES File Explorer. Why does onResume() seem to be called twice?

As soon as I force stop ES File Explorer, this hiccup behavior no longer happens… it’s frustrating to know after trying many other proposed solutions. So beware of any other interrupting apps like this one.

Leave a Reply

Your email address will not be published. Required fields are marked *