I want to reboot device on particular time so i am using alarm manager for that.below is the code of my activity.
public class MainActivity extends AppCompatActivity {
private static int timeHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
private static int timeMinute = Calendar.getInstance().get(Calendar.MINUTE);
AlarmManager alarmManager;
private PendingIntent pendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 02);
alarmManager.cancel(pendingIntent);
// if(Calendar.getInstance().after(calendar)){
// // Move to tomorrow
// calendar.add(Calendar.DATE, 1);
// }
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntent);
//
// alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
// SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
// AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
and this is my receiver
public class AlarmReceiver extends BroadcastReceiver {
public static void rebootDevice() {
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("reboot \n");
} catch (Throwable t) {
t.printStackTrace();
}
}
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Triggered", Toast.LENGTH_SHORT).show();
Log.d("Gajanand", "onReceive: Triggered");
rebootDevice();
}
}
Yes code is working fine but not on the exact date.for example if i run the same code now. alarm not triggers if i change the date it triggers. i am not getting what is the problem with code and there is 10 seconds delay in triggering alarm. any help
There are two problems with your code:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 02);
Here you're setting HOUR_OF_DAY and MINUTE but the SECOND field still has its initial value, so the alarm won't be triggered exactly on the minute
(unless you called calendar.setTimeInMillis(System.currentTimeMillis()) exactly on the minute, which is quite unlikely).
Should be something like this:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 2);
calendar.set(Calendar.SECOND, 0); // setting seconds to 0
setRepeating() is inexact and doesn't work with Doze.
For exact trigger times you should use exact alarms, check this answer for an example.
This is from the documentation
Note: as of API 19, all repeating alarms are inexact. If your
application needs precise delivery times then it must use one-time
exact alarms, rescheduling each time as described above. Legacy applications
whose {#code targetSdkVersion} is earlier than API 19 will continue to have all
of their alarms, including repeating alarms, treated as exact.
Repeating alarms are always inexact so that they wont consume much battery. They may be fired a bit later than the expected time. If you want your alarm to exact, don't make it repeating. Set it again once you receive the alarm
Related
I have an AlarmManager that I call at the end of every day, ie 23.59PM, to do some stuff for the new day. (Its called, NewDayReceiver.class.) It repeats every day.
I also set a broadcast receiver that will run the alarm on reboot. It all works fine.
However, if the phone is off at the end of the day, the alarm for that day is not called. When the phone is turned back on, on boot the alarm is set again, however its set for the end of the new day. It comes out, that the alarm for that day was never called. For example, if its off Sunday night, on Monday morning the phone is turned on but the alarm hasn't been called. It will only be called Monday night?
How can I do it, that on the boot broadcast receiver, I can check if the alarm was called for that day, and if it wasn't set the alarm to go off right away.
I hope its clear.
Here is my alarm for every day.
Intent intent = new Intent(this, NewDayReceiver.class);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
if(!calendar.before(Calendar.getInstance())) {
// Repeat every 24 hours
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24*60*60*1000, pendingIntent);
Log.d(TAG, "New day alarm set for:" + calendar.getTime() + " and will repeat every day");
}
Here is my BroadcastReceiver, that I call on boot:
public class BootBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "999.BootBroadcastReceiver";
#Override
public void onReceive(Context pContext, Intent intent) {
newDayAlarm(pContext);
newWeekAlarm(pContext);
}
private void newWeekAlarm(Context context) {
Intent intent = new Intent(context, NewWeekReceiver.class);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 55, intent, 0);
// real for end of week
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
if(!calendar.before(Calendar.getInstance())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Log.d(TAG, "New week alarm set for:" + calendar.getTime());
}
}
}
I have an alarm in my app:
public class MainActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.curentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(MINUTE, 11);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = Pending.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntente);
}
}
This is my AlarmReceiver.class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println("ALARM: " + sdf.format(new Date()));
}
}
And in my AndroidManifest.xml I have this line
<receiver android:name=".main.AlarmReceiver" />
The issue is that the alarm does not alarm for the time I set. I set the alarm for
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(MINUTE, 5);
Then the alarm alarmed at 11:11:29. Then I set the alarm for
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(MINUTE, 20);
Then the alarm alarmed at 11:26:29. Then I set the alarm for
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(MINUTE, 29);
Then the alarm alarmed at 11:41:29.
It continued this way all morning. However, if I replace this line
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntente);
with this line
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, (SystemClock.elapsedRealtime()+10000), pendingIntent);
Then the alarm alarms perfectly in the appropriate 10 seconds.
What is going on?
As per the documentation, setInexactRepeating is not accurate by design. In order to reduce the battery drain by waking up the device too many times, it internally tries to fire several alarms at the same time resulting in inexact alarm time for some of the clients.
https://developer.android.com/reference/android/app/AlarmManager.html#setInexactRepeating(int,%20long,%20long,%20android.app.PendingIntent)
I have started alarm of 9:00 AM in android on Boot Completed. But fires alarm every minute after it has completed boot.
My Requirement is it should set Alarm after boot but only fires alarm at 9:00 AM.
Here is my code:
public class AlarmUtil {
private PendingIntent alarmIntent;
public static void setAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
calendar.set(Calendar.AM_PM, Calendar.AM);
//calendar.setTimeInMillis(calendar.getTimeInMillis());
calendar.add(Calendar.SECOND, 1);
Intent intent = new Intent(context, Services.class);
PendingIntent pintent = PendingIntent.getService(context, 123456789,
intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1 * 60 * 1000, pintent);
}
}
public class AlarmBroadcastReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Toast.makeText(context, "Booted!", Toast.LENGTH_SHORT).show();
AlarmUtil.setAlarm(context);
}
}
}
services (My service Class)
public class Services extends IntentService {
public Services(String name) {
super("services");
// TODO Auto-generated constructor stub
}
public Services() {
super("services");
// TODO Auto-generated constructor stub
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyApp.counter += 1;
Toast.makeText(getApplicationContext(),
"Service started: " + MyApp.counter, Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
protected void onHandleIntent(Intent intent) {
Toast.makeText(getApplicationContext(), "handling intent",
Toast.LENGTH_LONG).show();
}
}
where i am lacking. Please help me. Thanks in advance.
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1 * 60 * 1000, pintent);
By calling setRepeating(), you are instructing it to fire the intent on every minute. You probably meant to use set() or setExact() instead.
Additionally, you're setting the alarm for 9:00 on the current date. I'm not exactly sure what your objective is but if you want an alarm for the "next 9:00" (i.e. as an alarm clock) you should probably add a day if the current time is greater than 9:00. From the documentation:
If the stated trigger time is in the past, the alarm will be triggered
immediately.
EDIT: If what you need is to fire this alarm every day at 9:00, then setRepeating() is correct, but the time in milliseconds should be AlarmManager.INTERVAL_DAY. Be mindful of the note about past alarms, though. If you boot your phone, say, at 10:00 AM, and you use your current code, you will get an immediate alarm in addition to the future ones.
And, as #DerGolem pointed out, if you target API level 19 then these alarms will be inexact (and there is no setRepeatingExact()). If you need exact alarms, then you will have to schedule one with setExact(), then the next one when that one fires, and so on.
Hi I have used following code and able to generate alarm at 9 Am each day
alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmService.class);
PendingIntent pintent = PendingIntent.getService(this, 123456789,
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, 9);
calendar.set(Calendar.MINUTE, 00);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1000 * 60 * 1 * 60 * 24, pintent);
you need to replace "1 * 60 * 1000" with AlarmManager.INTERVAL_DAY to set it daily
I've created Service UploadData which triggers on Start Sync event. Added coded in there to schedule Service which runs at 9:00 pm daliy with 1 Hour Interval which runs perfectly fine.
ServiceAlarm.startServiceAlarm();
Code snippet:
public class ServiceAlarm {
public static AlarmManager alarmMgr;
public static PendingIntent alarmIntent;
static Context context;
public static void startServiceAlarm()
{
context = MyApplication.getApplication();
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(SmartConsultant.getApplication(), UploadData.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
// Set the alarm to start at 9:00 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 21);
calendar.set(Calendar.MINUTE, 00);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_HOUR, alarmIntent);
Log.i("Service", "Service Started!");
}
public static void stopServiceAlarm()
{
alarmMgr.cancel(alarmIntent);
}
}
But I want these Service to shutdown after 12:00 am [It must run only thrice in a day between 9:00 pm to 12:00 am].
How One can stop the same service at 12:00 am?
I don't think there is a specific method to schedule a stop time. I would say for your specific case the best bet would be to change the setup of your service calls. Have the alarm manager fire at 9. Then when you receive that alarm check the time and if one hour is still before midnight fire another alarm.
I am following Android developers documentation and some other tuts to create an Alarm manager which fires and wakes up the CPU at 4pm everyday, following is my code:
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
BroadcastReceiver br;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 16);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
}
public void setup() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent i) {
Toast.makeText(c, "Rise and Shine!", Toast.LENGTH_LONG).show();
//Invoke the service here Put the wake lock and initiate bind service
}
};
registerReceiver(br, new IntentFilter("com.testrtc") );
alarmIntent = PendingIntent.getBroadcast( this, 0, new Intent("com.testrtc"),
0 );
alarmMgr = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
}
}
Manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
However I dont get any errors, but the alarm (Toast message) wont fire.
EDIT from the developer docs:
RTC examples
Here are some examples of using RTC_WAKEUP.
Wake up the device to fire the alarm at approximately 2:00 p.m., and repeat once a day at the same time:
// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
This one for set Repeating, says that if I want my alarm to fire at 8:30 and then repeat after each 20 minutes, however I just want to fire my alarm at a specific time but I dont want to repeat it.
Wake up the device to fire the alarm at precisely 8:30 a.m., and every 20 minutes thereafter:
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);
Decide how precise your alarm needs to be
Choosing the alarm type is often the first step in creating an alarm. A further distinction is how precise you need your alarm to be. For most apps, setInexactRepeating() is the right choice. When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. This reduces the drain on the battery.
For the rare app that has rigid time requirements like yours, the alarm needs to fire precisely at 4:00 p.m. everyday then use setRepeating().
Reference: Decide how precise your alarm needs to be
Solution :
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
// Set the alarm to start at approximately 4:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 16);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000*60*60*24, alarmIntent);
Edited Testing : (Fire alarm at every 10seconds)
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime(),
1000*10, alarmIntent);
Conclusion :
setup() method was not called before dealing with alarms.
Update for API 19+
setRepeating is inexact when targeting api level 19 or higher. For exact repating you can now use setExact() and manage repeating yourself.
reference: AlarmManager documentation
Instead of using setInexactRepeating() I suggest you to use setRepeating()
from the docs,
setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour.
setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)
Schedule a repeating alarm.
Documentation is quite clear:
public void setInexactRepeating (...)
triggerAtMillis time in milliseconds that the alarm should first go
off, using the appropriate clock (depending on the alarm type). This
is inexact: the alarm will not fire before this time, but there may be
a delay of almost an entire alarm interval before the first invocation
of the alarm.
so to my understanding but there may be a delay of almost an entire alarm interval means you may have one day delay, because u use AlarmManager.INTERVAL_DAY.
set minutes and seconds also to calendar ..
calendar.set(Calendar.HOUR, 16); // At the hour you wanna fire
calendar.set(Calendar.MINUTE, 0); // Particular minute
calendar.set(Calendar.SECOND, 0);
and use
alarmManager.setRepeating(AlarmManager.RTC,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY,
alarmIntent);
I had your same problem (usually is an Huawei issue) and I resolved by enabling the app in the PowerManager or Protected Apps.
Try to create a receiver that extends WakefulBroadcastReceiver:
public class MyReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myService = new Intent(context, MyService.class);
context.startService(myService);
}
}
In your service, you can put your toast, or try to write a log in a file to be sure that it works. Then, in your activity:
Intent myAlarm = new Intent(context.getApplicationContext(), MyReceiver.class);
PendingIntent recurringAlarm = PendingIntent.getBroadcast(context.getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), 4 * 1000 * 60, recurringAlarm);
// Alarm every 4 minutes