Turning on screen from receiver/service - android

I would like my app to be able to turn the screen on and display my app. Let's say I'm setting an alarm and every hour I want my app to be displayed for 2 mins before the device naturally sleeps.
I see that WakeLock (FULL_LOCK) and KeyguardManager are deprecated.
I have created a WakefulBroadcastReceiver and service and these are working.
#Override
protected void onHandleIntent(Intent intent) {
// I need to show the screen here!
for (int i=0; i<5; i++) {
Log.i("SimpleWakefulReceiver", "Running service " + (i + 1)
+ "/5 # " + SystemClock.elapsedRealtime());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
Log.i("SimpleWakefulReceiver", "Completed service # " +
SystemClock.elapsedRealtime());
SimpleWakefulReceiver.completeWakefulIntent(intent);
}
How do I programmatically turn on the screen, get past lock and display my Activity from the IntentService ?
Thanks

You can use this code to turn the screen on.
lock = ((KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE)).newKeyguardLock(KEYGUARD_SERVICE);
powerManager = ((PowerManager) getSystemService(Context.POWER_SERVICE));
wake = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
lock.disableKeyguard();
wake.acquire();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
You need the following permission in AndroidManifest.xml file:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
EDIT (USE THIS ONE, NOTHING IS DEPRECATED):
There is an one more alternative for doing this, for that you need to launch an activity, In the activity onCreate() you need to add the flags to the window.
For example:
#Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);`
}

I don't know what you're talking about, wakelock is definitely not deprecated. Certain types are no longer the Google preferred way of doing things, but normal wakelocks are still around and still the easiest way of doing this. Make sure to add the ACQUIRE_CAUSES_WAKEUP flag when taking the lock. In fact notice that a WakefulBroadcastReceiver is implemented by using wakelocks.

You can use this code to turn the screen on.
private void turnScreenOn() {
int flags = WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
getWindow().addFlags(flags);
}
You can use this code to keep it on until the wake lock is dimissed.
<uses-permission android:name="android.permission.WAKE_LOCK" />
private PowerManager mPowerManager;
private PowerManager.WakeLock mWakeLock;
#Override
public void onCreate() {
super.onCreate();
mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "Service");
}
private void acquireWakeLock() {
try {
mWakeLock.acquire();
}
catch (Exception e) {
e.printStackTrace();
}
}
private void releaseWakeLock() {
try {
mWakeLock.release();
}
catch (Exception e) {
}
}

Related

Launch Activity from FCM

In my application, i need to launch an activity and turn screen on, when high-priority FCM message is received. It's an alarm activity, which is very, very important for users.
On most Android devices, the code is working fine. However, on some Huawei or LG devices, the activity is not launched when the device is in Doze mode, or in the pocket (proximity sensor). The behaviour should be similar like Alarm clocks, calls etc.
Here is my code:
FirebaseMessagingService:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Intent dialogIntent = new Intent(getBaseContext(), AlarmActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
dialogIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
getApplication().startActivity(dialogIntent);
}
Alarm Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set flags so an activity fire on the screen
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
);
setContentView(R.layout.activity_alarm);
.
.
}
I wanted to use SCREEN_BRIGHT_WAKE_LOCK before I launch an activity, but it's deprecated.
I am using in my activity this code:
#Override
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setShowWhenLocked(true);
setTurnScreenOn(true);
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
keyguardManager.requestDismissKeyguard(this, null);
}
} else {
//noinspection deprecation
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
);
}
}
.....
}
To prevent different behavior on different devices I use in my activity layout this:
<android.support.design.widget.CoordinatorLayout
....
android:keepScreenOn="true"
>

Android: Wake up screen from a service

I am working on an android app that listens to the surrounding voices, and executes commands.
One of the commands is waking up the screen.
In order to achieve that goal, I am using the following function, inside my service:
private void wakeupScreen() {
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock fullWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Loneworker - FULL WAKE LOCK");
fullWakeLock.acquire(); // turn on
try {
Thread.sleep(10000); // turn on duration
} catch (InterruptedException e) {
e.printStackTrace();
}
fullWakeLock.release();
} catch (Exception e) {
return e;
}
return null;
}
}.execute();
}
However, I have several problems with this code: (it runs on a service)
Using SCREEN_BRIGHT_WAKE_LOCK and FULL_WAKE_LOCK is deprecated.
The use of AsyncTask and sleep seems like a bad solution for turning the screen on, in non-blocking way.
I wonder if more elegant way exists. Any suggestions?
Apparently, there is no elegant way to achieve that goal.
I will summarize my 3 non-elegant solutions to that problem, for future readers:
Use wakelocks in asynchronously way:
private void wakeupScreen() {
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock fullWakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Loneworker - FULL WAKE LOCK");
fullWakeLock.acquire(); // turn on
try {
Thread.sleep(10000); // turn on duration
} catch (InterruptedException e) {
e.printStackTrace();
}
fullWakeLock.release();
} catch (Exception e) {
return e;
}
return null;
}
}.execute();
}
Launch an activity that turns the screen on.
Simulate HOME button click. (similar to solution 2, without the need to create a custom activity, and slightly different behavior)
I found the first solution as the best for my needs.
Launch an activity, just to get the screen on under onCreate().
See the discussions at what is the proper, non-deprecated way to wake up the device?

Android turn on the screen

I making the application where an activity launch is scheduled by AlarmManager. I would like to appear even if the screen is turned off and device is locked.
To achive this a set the Window flags
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
And try to obtain lock for the screen
if(_lock == null)
{
PowerManager pm = (PowerManager)App.getAppContext()
.getSystemService(Context.POWER_SERVICE);
_lock = pm.newWakeLock(
PowerManager.FULL_WAKE_LOCK, "ScreenOn");
_lock.acquire();
}
The _lock is PowerManager.WakeLock which is released in onPause
protected void onPause()
{
if(_lock != null)
{
_lock.release();
}
}
This code is executed in onCreate and onRestart. Everything works OK if the activity is not launched yet.
But if it was launched earlier the screen is not turned off.
onRestart is called first
onResume is then called
onPause is called immediately
So the activity is not launched. My question is how to turn on the screen in such situation. (I am using API 15).
I came up with the solution. I created a new activity which will be trying to turn on the screen in the onCreate() and then wait until it is turned on. When the screen is ok it will launch the activity which should be displayed. To make the Android always create this activity
public class TurnOnScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm.isScreenOn()) openActivity();
else {
registerReceiver(mScreenOnReceiver, new IntentFilter(
Intent.ACTION_SCREEN_ON));
reciever_registered = true;
turnScreenOn();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (reciever_registered) {
unregisterReceiver(mScreenOnReceiver);
reciever_registered = false;
}
}
private boolean reciever_registered = false;
private final BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
openActivity();
}
};
private void openActivity() {
Intent intent = new Intent();
// ....
finish();
}
private void turnScreenOn() {
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
}
}
I am still looking for explanations why the screen is not turned on in onRestart.
Have you heard of "The Lighted Green Room"? Check out the code below, it may be what you're looking for.
http://code.google.com/p/ch-bfh-fbi-mobicomp-2011/source/browse/ch_simplix_android_repetitive_service/src/com/androidbook/longrun/LightedGreenRoom.java?spec=svn38&r=37
Just use your code :
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
in onCreate() only and remove all those other Activity-Cycle methods if they are not doing anything else then this.
I don't think you need any more code to use to perform it.

Android: Which events do wakeup a device

I have written an android application and now there is a problem.
If my application is running and I power off my device, then sometimes it just wakes up after about 8 seconds and then the screen is on and it shows my application again.
My question is:
Which events or processing constraints (like handling broadcast intents) do wakeup a device?
Edit: Will an alarm with RCT_WAKEUP turn on the device screen?
Thanks in advance!
The AlarmManager won't actually turn the screen on for you. You can use a wakelock instead.
PowerManager.WakeLock wakelock;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
.........
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "AlarmReceiver");
wakelock.acquire();
}
When you're done with the activity just be sure to release the wakelock:
#Override
protected void onStop() {
super.onStop();
wakelock.release();
}
You also need to add the wake lock permission in your manifest file:
<uses-permission android:name="android.permission.WAKE_LOCK"/>
Alternatively, if you don't want to have to include this extra permission you can use the following code in your activity instead of using a wakelock:
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

Wake Android Device up

Hey i need to wake my sleeping android device up at a certain time.
Any suggestions?
P.S. Wake up: turn display on and maybe unlock phone
To wake up the screen:
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
wakeLock.acquire();
To release the screen lock:
KeyguardManager keyguardManager = (KeyguardManager) getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);
KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
keyguardLock.disableKeyguard();
And the manifest needs to contain:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
For more details about PowerManager, refer to the API documentation: http://developer.android.com/reference/android/os/PowerManager.html
EDIT: this answer is reported as deprecated.
Best is to use some appropriate combination of these window flags:
http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_DISMISS_KEYGUARD
http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_SHOW_WHEN_LOCKED
http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_KEEP_SCREEN_ON
http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_TURN_SCREEN_ON
If you want to run on older versions of the platform that don't support the desired flag(s), you can directly use wake locks and keyguard locks... but that path is fraught with peril.
ONE IMPORTANT NOTE: Your activity must be full screen in order for the above flag combination to work. In my app I tried to use these flags with an activity which is not full screen (Dialog Theme) and it didn't work. After looking at the documentation I found that these flags require the window to be a full screen window.
I found a way and it is not that complex... works on any API version.
You need to use PowerManager.userActivity(l, false) method and register your activity as broadcast received for SCREEN_OFF intent:
In your actiivity OnCreate put something like:
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "Screen OFF onReceive()");
screenOFFHandler.sendEmptyMessageDelayed(0, 2000L);
}
};
It will kick off the handler after 2 seconds of Screen Off event.
Register receiver in your onResume() method:
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(mReceiver, filter);
Log.i(TAG, "broadcast receiver registered!");
Create a handler like the one below:
private Handler screenOFFHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// do something
// wake up phone
Log.i(TAG, "ake up the phone and disable keyguard");
PowerManager powerManager = (PowerManager) YourActivityName.this
.getSystemService(Context.POWER_SERVICE);
long l = SystemClock.uptimeMillis();
powerManager.userActivity(l, false);//false will bring the screen back as bright as it was, true - will dim it
}
};
Request permission in your manifest file:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Do not forget to unregister broadcast receiver when you are done. You may do that in onDestroy() for example (which is not guaranteed)
unregisterReceiver(mReceiver);
Log.i(TAG, "broadcast UNregistred!");
On newer devices you should use something like this, since the mentioned Flags are deprecated.
class AlarmActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_alarm)
// Keep screen always on, unless the user interacts (wakes the mess up...)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
setTurnScreenOn(true)
setShowWhenLocked(true)
(getSystemService(KeyguardManager::class.java) as KeyguardManager).requestDismissKeyguard(this,
object: KeyguardManager.KeyguardDismissCallback(){
override fun onDismissCancelled() {
Log.d("Keyguard", "Cancelled")
}
override fun onDismissError() {
Log.d("Keyguard", "Error")
}
override fun onDismissSucceeded() {
Log.d("Keyguard", "Success")
}
}
)
}
}
KeyguardManager.requestDismissKeyguard only wakes up the device, if the setter setTurnScreenOn(true) was called before.
I tested this on my Android Pie device.
Try with the below code after setContentView(R.layout.YOUR_LAYOUT); in activity onCreate() method
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
Log.d(TAG, "onCreate: set window flags for API level > 27");
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
KeyguardManager keyguardManager = (KeyguardManager) getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);
setShowWhenLocked(true);
setTurnScreenOn(true);
} else {
Log.d(TAG, "onCreate: onCreate:set window flags for API level < 27");
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
If you are showing a window when waking up, you can get it working easily by adding few flags to your activity, without using a wake lock.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
Settling an alarm programatically will wake up the phone(play a sound) and i guess the turn on display would be an option there.
I donot think there would be an exposed API that will unlock the phone automatically.
getWindow().addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD);
will dismiss the general keyguard and cause the device to unlock.

Categories

Resources