I'm posting this because on a HUAWAI Prism II Android 4.1.1 (API 16) device the game I'm working on had the following annoying behavior:
I'm displaying my main menu which has some animation in a SurfaceView and plays a sound once in a while.
The device goes idle, dims, and then goes dark.
It calls onDestroy
on my Activity, and then while the screen is off creates my Activity again, calling onCreate
!
So the problem is my animations and sounds are playing while the screen is off. What I really want to happen is for my animation loop to not run at all if the screen is off. Broadcast receivers don't work because I can't store the state from the last time the screen went off. I thought about some hacks involving static booleans but it just seemed like a kluge that may not work and have horrible edge cases. The screen is already off when my Activity is created again, so I won't get an event through the broadcast receiver that my screen is off.
I solved this using both a broadcast receiver and the code listed above.
In my onCreate
, I create the broadcast receiver. This will control my animation loop when the screen turns on and off.
if (mScreenReceiver == null) {
mScreenIntentFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
mScreenIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
mScreenReceiver = new ScreenReceiver();
registerReceiver(mScreenReceiver, mScreenIntentFilter);
}
public class ScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
controlAnimLoop(false, false, true);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
controlAnimLoop(false, false, false);
}
}
}
In my controlAnimLoop, I check isScreenOn
, which is this code:
private boolean isScreenOn() {
if (android.os.Build.VERSION.SDK_INT >= 20) {
// I'm counting
// STATE_DOZE, STATE_OFF, STATE_DOZE_SUSPENDED
// all as "OFF"
DisplayManager dm = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
for (Display display : dm.getDisplays ()) {
if (display.getState () == Display.STATE_ON ||
display.getState () == Display.STATE_UNKNOWN) {
return true;
}
}
return false;
}
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
return powerManager.isScreenOn();
}