I have an app that uses text to speech to inform the user every 10 mins that 10 mins have passed. It currently works fine but if you sleep the phone (press the power button) it no longer plays the sound.
How can i play these sounds even when the phone is asleep?
In general, your code is not running if divice goes to sleep. In order to make your code running you need to acquire WakeLock from PowerManager. But in your case you don't need to have the WakeLock acquired all the time. You need to wake you application every 10 minutes. Otherwise your app will just eat battery doing nothing.
In order to wake your application periodically you need to use a special Android's AlarmManager.
Here is an example:
Intent myIntent = new Intent(getApplicationContext(), YourActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, interval, pendingIntent);
You also may send broadcast which you will process in your Service (if you don't want to use Activity).
EDIT: Playback will not start unless you explicitly create a SCREEN_DIM_WAKE_LOCK. Note that PARTIAL_WAKE_LOCK will not work with playback (don't now why, probably it's a bug).
PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "Music");
wakeLock.acquire();
...start playback...
wakeLock.release();
EDIT: Added project that shows an example of running a playback every 60 seconds (even when screen is off and usb cable is disconnected). It can be found here: http://code.google.com/p/playevery60/
Related
I used Alarm Manager to trigger every 5 seconds and it works fine. But the problem is the phone didn't go into sleep mode and I can't see the gap from the collected data using alarm manager.
Can anyone help me how to check if the phone goes into sleep correctly or not?
here is my code
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
public void startAlarm() {
manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
int interval = 5000;
manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
Toast.makeText(this, "Alarm Set", Toast.LENGTH_SHORT).show();
}
By using AlarmManager you ensure that your app will be waken by the system even if the phone is sleep and your activity/service is in the background.
But this does not mean your app (or any other app) have the ability to force the device into Doze mode.
In order to validate that your app works in Doze as expected use this command to force the device into Doze mode:
$ adb shell dumpsys deviceidle force-idle
Additional Info
this method:
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP...
WILL NOT wakeup the device if it's in Doze mode, only after the device will get out from the Doze mode.
To ensure your app will work in Doze use this command:
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP...
I'm working on location tracking application using FusedLocationProvider. I have a background service which tracks location of phone in every 5 minutes.
All works well with it, but once the phone goes idle then after 3 to 4 hours of time, the background service stops to take location. When user unlocks the phone the tracking start again.
Can someone please guide me what could be causing the issue?
One possibility could be Android M Doze Mode. When the device is unplugged and stationary for a period of time, the system attempts to conserve battery by restricting apps access to CPU-intensive services. Doze mode starts after about 1h of inactivity, periodic tasks etc. are then scheduled to maintenance windows. When the user unlocks the device, doze mode is turned off again.
You find more information about Doze Mode in the developer docs:
http://developer.android.com/training/monitoring-device-state/doze-standby.html
Maybe your service is being stopped because the phone needs to free up memory so it kills your service. Make sure your service is set as a foreground service.
A foreground service is a service that's considered to be something the user is actively aware of and thus not a candidate for the system to kill when low on memory. A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading, which means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground.
http://developer.android.com/guide/components/services.html
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
Android will put your service to sleep after being idle for a while. You can use WakeLock to prevent that from happening.
public int onStartCommand (Intent intent, int flags, int startId)
{
PowerManager mgr = (PowerManager)getSystemService(Context.POWER_SERVICE);
mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
mWakeLock.acquire();
...
return START_STICKY;
}
public void onDestroy(){
...
mWakeLock.release();
}
I am building an Android Alarm Applicaion, and used following code for Main Calling Class:
AlarmManager inst_alarm= (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent =new Intent(MainActivity.this,Alarm.class);
pintent= PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
inst_alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),pintent);
//"cal" is reference of calendar class to get saved time in millisecond.
for Service Class:
public class Alarm extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context c, Intent i) {
Uri uri_alarm= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
if(uri_alarm==null)
{ uri_alarm=RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
}
Ringtone ringtone_alarm=RingtoneManager.getRingtone(c, uri_alarm);
ringtone_alarm.play();
}
}
This code work fine but i have few quesions.
Question: 1) Is it possible to alarm bell on scheduled time if android device is switched off(device get power on automatically to ring bell on saved time) as in default application of android device does.
2) Suppose i saved alarm after 8 minutes exactly and i restart my device then alarm start ringing immediately after boot(Because i have used "bootcomplete" for receiver in manifest) but i want to play alarm after 8 minutes exactly not on reboot.(I have saved alarm in shared-preference but how to use it on reboot)
EDIT: Can I use "Power Manager" class or any other class to handle above mentioned situation ?
1) Is it possible...
No, not from complete power off. You're most likely referring to screen being off and the device in low power state. If the device is turned completely off then alarms cannot wake it. The default Android clock app just wakes it from sleep. If you'd like to wake up the screen and play sound, you'll have to create a Service which can be activated via your WakefulBroadcastReceiver and have it start the appropriate UI. If you do not, then the system can go right back to seep when your onReceive() is done.
2) ...want to play 8 minutes after...
What you're likely seeing is a previous expiration of your Alarm firing and you're waking up the device (not powering it on.) Alarms are not retained across power cycles or reboots. If you wish to have them stick around after a true reboot, then you'd have to manage that yourself. The PowerManager and AlarmManager do not provide such a facility.
For (1), if you're talking about complete shutdowns, it's unfortunately impossible. There is no way to do this without specialized hardware (and its corresponding software interface to your app).
For (2), you can do something clever. For example, persistently store the timestamp whenever the device restarts/turns off (you can register a BroadcastReceiver for ACTION_SHUTDOWN in addition to your BOOT_COMPLETE) when you have a pending alarm bell, and use that information on reboot/boot to resume (or stop, depending on the time difference and the alarm bell's "timer") or otherwise re-sync your pending alarm bell logic.
And for your PowerManager question, again if we're talking about complete shutdowns, unfortunately the answer is no.
PowerManager is used to mainly prevent the device from going into deep sleep. Remember, Android devices turn off their CPU's some time after they are locked, preventing your app from doing calculations/processes. This is essentially what the notion of "wakelocks" is about.
I've set a repeating alarm that I only want going off when the device is awake. When it's asleep, I want it to stop (and come back on when the device wakes up). However, it's currently going off no matter what. Here's how I register my alarm:
Intent updateIntent = new Intent(UPDATE_INTENT);
AlarmManager alarmService = (AlarmManager) context.getSystemService(
Context.ALARM_SERVICE);
PendingIntent updatePendingIntent = PendingIntent.getBroadcast(context, 0,
updateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmService.setInexactRepeating(AlarmManager.RTC, Calendar.getInstance().getTimeInMillis(), UPDATE_INTERVAL, updatePendingIntent);
The alarm manager docs say that RTC will not wake up the device. The docs specify exactly the behavior that I want:
Alarm time in System.currentTimeMillis() (wall clock time in UTC). This alarm does not wake the device up; if it goes off while the device is asleep, it will not be delivered until the next time the device wakes up.
When I press the lock button on the device, I clearly see the going to sleep message from PowerManager in logcat:
I/PowerManagerService(488): Going to sleep by user request...
And then my alarm goes off anyway. What's going on here?
Ironically, every other question I've found on SO deals with alarms NOT going off while the device is asleep. I wish I had their problem!!
However, it's currently going off no matter what.
Presumably something else is holding a partial WakeLock, and the device is not actually asleep, even though the screen may be off. Use adb shell dumpsys power to try to track it down (look for the "Wake Locks" section).
I eventually decided to register broadcast receivers to listen for SCREEN_ON, and SCREEN_OFF, and toggle the alarm appropriately. I realize this might not be super elegant, but at least it always works even if another app is holding a wake lock.
Listening for screen on and off: android: broadcast receiver for screen on and screen off
Turning off an alarm: How to stop an alarm in android
In my app, I set an alarm
AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
...
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
...
alarmMgr.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pendingIntent);
It works fine unless I turn off and turn on the phone.
To be more specific, let's say at 10:20, I set an alarm to 10:22 and I turn off and turn on the phone at 10:21, alarm won't work.
What might be the problem? Is that a broadcast issue of the pendingIntent there or should I set some flags of the alarmManager object for it to work in such conditions?
The documentation about the AlarmManager says that :
Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted.
It seems that the AlarmClock included by default by Android does work even after a reboot.
On way to keep your alarms working after a reboot, is to start your application on boot completed and set up all the alams again with the AlarmManager.
(In fact you may want to just setup your alarms using a Broadcast, not start your app)
Here is a StackOverflow question dealing about lunching an app on startup.
You wan also check out how the default AlarmClock does this by reading from the source.
You can read and download it from here