7

There are similar posts to this, but none are quite what I'm looking for. I'd like to change the screen timeout for a specific activity. I want to avoid using WakeLock if possible and I don't want to change the device's system-wide timeout delay setting.

Is there any way of doing this short of manually tracking user activity and using a wake lock?

=----=

Clarification: for example, how can you set the screen inactivity timeout (the time it takes for the screen to turn off after there is no input) to be some value like 3 minutes?

It is possible to do this by setting the System settings, but this affects the entire device (even after the app is closed), so this is not a good solution.

Thanks!

Kleptine
  • 5,089
  • 16
  • 58
  • 81
Sheado
  • 161
  • 1
  • 7
  • Well, since your activity is in the foreground, you don't need a `WakeLock`. Just use `setKeepScreenOn()`, available on any handy `View`. So long as that `View` is on the screen, the screen stays on. I'm not aware of way for Android to tell you that such-and-so time has lapsed since user activity, though, so I suspect that you're on your own for that part. – CommonsWare Feb 13 '14 at 23:30
  • 1
    Thanks for the response. setKeepScreenOn() works fine, but I have to keep track of user activity to determine when the user has gone idle at which point I would let the screen turn off. I just wanted to make sure there wasn't some convenience function out there to do all this for me =] guess not though – Sheado Feb 14 '14 at 00:59
  • Did you ever find a nice way of doing this? – Kleptine Jul 31 '15 at 17:41
  • @GuyNoir Did you see this - http://stackoverflow.com/questions/1114270/android-screen-timeout – TDG Aug 01 '15 at 06:28

4 Answers4

5

First, a note on changing the System Settings to increase timeout for your activity. Intuitively I don't like this approach since you're making a system-wide change just to accomodate your application. Moreover, when changing System Settings in this manner it's hard to guarantee that you will be able to set it back(i.e. you forget to set it back / your app crashes before you set it).

A quick summary of the solution:

  • Use the Activity.onUserInteraction() method on Activity that is called for key, touch, trackball events.
  • When there is User interaction call View.setKeepScreenOn() on the root view of your activity(or some view within your activity that is persistent).
  • Use a simple Handler to post delayed messages to disable keeping the screen on after a certain amount of time.

Now, onto the code:

private ViewGroup mActivityTopLevelView;

private static final int DISABLE_KEEP_SCREEN_ON = 0;
private static final int SCREEN_ON_TIME_MS = 1000*60*3;

@Override
protected void onResume() {
    super.onResume();
    Log.d(TAG, "onResume");
    setScreenOn(true);
}

@Override
protected void onPause() {
    super.onPause();
    Log.d(TAG, "onPause");
    setScreenOn(false);
}

@Override
public void onUserInteraction() {

    super.onUserInteraction();
    Log.d(TAG, "onUserInteraction");
    setScreenOn(true);
}

private void setScreenOn(boolean enabled)
{
    // Remove any previous delayed messages
    Log.d(TAG, "setScreenOn to " + enabled);
    mHandler.removeMessages(DISABLE_KEEP_SCREEN_ON);

    if( enabled )
    {
        // Send a new delayed message to disable the screen on
        // NOTE: After we call setKeepScreenOn(false) the screen will still stay on for
        // the system SCREEN_OFF_TIMEOUT. Thus, we subtract it out from our desired time.
        int systemScreenTimeout = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 0);
        int totalDelay = SCREEN_ON_TIME_MS - systemScreenTimeout;
        if( totalDelay > 0 )
        {
            mActivityTopLevelView.setKeepScreenOn(true);
            Log.d(TAG, "Send delayed msg DISABLE_KEEP_SCREEN_ON with delay " + totalDelay);
            mHandler.sendEmptyMessageDelayed(DISABLE_KEEP_SCREEN_ON, totalDelay);
        }
    }
    else
    {
        mActivityTopLevelView.setKeepScreenOn(false);
    }
}

private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if(msg.what == DISABLE_KEEP_SCREEN_ON)
        {
            setScreenOn(false);
        }
    }
};

Tested on Android 5.1.0.

Trevor Carothers
  • 2,250
  • 11
  • 19
  • 1
    Ahh, you are a wonder. This is exactly what I was looking for. I was thinking of some sort of timer based solution, but I didn't know how to handle the input -- works great! Thanks! – Kleptine Aug 02 '15 at 08:33
  • What does `mActivityTopLevelView` need to be initialized to? – Michael Feb 14 '16 at 17:02
  • Great solution, but I have noticed that it doesn't work if the existing screen timeout is greater than the desired timeout - for instance, if I want a timeout of 1 minute but the default is 5 minutes, the screen doesn't go off until 5 minutes of no activity, instead of one minute. – Michael Feb 14 '16 at 17:43
  • You should be able to turn the screen off manually in the "else" condition of setScreenOn() to handle this case: http://stackoverflow.com/questions/6756768/turn-off-screen-on-android/6757206#6757206 – Trevor Carothers Feb 15 '16 at 18:36
0

From what I read, it looks like you are trying to dismiss the activity after some amount of time. (Please correct me if I misinterpreted your question.) You could try using a timer to dismiss the activity after a certain amount of time. For example:

new Timer().schedule(task, timeout);

Where task refers to the method that needs to be exectuted (A function dismissing your activity) and timeout represent s the delay before the task is executed.

Takide
  • 335
  • 3
  • 10
  • The question isn't about dismissing the activity. Normally on an android device, the screen turns off after a default period of inactivity (say 30 seconds). I want to change this period to 3 minutes, but *only* while my activity is in the foreground. – Kleptine Jul 31 '15 at 21:03
  • Ah that makes a lot more sense! I will update my response in a bit. – Takide Jul 31 '15 at 21:16
0

you have 2 requirements from what i understand in your question,
1)change a particular activity screen timeout.
2)if user is not interacting for long lock the screen. It can be done like this, for changing screen timeout, since you didnt want to use any WAKE LOCK try this

public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  }

you can read about it here https://developer.android.com/training/scheduling/wakelock.html

For the second part
As soon as the app starts start a timer in the shared preference of the app and if the timer count is crosses the required time limit then reset flag so that screen gets locked

Aniruddha K.M
  • 7,361
  • 3
  • 43
  • 52
  • The KEEP_SCREEN_ON flag keeps the screen on indefinitely, where I only want the screen to stay on for roughly 3 minutes. The timer would kind of work, but would have to be reset whenever an input is made, which would get messy (as you'd have to handle all possible inputs and devices). – Kleptine Jul 31 '15 at 21:02
0

Just change the setting temporarily while your app is foregrounded:

String originalTimeout;
int temporaryTimeout = 1 * 60 * 1000;
@Override
protected void onResume() {
    super.onResume();

    originalTimeout = Settings.System.getString(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT);
    Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, temporaryTimeout);
}

@Override
protected void onPause() {
    super.onPause();

    Settings.System.putString(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, originalTimeout);
}

This requires the android.permission.WRITE_SETTINGS permission.

tachyonflux
  • 20,103
  • 7
  • 48
  • 67
  • 1
    Someone else posted the correct solution, but the reason this doesn't work is because you could accidentally it overwritten if your app crashes or the phone suddenly shuts off (without a chance to run onPause). – Kleptine Aug 02 '15 at 08:34