I have an activity that might by launched when screen is locked. I use this code to make it work:
if (powerManager != null) {
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP, "App:wakeuptag");
wakeLock.acquire(1000 * 60);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
setTurnScreenOn(true);
} else {
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);
}
And so far, it works only if application was in foreground before user locked the screen. If application was in bacgkround state before screen was locked, then this code won't work.
Edit: I found out it's not because app is being in background, it's because the app was closed by pressing HOME button, if I close app with back button everything works fine. So, this is somehow relevant with HOME button.
Related
My app never goes to sleep while power is connected and if power is removed then the tablet goes into sleep. After powercable is reinserted the app is getting launched automatically when power is connected (Battery is charging).
To achive this I have implemented a BroadcastReceiver and within this Receiver I (re-) launch my app with:
if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
// Start the MainActivity
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
context.startActivity(i);
}
In the MainActivity I use (in onCreate()):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
setTurnScreenOn(true);
}
else{
}
if( something...) {
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
}
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Object o = this.getSystemService(Context.KEYGUARD_SERVICE);
if (o != null) {
KeyguardManager keyguardManager = (KeyguardManager) o;
keyguardManager.requestDismissKeyguard(this, null);
}
}
else {
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
This works fine as long as the app is not screen-pinned. If the app is screen-pinned then this works only once. I assume because the app gets launched from screen-pinned context ?? Any further plugging of the powercable launches the app but is getting overlayed by a battery charge % window which dissapears after ca. 5 seconds and then the tablet goes into sleep. Is there a difference in this context when the app is screen-pinned ?
I am trying to show an activity when the screen is locked. I am running a service in the background, when an event occurs, I want to open an activity even if the app is locked(Similar to alarm app, which wakes up the screen and displays its activity). I have followed the following steps,
When OnReceive() is called, I want to open the activity on the lock screen.
public void OnReceive() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "myalarmapp:alarm.");
wl.acquire(5000);
Intent startAlarmActivity = new Intent(MainScreen.this, AcceptScreen.class);
startActivity(startAlarmActivity);
wl.release();
}
Added below code in the activity's onCreate method which I want to show,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
setTurnScreenOn(true);
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);
}
else {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
Added this in manifest for the activity which I want to show,
<activity
android:name=".v2.ui.orderaccept.AcceptScreen"
android:exported="true"
android:label="#string/title_activity_accept_screen"
android:theme="#style/AppTheme.NoActionBar"
android:showOnLockScreen="true"
android:screenOrientation="sensorPortrait"/>
It is working as expected when the phone does not have a lock screen password. But it does not work when there is a password for the lock screen.
Finally, I got the solution.
add below code in the activity's onCreate method which you want to show on the lock screen,
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
Manifest,
<activity
android:name=".v2.ui.orderaccept.AcceptScreen"
android:exported="true"
android:label="#string/title_activity_accept_screen"
android:theme="#style/AppTheme.NoActionBar"
android:launchMode="singleInstance"/>
Call the activity,
val intent = Intent(context, targetclass)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
I have the following code which brings my Android app to foreground once I receive a Firebase Push notification or FCM.
#ReactMethod
public void backToForeground() {
Context context = getAppContext();
String packageName = context.getApplicationContext().getPackageName();
Intent focusIntent = context.getPackageManager().getLaunchIntentForPackage(packageName).cloneFilter();
Activity activity = getCurrentActivity();
boolean isOpened = activity != null;
if (isOpened) {
focusIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
activity.startActivity(focusIntent);
} else {
// Custom flag to check whether app was started from this method
focusIntent.putExtra("FLAG_ON_CALL_BRING_TO_FRONT", "true");
focusIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK +
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED +
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD +
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
getReactApplicationContext().startActivity(focusIntent);
}
}
Now in MainActivity I have used the bundle as following:
#Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.show(this);
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
if (extras != null) {
// Custom flag defined in AppStateManagerModule
String extraString = extras.getString("FLAG_ON_CALL_BRING_TO_FRONT");
if (extraString != null) {
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
);
}
}
}
My code is working correctly in the following cases:
When FCM is received on device:
If app is open, action is performed
If app is in background i.e minimized, app opens and action is performed
If app is killed, app opens and action is performed
If app is killed and phone is locked, app opens on top of lock screen and then action is performed
Now here's the case which doesn't work properly:
If I start my app and its in foreground or if its minimized and I lock my phone, my app is running fine and my code brings it to front, it performs the required operation BUT it doesn't show on top of lock screen.
Action is performed fine in point 5 but it doesnt show on top of lock screen.
If app is active or in background, after phone is locked it will still be considered active. So since an activity is active, it can't be thrown on top with intent since its already used to activate the activity.
We need to add window flags on an active activity to bring it to front like this:
if (isOpened) {
focusIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
activity.startActivity(focusIntent);
// Adding Window Flags to bring app forward on lock screen
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
activity.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
);
}
});
}
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"
>
i start an activity from a BroadcastReceiver, which is triggered by an alaram (RTC_WAKEUP type). in onCreate of that activity i add these flags
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
);
problem is that sometimes (approximately 10% cases) the screen does not turn on. the alarm is correctly triggered (i here the sound of a notification, which is also fired in the receiver's onReceive(). then, if i hit the phone's power button, the screen turns on, showing my activity, and instantly turns off. after that, the power button works good. this happen on android 2.3.7 and here is the onReceive() method
#Override
public void onReceive(Context context, Intent intent) {
m_Context = context;
Bundle extras = intent.getExtras();
final int id = extras.getInt("timer_id");
Intent activityIntent = new Intent(m_Context, MyActivity.class);
activityIntent.putExtra("timer_id", id);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
m_Context.startActivity(activityIntent);
// and now load the alarm sound and play it for the desired time
showFinishedNotification();
}
i would like to avoid using PowerManager, as it needs a permission, and the flags are the prefered way.
what could be a problem? logcat does not show any problems...
From my experience and research on this topic:
The FLAG_TURN_SCREEN_ON can not be used to turn the screen ON and OFF multiple times in your application.
The FLAG_TURN_SCREEN_ON can only be used once to turn the screen ON when creating a new activity (preferably in the onCreate() method) or when re-creating a view.
Now, you can get around this limitation by:
Launching a new activity and setting the flag there, then finishing the activity (by the user or programmatically) to let the screen turn off.
Setting the params.screenBrightness parameters to as "dim" as possible, sometimes the screen "appears OFF". You can then increase the brightness to "turn ON" the screen. However, this often does not work as the screen is still dim but visible, also this doesn't work if the user locks the phone.
Using the Power Manager Wakelock (this still works but Android deprecated this functionality, so they are discouraging the use of this technique). However, as far as I can tell this is the only way I can get my application to turn the screen ON/OFF reliably.
None of these are ideal (in fact they feel like hacks) but just use the one that better suits your application needs.
You can read more here:
Android Alarm Clock Source Code
Android Desk Clock Source Code
Dimming the screen to appear OFF/ON
Using a wakelock to keep the screen ON/OFF
Waking up device and turning screen ON multiple options
I'm a bit late to the party here but I've been fighting this for a while now and finally found a way to get the screen to unlock every time. I add the flags in the onAttachToWindow() event. Typically I do this from a WakefulBroadcastReceiver so the screen transitions smoothly but that's use-case dependent.
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
//Screen On
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);
}
private void clearFlags() {
//Don't forget to clear the flags at some point in time.
getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
problem is that sometimes (approximately 10% cases) the screen does not turn on
If I had to guess, the device is falling back asleep before the activity starts up. Once onReceive() returns, the device can and will fall back asleep, and it will be some time after onReceive() returns before your activity will start.
This same scenario, but replacing startActivity() with startService(), is why I had to write WakefulIntentService, which uses a WakeLock to ensure that the device stays awake long enough for it to do its work, then releases the WakeLock.
Late answer But it will help for anyone.
For higher and lower versions use following code (it working fine)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
setTurnScreenOn(true);
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(this, null);
}
else{
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);
}
setContentView(R.layout.activity_incoming_call);
}
Important Note: you should place before setContentView()
I use these three methods simultaneously which works at almost any device.
public static void turnScreenOnThroughKeyguard(#NonNull Activity activity) {
userPowerManagerWakeup(activity);
useWindowFlags(activity);
useActivityScreenMethods(activity);
}
private static void useActivityScreenMethods(#NonNull Activity activity) {
if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) {
try {
activity.setTurnScreenOn(true);
activity.setShowWhenLocked(true);
} catch (NoSuchMethodError e) {
Log.e(e, "Enable setTurnScreenOn and setShowWhenLocked is not present on device!");
}
}
}
private static void useWindowFlags(#NonNull Activity activity) {
activity.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);
}
private static void userPowerManagerWakeup(#NonNull Activity activity) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
WakeLock wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, tag);
wakeLock.acquire(TimeUnit.SECONDS.toMillis(5));
}
Targeting sdk 30
Following code enables to open Activity from PendingIntent, even if application
was cleared from recent apps
and screen is dimmed
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(view)
turnOnScreen()
}
private fun turnOnScreen() {
window.addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
)
setTurnScreenOn(true)
setShowWhenLocked(true)
val keyguardManager = getSystemService(KEYGUARD_SERVICE) as KeyguardManager
keyguardManager.requestDismissKeyguard(this, null)
}