I have an android app where I am trying to play videos based on the server's clock time(not the android device's clock time which might be different)
08:00:00 - 08:04:59 -> video_url_1
08:05:00 - 08:09:59 -> video_url_2
08:10:00 - 08:14:59 -> video_url_3
So when the user opens the app,if the server's clock time falls in the above category,then the respective videos are played,otherwise a timer for remaining seconds is shown based on the server's clock time.
If the android app is already open,then it should automatically start playing video when the server's clock time falls in any of the above categories.
Continuously pinging the server for its clock time is not a good option.So how can we achieve the above functionality?
I think Alarm Manager is your solution.
The flow would be the following:
Android app opens and request the server what the server time is and when is the next video.
Calculate how in how many minute or seconds the time will be done.
Setup an alarm in the device for that time. Let's say the server time is 8:45 and the next video is at 9:30. So you know 45 minutes has to pass in order to be able to play the video. So the alarm should be trigger in 45 minutes.
When the alarm is trigger, check the server again and if it's fine, play the video and schedule your next alarm (for the next video or if the server now wants to play the video in another moment), if the user fake his time, then recalculate the time that need to pass and reschedule your alarm.
Set the alarm manager example to trigger a broadcast receiver:
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
Intent alarmIntent = new Intent(context, MyBroadCastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
// add here your calculate minutes or seconds or hours
calendar.add(Calendar.MINUTE, 45);
if (alarmManager != null) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
Then have your broadcast receiver to handle any other action:
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do your magic, could be play the video or show a notification saying the video is ready to play
}
}
If you want more information about the alarms in Android, take a look at this link:
https://developer.android.com/training/scheduling/alarms.html
Related
I'm developing an app which you can schedule your time and It reminds you on time just like google calendar. I use AlarmManager class and set a Repeating task to check Database every one minute and see if there is any alarm on that time or not.
#Override
public void onReceive(Context context, Intent intent) {
Calendar now = Calendar.getInstance();
doRepeatingWorks(now.getTimeInMillis()); // Like Checking if one day passed to do some tasks
checkDbIfThereIsSomeSchedule(now);
}
And I call this to start alarm manager:
public void setAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), G.ALARM_CHECK_INTERVAL_MILIS, pendingIntent);
}
But it's inaccurate and sometimes I figure out that the task killer apps kill my alarm and make it totally worthless.
Although using a foregroundService is battery consuming and it goes on user's nerve with the notification.
Is there any solutions or alternatives for this problem?
I use AlarmManager class and set a Repeating task to check Database every one minute and see if there is any alarm on that time or not
That is a truly awful approach. This sort of behavior is precisely why Doze mode and app standby were added in Android 6.0.
Is there any solutions or alternatives for this problem?"
Schedule an alarm event for first event. When you get control, notify the user about the event, then schedule an alarm event for the next event in sequence. If the user adds a new event that is sooner than your first event, cancel the previous alarm and schedule one for the new first event.
You don't need to check there is an alarm in each 1 min. I hope this post helps you - Scheduled Alarm Manager not working Android
I know there is a lot of discussion about AlarmClock and AlarmManager and how to set alarms, launch apps, etc. However, I am yet to find the perfect answer for the following scenario.
In my Android alarm clock application I'm developing, I want to set an alarm for a specific time, pass in other settings such as what song to play, vibrate, etc.
1) what should I use to do this? AlarmClock or AlarmManager?
2) Now, when the alarm goes off at the specified time, how do I tell it to launch my custom Activity? Again the question of AlarmClock or AlarmManager.
This custom activity would show the time and have buttons saying "Sleep" or "Snooze" which the user can press (pretty much what happens when an alarm in any other alarm clock app goes off). I don't want to launch my alarm app, ONLY that one screen when the alarm goes off. When the user hits a button, I want to close that custom acitvity and for nothing else related to that app to open. I would like it so that the user can go back to doing whatever they were doing.
I think you can do your job with AlarmManager. As you say, if you want to set alarm for a specific time, you should use setRepeating(). If you want to wake up your device when the alarm fires choose RTC_WAKEUP type and if you don't want that RTC type. You define a PendingIntent, whatever you want to do(play sound, light and vibrate), you can do within this activity that attached to this intent. You should design your layout in that(YOUR_ACTIVITY) layout and put buttons to snooze/cancel alarm.
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, YOUR_ACTIVITY.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
Above code set an alarm for 14:00 and interval of one day which means it will be fired everyday 14:00 and run YOUR_ACTIVITY until you cancel it. this is an example in Google Android Documents.
I'm new in android. I struggle with my application approximately 3 weeks. I need sent and receive packets in normal mode and sleep mode. My app must exchange data a 5 seconds. I tried using alarmmanager but on android 5 it's not works. On android 5 an interval changes it on 60 seconds. Such a solution makes the battery wears out quickly. When I use normal asynctask, not IntentService, then it works only when screen is ON and app is visible. When app is hidden or I click power OFF then exchange data stops working. What is the best solutions?
Even RTC_WAKEUP doesn't help most of the times.
Solution that worked for my app when device in deep sleep mode:
Use WakefulBroadcastReceiver combined with AlarmManager.
Service is started by startWakefulService() and when it is finished, it releases the wake lock by calling completeWakefulIntent(intent). So the device will be allowed to go back to sleep.
I'm not adding any code. Search for examples on how to use WakefulBroadcastReceiver with AlarmManager. Even WakefulBroadcastReceiver doc has some template code.
Also reduce the frequency of alarm so you can avoid draining so much battery.
You can use the AlarmManager class to wake up the device at a particular time, then fire off an operation at whatever interval you'd like. Code from the docs found here:
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 20, alarmIntent);
Notice the last line of this block. You can use the method setRepeating() to set whatever interval you'd like.
I try to build a Tamagotchi game with Unity for Android. The Tamagotchi has a food attribute that should go down even when the Game is closed.
So my approach would be build a IntentService that holds the variables, increase and decrease them if needed. For Batterie reasons i would use Alarm manager to start the Service only every 10 minutes if the App is closed. If the app is started it would bind the Service so it never closes and i can get the Variables.
Is there a more efficient way to handle this? I dont want my app to battery drain too much.
€:
If the food gets low it should also display a notification.
There is indeed a more efficient way to handle this.
Why don't you just save a timestamp when the user closes the app and calculate the time passed when the user opens the app again?
Then you can calculate the new food attribute you're done.
Edit: If you want to show notifications if the food is low you need the alarm manager.
Here is some example code:
public static void registerAlarm(Context context) {
Intent i = new Intent(context, YOURBROADCASTRECIEVER.class);
PendingIntent sender = PendingIntent.getBroadcast(context,REQUEST_CODE, i, 0);
// We want the alarm to go off 3 seconds from now.
long startTime = SystemClock.elapsedRealtime();
startTime += 60000;//start 1 minute after first register.
// Schedule the alarm!
AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, startTime, 900000, sender); // 15min interval
}
You can also calculate when the Tamagotchi will be hungry just before the game is closed and set alarm only to that point to show notification.. unless the game opened again so you clear all notifications.
Here i am going to use the alarm service to play the alarm at every 30 minutes. Right now i have set it to play it at every 10 second from the Every start.
Here is the Code:
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_layout);
Intent myIntent = new Intent(SettingsActivity.this, MyAlarmService.class);
pendingIntent = PendingIntent.getService(SettingsActivity.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10*1000, pendingIntent);
}
Now the Problem is, I want to start the alarm from the 12:30 not from the time application start and it should repeatedly play at evert 30 minutes. like 1:00, 1:30, 2:00 . . . etc
So what changes i have to do in my code ?
To start a service at specific time.
see this post maybe helpful:
Using Alarmmanager to start a service at specific time
Set your initial alarm time for 12:30 using the Set method.
When the alarm fires, then set up your next alarm time and keep doing that until you don't want the alarm any more.
You don't need a service to do such a simple task. AlarmManager is more than capable of handling this.
Try it
And Use first time -
Try another
A naive approach would be:
Start a context that will always run, such as a Thread in a Service.
Calculate the timestamp of the time you want the next alert to ring using Date and put it in "long alertTimestamp".
In a loop, calculate the timestamp right now using Date and put it in "long nowTimestamp" .
If nowTimestamp < alertTimestamp, put the thread to sleep for (alertTimestamp - nowTimestamp).
Else sound the alert and recalculate alertTimestamp, repeat.
Make sure you catch notify interruptions to the tread gracefully, that is the key to aborting the timer.
Hope this was helpful.
For repeating every 30 minutes you will need to add this to your code:
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000*60*30, pendingIntent); //millisecs*seconds*minutes
But I haven't figure out how to start at specific time yet.