Several Android devices famously the Nexus series have a magnetic sensor that is NOT the android.hardware.Sensor.TYPE_MAGNETIC_FIELD
used exclusively to turn the screen ON/OFF automatically using phone cases that have a small magnet inside them.
On my application, I'm using magnet detection using android.hardware.Sensor.TYPE_MAGNETIC_FIELD
and the SensorManager
to detect user touches the phone in a case with some magnets inside.
The code works without issues, the problem is that it's extremely easy on those devices to accidentally trigger the screen ON/OFF sensor thou, turning off the screen.
I've tried:
android:keepScreenOn="true"
on the XMLandroid.permission.WAKE_LOCK
and acquiring a wake-lock via PowerManager
.Both without success.
Is there a way to temporarily disable this sensor while my activity is resumed?
The keepScreenOn = true in manifest also doesn't work here as the action of hall effect sensor is same as pressing power button.
Here, I offer a work-around that I have tested. In this approach you display your activity regardless of hall-effect sensor locking the device and turning of the display.
Before beginning the unlocking action
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
credits for above code - https://stackoverflow.com/a/45951927/9640177
Also make sure to add Permissions
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
Setting these flags will make sure that your window will be visible above lockscreen.
Now, listen for ACTION_SCREEN_OFF intent. To do this add a broadcast receiver that listens for this intent broadcasted by the system. You need to register the receiver locally. (stackoverflow.com/a/9478013/9640177) in manifest
<receiver android:name=".receiver">
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF"/>
</intent-filter>
</receiver>
Receiver class
public class receiver extends BroadcastReceiver {
MyActivity activity;
receiver(MyActivity activity){
this.activity = activity;
}
@Override
public void onReceive(final Context context, Intent intent) {
activity.turnOnScreen();
}
}
Inside activity
// register receiver
...
IntentFilter screenStateFilter = new IntentFilter();
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
receiver r = new receiver(MyActivity.this);
registerReceiver(r, screenStateFilter);
...
// function to turn on display
public void turnOnScreen(){
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "my:Tag");
wakeLock.acquire();
wakeLock.release();
}
credit - https://stackoverflow.com/a/44706632/9640177 This will turn the display on.
Don't forget to remove these flags after your activity has done the job and does not require to be in forefront.
getWindow().removeFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
This will make your window disappear from lock-screen and make the application function normally.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With