I've been trying to setup my first alarm using AlarmManager and BroadCastReceiver as explained here: http://smartandroidians.blogspot.com.es/2010/04/alarmmanager-and-notification-in.html
My setup:
AndroidManifest.xml:
<receiver android:name="es.radiopodcastellano.player.SleepAlarm" />
My main Activity onCreate (this code actually resides on a subclass, but to simplify I put it there):
#Override
public void onCreate(Bundle savedInstanceState) {
// <Stripped code>
AlarmManager alarm = (AlarmManager) currentContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this.getApplicationContext(), SleepAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
alarm.set(AlarmManager.RTC_WAKEUP,(System.currentTimeMillis() + (5 * 1000)),pendingIntent);
}
SleepAlarm.java:
public class SleepAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("RPod_SleepAlarm","Alarm!!");
}
}
Output from "adb shell dumpsys alarm" show this, so it seems the intent is being called:
es.radiopodcastellano.player
221ms running, 32 wakeups
44 alarms: flg=0x4 cmp=es.radiopodcastellano.player/.SleepAlarm
However, Logcat shows nothing for "RPod_SleepAlarm" tag. What could I be doing wrong?
I found the problem.
The receiver on the manifest was inside another receiver for a widget, and it must be a children of the application. So, if you're having the same behaviour as me, please check that you've set up the AndroidManifest.xml correctly:
Related
I am starting to learn about the AlarmManager, and I want to fire a broadcast to fetch some info from a server. The documentation is clear about the intents and the alarms, but I cannot find anything on how the receiving end should look.
This is my alarm code:
AlarmManager aMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
aMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 10000,
AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);
and my AlarmReceiver is like this:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(MainActivity.TAG, "Received intent");
}
}
But nothing happens. I added a button to just fire the broadcast like this:
public void btnTrigger_onClick(View view) {
Intent i = new Intent(this, AlarmReceiver.class);
sendBroadcast(i);
}
and also nothing happens here.
I have used broadcasts before, but only with registerReceiver, but I do not want to process the broadcast in my Activity now.
Explicit broadcasts — ones where the Intent has the component name (i.e., class) — require a <receiver> element in the manifest in order to work.
I'm programming an application that will fire a specific method once it hits a certain date / time. However, my broadcast reciever is not firing...i can see that the alarm is set.
my method within an activity:
private void setAlarm(Date date){
Intent activate = new Intent(this, Alarm.class);
AlarmManager alarms ;
Calendar cal = new GregorianCalendar();
cal.setTimeInMillis(date.getTime());
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, activate, 0);
alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Log.d("ALARM","Setting alarm");
alarms.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmIntent);
Log.d("ALARM","Setting time "+cal.getTimeInMillis());
}
My BroadcastReciever:
public class Alarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("ALARM", "RING RING");
}
}
My manifest within the <application> tag:
<receiver android:name=".Alarm" android:process=":remote" >
<intent-filter>
<action android:name="com.package.feature.subpackage.arrangealarm.ALARM_ACTION"/>
</intent-filter>
</receiver>
Does anyone have any idea why this is not firing?
There seems to be nothing wrong with your code (I copied the snippet and had Android Studio generate a BroadcastReceiver for which I set android:process=":remote" just like you do).
When I run the app, the BroadcastReceiver fires but I can only see the respective Logcat entry when I select "No Filters" in the Logcat settings (on the right side), not when I choose "Show only selected application".
This happens because you use android:process=":remote". The BroadcastReceiver will run in another process than the "main" application process, so the "RING RING" will appear under another process id.
I'm trying to make an Alarm using the Alarm Manager. The app runs without any error messages, but nothing happens.
I tried solutions from developer.android.com and suggestions from stackoverflow.
I also tried copying a complete tutorial i found, but nothing worked.
The app runs on API22 and was tested on an emulator(API23) and a real device(API22).
This is my Code:
MainActivity.java startAlarm():
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent myIntent = new Intent(MainActivity.this,AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,myIntent,0);
manager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime()+3000,pendingIntent);
AlarmReceiver.java:
public class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"THIS IS MY ALARM",Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml, between <manifest...> and </manifest>:
<receiver android:process=":remote" android:name=".AlarmReceiver"></receiver>
your reciever name is AlarmToastReceiver not AlarmReceiver
try:
<receiver android:process=":remote" android:name=".AlarmToastReceiver "></receiver>
Ok, so I have a main activity called 'Main.java'. This main activity starts an AlarmManager which fires an intent leading to 'AlarmReceiver.java'.
This 'AlarmReceiver.java' then creates a notification which has two buttons on it. One of the buttons is a deletion button, and so when the user clicks on that button, another intent is fired, leading it to 'DelPair.java'.
In DelPair.java, I modify a table in a Database, but then I need the UI of Main.java to reflect this change. I have created two functions in Main.java called updateArrayFromDB() and updateUIFromArray() to do this for me:
updateArrayFromDB() will sync an ArrayList created in Main.java to a
certain table in the DB.
updateUIFromArray() will change the UI of
Main.java to represent the ArrayList that has just been changed.
The problem is that I cannot call these two functions from DelPair.java (they don't exist in that space). I have come across Serializables in trying to find an answer but I don't know enough to know if they apply here or exactly how to implement them across the AlarmManager and the NotificationManager.
How can I access these methods from DelPair.java?
In Main.java:
public void updateArrayFromDB(){
//... The code for this is long and irrelevant
}
public void updateUIFromArray(){
//... The code for this is long and irrelevant
}
private void SendNotification() {
Intent intent = new Intent(this, AlarmReceiver.class);
//...
PendingIntent sender = PendingIntent.getBroadcast(this, 2 , intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, 5000, notif_freq, sender);
}
In AlarmReceiver.java:
Intent delPairI = new Intent(context, DelPair.class);
PendingIntent delPairPI = PendingIntent.getService(context, 0, delPairI, PendingIntent.FLAG_UPDATE_CURRENT);
Notification noti;
noti = new Notification.Builder(context)
//...
.addAction(R.drawable.ic_delete_icon, "Delete the thing", delPairPI)
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, noti);
and then in DelPair.java:
public class DelPair extends IntentService {
//...
#Override
protected void onHandleIntent(final Intent intent) {
//...
Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
getApplicationContext().sendBroadcast(it);
handler.post(new Runnable() {
#Override
public void run() {
//... here is where I update the database, which works perfectly
//now need to update the UI and array in Main.java
updateArrayFromDB(); //these lines
updateUIFromArray(); //obviously don't work
}
});
}
}
Why not use broadcasts ? in onHandleIntent just send a broadcast
Intent i = new Intent();
i.setAction(CUSTOM_INTENT);
//put relevant data in intent
getApplicationContext().sendBroadcast(i);
The broadcast receiver:
public class IncomingReceiver extends BroadcastReceiver {
private MainActivity act;
public IncomingReceiver(MainActivity main){
this.act = act;
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(CUSTOM_INTENT)) {
System.out.println("GOT THE INTENT");
// call the method on act
}
}
}
In your activity onResume - register new IncomingReceiver, onPause unregister
private IncomingReceiver receiver;
public void onCreate(Bundle bOs){
//other codes
receiver = new IncomingReceiver(this);
}
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction(CUSTOM_INTENT);
registerReceiver(receiver, filter);
super.onResume();
}
#Override
protected void onPause() {
unregisterReceiver(receiver);
super.onPause();
}
Since you need to have an updated UI based on database changes, you can call updateArrayFromDB() and updateUIFromArray() in the onResume() method of your activity so the UI gets updated each time the user enters the activity.
I am using cwac-Location Poller (from here) to constantly poll user location and display location based notifications. This all is working fine but now I am trying to attach another BroadcastReceiver so that if my application is in foreground, instead of displaying notification animate the google map to current user location. But for some reason I can't get it working.
onCreate() method of MapActivity I have following code to start poller:
#Override
public void onCreate(Bundle savedInstanceState) {
.....
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, LocationPoller.class);
Bundle bundle = new Bundle();
LocationPollerParameter parameter = new LocationPollerParameter(bundle);
parameter.setIntentToBroadcastOnCompletion(new Intent(this, LocationReceiver.class));
parameter.setProviders(new String[] {LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER});
parameter.setTimeout(60000);
i.putExtras(bundle);
pendingIntent = PendingIntent.getBroadcast(this, 0, i, 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), PERIOD, pendingIntent);
}
in onResume() method I am registering another receiver using registerReceiver() method:
#Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(com.commonsware.cwac.locpoll.LocationPollerParameter.INTENT_TO_BROADCAST_ON_COMPLETION_KEY);
intentFilter.setPriority(1);
registerReceiver(locationReceiver, intentFilter);
}
Where locationReceiver looks like:
private BroadcastReceiver locationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "mapActivity called");
abortBroadcast();
}
};
And in order to send ordered broadcast to multiple receiver I have modified LocationPollerService to use sendOrderedBroadcast instead of sendBroadcast
public void onLocationChanged(Location location) {
handler.removeCallbacks(onTimeout);
Intent toBroadcast = createIntentToBroadcastOnCompletion();
toBroadcast.putExtra(LocationPollerResult.LOCATION_KEY, location);
sendOrderedBroadcast(toBroadcast, null);
quit();
}
Now the problem is my dynamically registered receiver never get called but the one mentioned in AndroidManifest.xml does:
<receiver android:name=".receiver.LocationReceiver" />
<receiver android:name="com.commonsware.cwac.locpoll.LocationPoller" />
<service android:name="com.commonsware.cwac.locpoll.LocationPollerService" />
Your problem is in a disconnect between the IntentFilter you create in Java and your createIntentToBroadcastOnCompletion() implementation, which you did not include in your question. Your IntentFilter is expecting a broadcast with a certain action string -- the Intent you are creating in createIntentToBroadcastOnCompletion() apparently does not include this action string.
BTW, with respect to "And in order to send broadcast to multiple receiver", sendBroadcast() is perfectly capable of sending broadcasts to multiple receivers.