AlarmManager executes my PendingIntent immediately instead of waiting for sertain time - android

I am trying to implement an alarm, and therefore my app has 2 activities: main one (where the user sets an alarm) and the 'ringing' one which is displayed when the alarm is actually triggered. Here is how I send an intent for AlarmManager to call the 'ringing' window:
public void scheduleAlarm(View view) {
Intent intent = new Intent(this, WakeUp.class);
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent wakeUp = PendingIntent.getActivity(this, 123, intent, 0);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(this.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calculateMillis(), wakeUp); // setExact is pretty much made for setting alarms anyway
}
private long calculateMillis() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
return cal.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
}
In my manifest I have the following:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".WakeUpWithMath"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".WakeUp"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/title_activity_wake_up"
android:theme="#style/FullscreenTheme" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>
</application>
I have tested it multiple times and with different values for the calculateMillis (even mocked to return 30000) yet the result is always the same: right after calling alarmManager.setExactit displayes the 'ringing' activity and does not wait for the time to pass at first.
What have I missed? Is the manifest configured wrong? do I need to use a <receiver> tag? if so, how should I configure it?

setExact uses absolute time, not relative time. Use the time returned by cal.getTimeInMillis() without subtracting current time.

Related

Use Alarm Manager to set Notification at specific time but my receiver class is not called on time

Long time = prefs.getLong("dailynoti", 0);
Intent intent = new Intent(cn, NotificationReceiver.class);
intent.putExtra("Desc", "Description...");
PendingIntent pendingIntent = PendingIntent.getBroadcast(cn, 1055, intent,0);
AlarmManager alarmManager = (AlarmManager) cn.getSystemService(cn.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,time, AlarmManager.INTERVAL_DAY, pendingIntent);
and my mainifest file
<receiver
android:name="com.mypackage.NotificationReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.REBOOT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
And this same code is use in same project but now in same project another module it will not work Broadcast Receiver isn't call at given time
my notification code is in Receiver file but Receiver class isn't call.
I checked all things like time is also get properly. so what is the problem . please help...
I used many solution like
PendingIntent pendingIntent = PendingIntent.getBroadcast(cn, 1055, intent, PendingIntent.FLAG_CANCEL_CURRENT
//FLAG_NO_CREATE
//FLAG_UPDATE_CURRENT
One approach that I think that will work is instead of alarmManager.setRepeating() use alarmManager.set() and when the alarm triggers then set the next alarm. This will give you almost accurate results. Why almost? Because due to Doze mode introduced in Android M. So this will give you between 0 to +5 min delay.

Query for when my service will be run in Android?

I have a service that fires off every 5 minutes or so... How would i query android to see when this service is scheduled to go off programatically?
<!-- Send Census Service -->
<service android:name="services.scheduled.SendCensusScheduledService"
android:icon="#drawable/ic_launcher"
android:label="SyncServerDataScheduledService" />
<receiver android:name="services.receivers.SendCensusScheduledServiceReceiver" >
<intent-filter>
<action android:name="ReceiptBucketClient.android.action.broadcast"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name="services.receivers.StartSendCensusScheduledServiceReceiver" />
Check by the PendingIntent:
PendingIntent intent = PendingIntent.getBroadcast(context, 0,
new Intent("ReceiptBucketClient.android.action.broadcast"),
PendingIntent.FLAG_NO_CREATE;
if (intent != null) {
// you have the service scheduled. Cancel it!
intent.cancel();
}
Remember that only the original application owning a PendingIntent can cancel it.

Android AlarmManager at Boot

I am using an AlarmManager to start a service that runs every minute. However, I am getting the "The application blabla has stopped unexpectedly." warning dialog with Force Close button when I turn on the device. I do not know what the error is because the only debugging option I have is with WIFI and the IP of the connection changes every time I reboot the device.
The service runs fine without the boot.
Here is my BroadcastReceiver running under the application:
public class FPBootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
android.os.Debug.waitForDebugger();
Intent bootintent = new Intent(context, FPService.class);
PendingIntent pi = PendingIntent.getService(context, 0, bootintent, PendingIntent.FLAG_UPDATE_CURRENT);
long nextUpdateTimeMillis = DateUtils.MINUTE_IN_MILLIS;
Time nextUpdateTime = new Time();
nextUpdateTime.set(nextUpdateTimeMillis);
AlarmManager FPAlarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
FPAlarm.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), nextUpdateTimeMillis, pi);
}
}
Manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:icon="#drawable/pc"
android:label="#string/app_name" >
<service android:name=".FPService" />
<receiver android:enabled="true" android:name="mypackage.FPBootReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name=".CF_Aachen"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Anything wrong you see that I am doing wrong with these?
UPDATE: Managed to debug the boot and I am getting AndroidRuntime(2781): java.lang.RuntimeException: Unable to instantiate receiver mypackage.FPBootReceiver: java.lang.ClassNotFoundException: mypackage.FPBootReceiver in loader dalvik.system.PathClassLoader
Android system can not see your Receiver, check your path unless your full package is actually "mypackage". You ether need to make it ".mypackage.FPBootReceiver" or specify the full path.
I wrote my BroadcastReceiver class under the same class of my Activity. That's why it was unable to find it.
I created a seperate class file in mypackage and created the class there and then it was solved.
Thanks to all who advised.

Broadcast Receiver and widget timezone

I use Broadcast Receiver, WidgetProvider and Configure Activity. Activity starts during the creation of a widget. Widgets are updated every 20 seconds.
private PendingIntent service = null;
Intent intent = new Intent(context, AlarmReceiver.class);
if (service == null) {
service = PendingIntent.getBroadcast(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
m.setRepeating(AlarmManager.RTC, TIME.getTime().getTime(), 1000 * 20,
service);
I whant to update widgets when I change time or timezone on my phone. Widgets are updated when I change the time ahead. But when I change the time back, nothing happens.
I've already added to the manifest
<receiver android:name=".AlarmReceiver" >
<intent-filter>
<action android:name="android.intent.ACTION_TIMEZONE_CHANGED" />
<action android:name="android.intent.ACTION_TIME" />
</intent-filter>
</receiver>
In the Broadcast Receiver I'm updating widgets.
Please refer to
http://developer.android.com/reference/android/content/Intent.html#ACTION_TIMEZONE_CHANGED
They should be
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.TIME_SET" />

How to update an app widget on midnight?

My app has a widget that shows today's date and need to be updated on midnight. The widget is defined in the manifest as
<manifest>
...
<application>
...
<receiver
android:name=".MyWidgetProviderClass"
android:label="MyLabel" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_icon_info" />
</receiver>
</application>
</manifest>
And the widget info file is
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="#layout/my_layout"
android:minHeight="40dp"
android:minWidth="294dp"
android:updatePeriodMillis="3600000" >
</appwidget-provider>
This causes the widget to get updated anytime between midnight and 1pm but I want to to get updated closer to midnight so I added to the app an intent receiver
<receiver
android:name=".MyWidgetUpdaterClass"
android:enabled="true" >
<intent-filter>
<action android:name="MyAction" />
</intent-filter>
</receiver>
and a static method
public static void setMidngintAlarms(Context context) {
Intent intent = new Intent("MyAction");
PendingIntent pendingIntent =
PendingIntent.getBroadcast(context, 0, intent, 0);
long interval = 24*60*60*1000;
long firstTime = SystemClock.elapsedRealtime() +
millisecondsToNextMidnight();
AlarmManager am = (AlarmManager)context.getSystemService(
Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, interval, pendingIntent);
}
(since alarm manager requests with the same intent overwriting each other there is not harm in calling setMidngintAlarms multiple times).
I tried calling setMidnightAlarms() from few places (from the app's main activity, from the AppWidgetProvider's onUpdate(), etc). Everything works well and the alarm manager intents are received and the widget is updated but only as long as the app runs. If I killed the app, the widgets stops updating on midnight.
Any idea how to cause the widgets to update on midnight? Do I need to add a service? If so how? Any example?
I am a little bit surprised how non trivial it is to get this basic functionality to work.
I resolve this problem by:
Start a service to listen to Intent.ACTION_TIME_TICK message.
Then send a broadcast to widget if Time TICKED. (At every minute).
Receive the broadcast in widget and judge weather it is the midnight by:
Code:
if (MyWidget.BROADCAST_TIME_TICK.equals(action)) {
//If it's midnight, then update.
int hour = Calendar.getInstance().get(Calendar.HOUR);
int minute = Calendar.getInstance().get(Calendar.MINUTE);
Utils.log(TAG, "time is : " + hour+":" + minute);
if (!(hour == 0 && minute == 0)) { //Only update at midnight's time tick.
return;
} else {
//Do the midnight stuff.
}
}
ad this to your manifest widget receiver
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="android.intent.action.DATE_CHANGED" />...
the change in date will trigger your onReceive() to fire up with the "android.intent.action.DATE_CHANGED" action

Categories

Resources