AlarmManager gets canceled after a while - java

I am writing my first app and I'm trying to fire a notification at a specific time every day that reports some information.
For starter, I created the following class that I use to restart the alarms after a reboot and to start the alarms from the main app (this to have just one piece of code to reuse).
public class SetAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
startReminderService(context);
}
public void checkServiceRunning(Context context) {
Intent reminderIntent = new Intent(context, AlarmReceiver.class);
reminderIntent.setAction("MyReminder");
// I check if a reminder is already active
boolean reminderActive = (PendingIntent.getBroadcast(context, REMINDER_SERVICE,
reminderIntent,
PendingIntent.FLAG_NO_CREATE) != null);
Log.d("test", "The reminder is active?" + reminderActive);
if (!reminderActive) {
startReminderService(context);
}
}
public void startReminderService(Context context) {
Calendar serviceNotificationTime = Calendar.getInstance();
serviceNotificationTime.set(Calendar.HOUR_OF_DAY, 9);
serviceNotificationTime.set(Calendar.MINUTE, 0);
serviceNotificationTime.set(Calendar.SECOND, 0);
Intent reminderIntent = new Intent(context, AlarmReceiver.class);
reminderIntent.setAction("MyReminder");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
REMINDER_SERVICE,
reminderIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager serviceAlarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
serviceAlarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
serviceNotificationTime.getTimeInMillis(),
AlarmManager.INTERVAL_DAY,
pendingIntent);
if (pendingIntent != null) {
Log.d("test", "Background service set up and running.");
} else {
Log.d("test", "Failed to set up background service!");
}
}
}
After that I updated the manifest with the following lines:
<receiver
android:name="com.mycompany.myapp.services.SetAlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name="com.mycompany.myapp.services.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="MyReminder" />
</intent-filter>
</receiver>
So far, everything goes right. When the phone reboots, the reminder is correctly restarted and (if the reminder time is in the past) it fires immediately.
The AlarmReceiver class is the following:
public class AlarmReceiver extends BroadcastReceiver {
private Context ctx;
#Override
public void onReceive(Context context, Intent intent) {
this.ctx = context;
remindStuff();
}
private void remindStuff() {
....
some code
....
// I check if the alarm is still on (probably awful, since it just fired)
SetAlarmReceiver setAlarmReceiver = new SetAlarmReceiver();
setAlarmReceiver.checkServiceRunning(ctx);
}
}
I use the same approach to check if the alarm is on from the main activity:
private void checkServicesRunning() {
SetAlarmReceiver setAlarmReceiver = new SetAlarmReceiver();
setAlarmReceiver.checkServiceRunning(getApplicationContext());
}
Everything looks correct to me, I've tried any solution I found, reading tons of questions like mine on StackOverflow but I still can't understand what I'm doing wrong.
The alarm fires correctly right after BOOT_COMPLETED is triggered by the system and it fires correctly when I just enabled the alarm (only if the notification time is in the past - f.e. when it's 10pm and the alarm must fire at 9am).
When the checkServiceRunning method runs, it tells me that the alarm is already enabled (returning true in the Logcat) but when I close the app and I re-run it after a while, the alarm looks like it's been canceled and it's being recreated by the app.
Any hint?
Thanks.
EDIT: I tried the command 'adb shell dumpsys alarm' and it actually shows my alarm running correctly so, at this point, I think the issue is something else but I cannot understand what...

Related

Alarm Clock: repeat setAlarmClock()

I'm trying to build an alarm clock, where the user can pick the time and the weekdays where the alarm has to fire. To do so, I used setAlarmClock(), because the alarm has to fire even if the device goes into doze mode.
The problem is, that setAlarmClock() is only a one time alarm and can't be repeated on a weekly basis.
The only solution I could think of is to make an setRepeatingAlarm(), which schedules the setAlarmClock() every day.
Please tell me if this is a smart work around or if there is a better way.
Also I'm not sure if I have to schedule the daily setAlarmClock() from a broadcast receiver or from an additional service.
Please tell me if you need further information or pieces of the code.
After many late hours I found the official solution. You have to handle all the alarms after each reboot. I have done this the following way:
Get permission in manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Then create a receiver with the following Intent filter:
<receiver android:name=".FragmentAlarm.RestartAlarmsReceiver" android:enabled="true"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<!--For HTC devices-->
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>`
Next you need to create this receiver. Mine looks like this:
public class RestartAlarmsReceiver extends BroadcastReceiver {
private String TAG = "halo";
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Log.e("starting", "starting JobScheduler");
schedule(context);
} else {
Log.e(TAG, "Received unexpected intent " + intent.toString());
}
}
private void schedule(Context context) {
// say when Job has to be executed
ComponentName componentName = new ComponentName(context, JobServiceC.class);
JobInfo info = new JobInfo.Builder(145, componentName)
.setOverrideDeadline(0)
.setPersisted(true) // keeps job alive after reboot -> need permission
.build();
JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
int resultCode = scheduler.schedule(info);
if (resultCode == JobScheduler.RESULT_SUCCESS) {
Log.e("TAG", "Job scheduled");
} else {
Log.e("TAG", "Job not scheduled");
}
}
private void cancel(Context context) {
JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
scheduler.cancel(145);
Log.e("TAG", "JobCancelled");
}
Here you must adjust the "Component Name", where you have to start your Java-class, which sets all the alarms again for this day.

Android How to set exact repeating alarm?

I'm building an alarm application which will have an exact repeating alarm.
Seeing how for Repeating Android provides only Inexact alarm with possible delay of 75% of chosen interval, I've tried making Exact alarm which upon triggering sets itself once again. This type of alarm works perfectly as long as my screen is kept on. But as soon as it goes to sleep, the alarm works fine the first time, but second alarm which is set programmaticaly fires with delay as if I was using Inexact method.
As an alternative solution I'm thinking of making an InexactRepeating alarm which will fire up every minute to check whether it's "the time". This way my alarm will be with 2 minute imprecision interval, which is acceptable. But I'm not sure how much it will strain phone's battery.
Any ideas guys?
Here's my attemp at Exact alarm:
AlarmManager.java
public static void setAlarm(Context context){
AlarmManager alarmManager = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);
//SET BROADCAST RECEIVER WHICH WILL BE THE ONE TO LISTEN FOR THE ALARM SIGNAL
Intent intent = new Intent(context, AlarmTriggerBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 22222, intent, PendingIntent.FLAG_CANCEL_CURRENT);
//SETING THE ALARM
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 300000, pendingIntent);
} else {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 300000, pendingIntent);
}
}
AlarmTriggerBroadcastReceiver.java
public class AlarmTriggerBroadcastReceiver extends BroadcastReceiver {
private final static String TAG_ALARM_TRIGGER_BROADCAST = "ALARM_TRIGGER_BROADCAST";
#Override
public void onReceive(Context context, Intent intent) {
//WAKE UP DEVICE
WakeLocker.acquire(context);
//LAUNCH PAGE
Intent intent1 = new Intent();
intent1.setClassName(context.getPackageName(), SomeActivity.class.getName());
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
Toast.makeText(context, "TOAST ALARM", Toast.LENGTH_LONG).show();
};
//SET NEW ALARM
AlarmManagerActivity.setAlarm(context);
WakeLocker.release();
}
}
WakeLocker.java
//WAKES UP DEVICE IF PHONE'S SCREEN LOCKED
public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context ctx) {
//if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, "myapp:WAKE_LOCK_TAG");
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null) wakeLock.release(); wakeLock = null;
}
}
Manifest
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.SET_ALARM"/>
<receiver
android:name=".Alarm.AlarmTriggerBroadcastReceiver"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
<intent-filter android:priority="1">
<action android:name="my.app.here.ALARM_RECIEVED" />
</intent-filter>
</receiver>
What do, fellow coders?
have you tried using a WorkManager instead of having to use the Broadcast Receivers? See details here. And an app demo here.

Repetitive alarm not working in actual devices but working in emulator

I know this is duplicate question but I have tried all the solution available on the Internet but not able to find the solution.
manifest file
<receiver android:name=".UpdateTables"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
calling this method in onCreate() of mainActivity.java and I also tried to call the method from application class.
private void setTheTimeToUpdateTables(Context context) {
Log.i("Update table function","Yes");
AlarmManager alarmManager=(AlarmManager) getSystemService(ALARM_SERVICE);
Intent alarmIntent=new Intent(context,UpdateTables.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(context,0,alarmIntent,PendingIntent.FLAG_UPDATE_CURRENT);
//alarmManager.cancel(pendingIntent);
Calendar alarmStartTime = Calendar.getInstance();
alarmStartTime.setTimeInMillis(System.currentTimeMillis());
//midnight
alarmStartTime.set(Calendar.HOUR_OF_DAY, 0);
alarmStartTime.set(Calendar.MINUTE, 1);
alarmStartTime.set(Calendar.SECOND, 0);
if(Calendar.getInstance().getTimeInMillis()>alarmStartTime.getTimeInMillis())
{
alarmStartTime.add(Calendar.DATE,1);
}
Log.i("TIME IS ",Long.toString(alarmStartTime.getTimeInMillis()));
System.out.println("Updating table time "+alarmStartTime);
System.out.println("Time in millseconds "+alarmStartTime.getTimeInMillis());
alarmManager.setInexactRepeating(AlarmManager.RTC,alarmStartTime.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);
Log.d("Alarm","Set for midnight");
}
public class UpdateTables extends BroadcastReceiver {
//midnight saga
DbHelper dbHelper;
ArrayList<ListMedicine> reminderInfo;
private SharedPreferences sharedPreferences;
private static AlarmManager alarmManager;
private static void init(Context ctx){
if (alarmManager==null)
alarmManager=(AlarmManager) ctx.getSystemService(Activity.ALARM_SERVICE);
}
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Update tables","yes");
}
When app is closed than it the updatetables broadcast receiver will not call.
output of ./adb shell dumpsys alarm before the app closed.
RTC #5: Alarm{28e47fec type 1 when 1487010660087 user.com.hlthee}
tag=*alarm*:user.com.hlthee/.UpdateTables
type=1 whenElapsed=+23h48m35s946ms when=2017-02-14 00:01:00
window=-1 repeatInterval=86400000 count=0
operation=PendingIntent{24cc8fb5: PendingIntentRecord{19e0864a user.com.hlthee broadcastIntent}}
But when the app is closed from recent activity then this entry is also delete. Why?
thats why no alarm is rang when app is closed.
Any help would be appreciated.
define a custom action name, such as:
public static final String MY_ACTION = "com.sample.myaction"
create a BroadcastReceiver:
public class MyAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(MY_ACTION)) {
// Do something here
}
}
}
Register the receiver on your AndroidManifest.xml:
<receiver android:name="com.sample.MyAlarmReceiver">
<intent-filter>
<action android:name="com.sample.myaction"/>
</intent-filter>
setup the alarm, use the following PendingIntent:
Intent i = new Intent(MY_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);

Starting service in android to read message after fixed interval

I am able to read message of user when the application gets installed. But what I want is that even after the application is closed, I should be able to read user message after a fixed interval of time. For example, application like Walnut that reads specific message and gives alerts automatically if any new message has come. How can I do the same.
Use Alarm manager and Pending Intent
Initiate Alarm manager here.
AlarmManager alarmMgr = (AlarmManager) this
.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
new Intent(this, AlarmReceiver_update.class),
PendingIntent.FLAG_CANCEL_CURRENT);
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
0, yourTimeInterval, pendingIntent);
And in AlarmReceiver_update class:
public class AlarmReceiver_update extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// Do whatever you want
}
}
And in Your AndroidManifest file register your receiver:
<receiver android:name="com.x.y.AlarmReceiver_update" >
<intent-filter>
<action android:name="android.test.BROADCAST" />
</intent-filter>
</receiver>
This is not complete just sample you have any doubt just comment.
You shuold use an alarm manager to set a repeating alarm.
Then you should setup a BroadcastReceiver Service that read the user messages onRecieve.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Run the task to read the user messages
}
}
This is a good tutorial
Have a look at the below links to learn how to notify the user if you found new message.
http://javatechig.com/android/repeat-alarm-example-in-android#3-defining-alarm-broadcastreceiver
http://developer.android.com/training/notify-user/build-notification.html

alarm manager does not launch android

Well in my app I am trying the following functionality. I want depending on the date and the time, the user to receiver some notifications.
For example:
September 9, 19.13 receive notification with message1
September 10, 07.30, with message 2,
same day, but 11.50, with message 3 and so on...
I used an alarm and a push bar notification but it worked only for the first one. So I serached for that and is is stated that I must use a repeating alarm manager.
Before I post my code I want to clarify some things:
1) I am thinking it that it should work like that:
i must check every 1-2 min, what time is it, fetch my next "time" from an array that events are stored, and set ana alarm for that, right? Then given that this bynch of code will run every 1-2 minutes, i will check again, fetch the next event,set alarm for that time and so on.
Am I correct?
So to begin with, i am trying to implement a repeating alarm manager which every 1 min will display me a Toast message (If I do this and replacing the toast message with get_next_event() and set_next_notification() will do the job I think. - These function are working fine in my project with only one alarm being set).
But problem is that when I am starting my service I see nothing.
here is my code:
Alarm.java
public class Alarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Starting Alarm Manager", Toast.LENGTH_LONG).show(); // For example
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
// Put here YOUR code.
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example
wl.release();
}
public void SetAlarm(Context context)
{
Toast.makeText(context, "Setting Alarm Manager", Toast.LENGTH_LONG).show(); // For example
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 , pi); // Millisec * Second * Minute
}
public void CancelAlarm(Context context)
{
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
YourService.java
public class YourService extends Service
{
Alarm alarm = new Alarm();
public void onCreate()
{
super.onCreate();
Toast.makeText(YourService.this, "Service Created", Toast.LENGTH_LONG).show(); // For example
}
public void onStart(Context context,Intent intent, int startId)
{
Toast.makeText(YourService.this, "Setting from Service", Toast.LENGTH_LONG).show(); // For example
alarm.SetAlarm(context);
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
DemoActivity.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStart = (Button) findViewById(R.id.buttonStart);
buttonStop = (Button) findViewById(R.id.buttonStop);
buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
public void onClick(View src) {
switch (src.getId()) {
case R.id.buttonStart:
Toast.makeText(ServicesDemo.this, "Button Pressed", Toast.LENGTH_LONG).show(); // For example
Log.d(TAG, "onClick: starting srvice");
startService(new Intent(this, YourService.class));
break;
case R.id.buttonStop:
Log.d(TAG, "onClick: stopping srvice");
stopService(new Intent(this, YourService.class));
break;
}
}
So i press the button, I see that "button is pressed" , i see that "service created" but then none of the toasts that alarm started are being shown. And of course, I see nothing every 1 min.
here is my manifest.
<application android:icon="#drawable/ic_launcher" android:label="#string/app_name">
<activity android:name=".ServicesDemo" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:enabled="true" android:name=".YourService" />
<receiver android:process=":remote" android:name="Alarm"></receiver>
</application>
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
</manifest>
So what do I need to change in my code or in the manifest?
I suggest you to use AlarmManager for this: http://developer.android.com/reference/android/app/AlarmManager.html .

Categories

Resources