简体   繁体   中英

Activity return to Portrait when Screen is Locked

Related questions:


This is a strange behaviour i got in my Activities.

Portrait mode (It's normal)

  1. Press screen lock, Activity: onPause() ;
  2. Unlock the screen, Activity: onResume() .

Landscape mode (It's strange)

  1. Press screen lock, Activity: onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume() which loads the Portrait layout;
  2. Unlock the screen, Activity: onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume() and loads the Landscape layout.

What I expect is:

Portrait mode: (same)

Landscape mode: (should act like Portrait mode)

  1. Press screen lock, Activity: onPause() ;
  2. Unlock the screen, Activity: onResume() .

So my questions:

  • Why does my Activities behave like this?
  • How does your Activities behave?

Original text description of my question:

While i press the Lock Screen button of my phone, when my Activity is at its Landscape mode, i noticed (in the debug messages i output to Eclipse) the Activity is re-created to its Portrait mode (while the screen is all black, of course). Then when i press the Lock Screen button again to unlock the screen, the Activity was destroyed and re-created to its Portrait again.

As i remember (not 100% sure though), and what i expect is, my Activity should only undergo onSaveInstanceState() and onPause() , while Lock Screen in Landscape mode, like what it does in Portrait mode. Rather than re-creating the Activity to Portrait and going back to Landscape again.

Is it that i have messed up something with my phone? How can i fix it back to normal?

Thanks!


Thanks everyone for contributing into this issue. Especially thanks @HoanNguyen for his effort of testing for me in his devices. And Especially thanks @Raghunandan for having an in-depth discussion with me concerning this issue.

Summarising everyone's contributions so far, i have the following conclusions:

1. This is a normal phenomenon.

It seems that, on mobile phones, the running Activities, that are in Landscape mode, are switched into Portrait mode upon screen lock is a normal behaviour. At least it is true on the tested phones so far. So we have to make sure our lifecycle functions can take care this change elegantly always.

2. Guess this is because of the "default orientation" in the locked screen.

We do not have documentation or many resource talking about this issue. But the assumption that the running Activities switching back to the device's "default orientation" upon screen lock, as in most devices the locked screen is in Portrait, is quite logical.

Further study:

I just wonder how the Activities behave if we are having a landscape locked screen?

You can stop the activity from restarting on orientation change but this is generally a pretty bad idea.

The Android documentation has a section on handling runtime changes with this note:

Note: Handling the configuration change yourself can make it much more difficult to use alternative resources, because the system does not automatically apply them for you. This technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications.

Android generally only recommends you supress recreating on rotation if you don't need alternate resources and , more importantly, have a performance requirement. A well-designed app shouldn't need to do this in most cases.

If you insist on going down the path of supressing default Android behavior, I'd modify Raghunandan's code and include a screen size attribute as well. As of API level 13, the screen size changes upon orientation change. So you must include screenSize unless you are only targeting API 12 and below.

<activity android:name=".MyActivity"
      android:configChanges="orientation|screenSize"
      android:label="@string/app_name">

To avoid activity from restarting

<activity android:name=".MyActivity"
      android:configChanges="orientation|keyboardHidden"//add tthis in manifest
      android:label="@string/app_name">

http://developer.android.com/guide/topics/resources/runtime-changes.html .

In normal circumstances when your screen is locked your activity is paused and when screen is unlocked activity resumes.

An issue when screen locked is: Current Activity may be stopped forcefully by the system if it finds shortage of memory, instead of moving Activity to background . In such a case, we should have to save (all the necessary data) the current state of the Activity.

Save you data in onSaveInstanceState() and restore data onRestoreInstanceState().

@Override
 public void  onSaveInstanceState(Bundle outState)
 {
  Log.v("$````$", "In Method: onSaveInstanceState()");
  //if necessary,set a flag to check whether we have to restore or not
  //handle necessary savings…
 }

@Override
public void onRestoreInstanceState(Bundle inState)
{
  Log.v("$````$", "In Method: onRestoreInstanceState()");
  //if any saved state, restore from it…
}

In your onCreate()

IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);

mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter); //register


public class ScreenReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent)
   {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
        {    
              Log.v("$$$$$$", "In Method:  ACTION_SCREEN_OFF");
              // onPause() will be called.
        }
        else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON))
        {
              Log.v("$$$$$$", "In Method:  ACTION_SCREEN_ON");
              //onResume() will be called.
              //Better check for whether the screen was already locked
              // if locked, do not take any resuming action in onResume()
              //Suggest you, not to take any resuming action here.       
        }
        else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT))
        {
              Log.v("$$$$$$", "In Method:  ACTION_USER_PRESENT"); 
              //Handle resuming events
        }
  }

In your onDestroy

  @Override
  public void onDestroy()
  {
        super.onDestroy();
        Log.v("$$$$$$", "In Method: onDestroy()");

        if (mReceiver != null)
        {
              unregisterReceiver(mReceiver); //unregister 
              mReceiver = null;
        }          

  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM