AlarmManager awakes Activity from Sleep but the Activity Closes Undesirably - android

I have an AlarmManager setting an alarm:
Intent intent = new Intent(mContext, AwakeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, PENDING_INTENT_ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(mContext.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + futureTime, pendingIntent);
and the alarm works as expected. When the alarm goes off I have AwakeActivity open. This also works as expected. In AwakeActivity I have:
#Override
public void onCreate(Bundle savedInstanceState)
{
// main
super.onCreate(savedInstanceState);
// inflate
setContentView(R.layout.awake);
Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); //relates to IInputConnectionWrapper issue - but not cause of instant close of app
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
Here is my Manifest definition:
<activity
android:name=".AwakeActivity"
android:label="#string/activityAwake"
android:configChanges="keyboardHidden|orientation"
android:theme="#android:style/Theme.NoTitleBar"
android:screenOrientation="portrait"
android:launchMode="singleInstance"
android:noHistory="true"
>
</activity>
The issue I'm having is that when AwakeActivity starts up it doesn't stay open. It instantly closes. But... this only happens if the phone is in sleep mode, if I leave the screen on and AwakeActivity opens via the alarm - all is well.
The other but... is that this happens on my Droid X running 2.3.4 and not my Galaxy Nexus 4.2.2. I've been at this for a while and feel as though I've done things properly.
What am I missing here? Any ideas?

I myself was running into a similar issue. On some devices the device would wake up and on others the activity would close. Have you tried using a WakeLock to see if the same thing happens?
So declare a global wakelock variable:
PowerManager.WakeLock wakelock;
In your onCreate method do something like:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE, "tag");
wakelock.acquire();
Now you just have to release the wakelock, say in your onPause method:
#Override
protected void onPause() {
super.onPause();
wakelock.release();
}
Also you need to include this in your manifest file:
<uses-permission android:name="android.permission.WAKE_LOCK"/>

Related

How To Show Activity On Lock Screen When Password Is Set In Android

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)

PowerManager does not trigger when Activity is started by the AlarmManager

I'm an artist and I'm working on an installation with a couple Android smartphones. I'm not an expert in Java/Android programming. I'm just learning by doing and stackoverflow is very helpful. I'm using different devices with different Android versions (2.3-4.4). The devices are constantly powered via usb. The app should run only during opening hours of an exhibition and resort automatically the next day. For scheduling I'm using the AlarmManager. Currently I have problems with the automatic restart on some of the devices, on others it work as expected.
Here are some snippets important form the scheduling:
In the AndroidManifest.xml I have the following permissions set:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Among others the WAKE_LOCK permission is set.
onCreate starts with:
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (android.os.Build.VERSION.SDK_INT > 12) {
if (pm != null) {
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK| PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
}
}else {
// unlock screen and switch screen back light on
// for Android 2.3 - disable for higher Versions
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
final KeyguardManager.KeyguardLock kl;
if (km != null) {
kl = km.newKeyguardLock("MyKeyguardLock");
kl.disableKeyguard();
}
if (pm != null) {
wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK| PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
}
}
wakeLock.acquire();
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this));
PowerManager.ACQUIRE_CAUSES_WAKEUP is used, which to my understanding should put the screen on irrespectively of it's state.
In onDestroy I'm using:
PendingIntent pendingIntent = PendingIntent.getActivity(MyApplication.getInstance().getBaseContext(),0,intent,PendingIntent.FLAG_ONE_SHOT );
AlarmManager alarmManager = (AlarmManager) MyApplication.getInstance().getBaseContext().getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.set(AlarmManager.RTC_WAKEUP , System.currentTimeMillis()+delayInMillis,pendingIntent);
Date date = new Date(System.currentTimeMillis()+delayInMillis);
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy ' 'HH:mm:ss.SSS");
Log.i("** restart at **",dateFormat.format(date));
}
This snippet is executed when finish() is called because of 'exhibition closing time reached'. As said, this works on most of the devices. On those devices, on which the app seems not to restart automatically, the app starts as soon as the screen is put on e.g. by pressing the power button or disconnecting usb (e.g. for connecting the laptop to read the logcat.) In the logcat I find something like (LG P-875 Android 4.1.3 should start at 14:00:xx)
03-25 14:00:53.516 677-748/? I/ActivityManager: START {flg=0x14000004 cmp=eu.karin_daum.daum.reality/.Start (has extras) u=0} from pid -1
03-25 14:00:53.546 677-748/? I/ActivityManager: Start proc eu.karin_daum.daum.reality for activity eu.karin_daum.daum.reality/.Start: pid=31324 uid=10099 gids={3003, 1015, 1028}
To me, this looks o.k., however the PowerManager did not react. In this example, the PowerManager reacted at the moment when I disconnected usb to connect my laptop some minutes later:
03-25 14:04:13.986 677-691/? D/PowerManagerService: userActivity mLastEventTime=201702573 time=201861160 mUserActivityAllowed=true mUserState=0x0 mWakeLockState=0x0 mProximitySensorActive=false timeoutOverride=-1 force=false
03-25 14:04:13.986 677-691/? D/PowerManagerService: setPowerState: mPowerState=0x0 newState=0x7 noChangeLights=false reason=2
03-25 14:04:13.986 677-691/? D/PowerManagerService: setPowerState: mPowerState=0 newState=7 noChangeLights=false
03-25 14:04:13.996 677-691/? D/PowerManagerService: setTimeoutLocked now=201861160 timeoutOverride=-1 nextState=3 when=201862660
03-25 14:04:14.006 677-747/? D/PowerManagerService: Perflock acquired: 7, 1
03-25 14:04:14.006 677-750/? D/PowerManagerService: offMask=0x0 dimMask=0x0 onMask=0x0 difference=0x1 realDifference=0x0 forceState=0x1
03-25 14:04:14.096 677-1038/? D/PowerManagerService: pid=31324 tag=MyWakeLock mAcquireCausesWakeupTime=201861278 diffTime=149932030
03-25 14:04:14.096 677-1038/? D/PowerManagerService: setPowerState: mPowerState=0x7 newState=0x7 noChangeLights=false reason=3
In the second but last line the request which I send in onCreate seems to be treated (tag=MyWakeLock)
During writing I just realise that the PowerManager did react automatically in the next test but only with a delay of about 10 minutes w.r.t. the AlarmManager action.
What am I doing wrong? Do I have to release the WakeLock in onDestroy? Is there a solution to the problem?
Problem solved. There have been two reasons why it was not working as I expected on all devices:
I was following the proposal made in several threads using PendingIntent.getActivity to start the activity directly instead of using a BroadcastReceiver instead. Apparently doing so would not guarantee to get control on the screen. After reading again the information on the Android Developer pages I implemented a BroadcastReceiver:
public class StartupReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent!=null){
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl;
if (android.os.Build.VERSION.SDK_INT < 13) {
wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "**StartupReceiver**");
KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
final KeyguardManager.KeyguardLock kl;
if (km != null) {
kl = km.newKeyguardLock("MyKeyguardLock");
kl.disableKeyguard();
}
} else {wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "**StartupReceiver**");
}
wl.acquire();
Intent i = new Intent(context, Start.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
wl.release();
}
}}
This works correctly on all devices with SDK<19
In order to get it also working on SDK=19 I had to change alarmManager.set to alarmManager.setExact, i.e.
Intent intent1 = new Intent(this,StartupReceiver.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(MyApplication.getInstance().getBaseContext(),0,intent1,PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) MyApplication.getInstance().getBaseContext().getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
if(android.os.Build.VERSION.SDK_INT<19) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayInMillis, pendingIntent1);
}else{
alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayInMillis, pendingIntent1);
}
Date date = new Date(System.currentTimeMillis()+delayInMillis);
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy ' 'HH:mm:ss.SSS");
Log.i("** restart at **",dateFormat.format(date));
}
These changes solved the problem

Android: Overriding the power button in a Fragment

I'm working on a thing where I need to override the power button in a Fragment when pressed. I did this successfully, however, the screen turns off when the power button is pressed.
I did a quick search and came across a few posts like this, this, and this. Some say it's doable and others say it's not. My question is that is this even doable? If so, any idea how to go about this?
You can use this to prevent screen from locking
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
While using in fragment
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
Use a BroadcastReceiver and listen for the android.intent.action.SCREEN_OFF or Intent.ACTION_SCREEN_OFF which is sent when power button is pressed (and screen is on). What i think is that overriding the power button is not possible , because of security issues.
What you are doing is not advisable. However you can write a broadcast receiver and then the screen gets locked, wake it up using AlarmManager. Below is the code.
#Override
public void onReceive(Context context, Intent intent) {
if ((intent.getAction().equals(Intent.ACTION_SCREEN_OFF))) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "TEST");
wakeLock.acquire();
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent inten = new Intent(context,NewActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 0, inten, 0);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 100, pi);
}
}
// Finish your WakeLock HERE. call this method after U put the activity in front or when u exit from the new activity.
public void finishWakeLocker(){
if (wakeLock != null)
wakeLock.release();
}
You cannot override the power button functionality however you can prevent system from showing dialog on long press of a power button using following.
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(!hasFocus) {
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
}
}

Android power button override and disable while application runing

hi i need to keep the device screen on mood, while application running.
disable the power button functionality to off the screen.
I have tried following codes
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
and wake locks
#Override
public void onReceive(Context context, Intent intent) {
if ((intent.getAction().equals(Intent.ACTION_SCREEN_OFF))) {
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "TEST");
wakeLock.acquire();
AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent inten = new Intent(context,NewActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 0, inten, 0);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 100, pi);
}
}
// Finish your WakeLock HERE. call this method after U put the activity in front or when u exit from the new activity.
public void finishWakeLocker(){
if (wakeLock != null)
wakeLock.release();
}
Thanks in advance
This is not possible, for security reasons. HOME and POWER buttons are two things you will not be able to directly override without system-grade permissions. After all, the user wouldn't like your app to take control of their device, would they? ;-)
You should plan the functionality in such a way that a wakelock or
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
is enough :-)
EDIT:
There are tutorials such as the one uday linked, but the effects are generally unreliable and work only on some devices. I have developed an app like that and trust me, you do not want to have to debug this ;-)

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);

Categories

Resources