The code snippet below....
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
///////////Do something////////////////////////
showtext.startScan();
//SEt Alarm
Intent intent = new Intent(this, TextReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+9000, pi);}
And my Receiver :
TextReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
///Show text/////
}
}
The thing is that when I run the program after 9sn, I am getting an error that "The app stopped unexpectedly". Why I get this error?
My goal is to show the text every 9sn. What is the correct usage of AlarmManager in the main activity
OR Should I set alarm in the BroadcastReceiver ?
Which one does makes sense: am.setRepeating or am.set in terms of my goal?
**Edit: How can I change my alarm code to run in the Broadcast Receiver ? **
//try this
AlarmManager am=(AlarmManager)getApplicationContext getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),(9 * 1000), pendingIntent);
Never, ever use FLAG_CANCEL_CURRENT with PendingIntents that are set as alarms.
What happens is that you wind up canceling the validity of the PendingIntent currently held by the alarm manager, and this means that the alarm manager can no longer tell that any newly-set alarm matches that old PendingIntent. You wind up with the old (invalid) alarm still registered along with your new one. If you keep doing this you can wind up with hundreds (or more!) stale alarms registered in the system, none of which will actually do anything but which are taking up memory and CPU.
Related
I have set repeating alarms, it works well but when I update the time the alarm does not work. I'm using same code and flag in pending intent but creating and updating from different activity. In log it says the alarm is triggered at specific time but it is not working. can anyone say what is the problem?
Calling alarm from Insert activity:
startAlarm(Insert.this, pillName, timeInMilis, code);
Calling alarm from Edit activity:
startAlarm(Edit.this, pillName, timeInMilis, code);
Function for creating and updating alarm:
public void startAlarm(Context context, String pillName, long time, int code) {
Intent aIntent = new Intent(context, AlarmReceiver.class);
aIntent.putExtra("pillName", pillName);
aIntent.putExtra("code", code);
PendingIntent pIntent = PendingIntent.getBroadcast(context, code, aIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time,60000, pIntent);
}
Broadcast Receiver class:
public void onReceive(Context context, Intent intent) {
String pillName=intent.getExtras().getString("pillName");
MediaPlayer mediaPlayer=MediaPlayer.create(context, Settings.System.DEFAULT_NOTIFICATION_URI);
mediaPlayer.start();
Toast.makeText(context,"Testing Alarm::"+pillName,Toast.LENGTH_SHORT).show();
}
When you start before stop the AlarmManager pending intent. It's may be working well
My code
public class BackgroundIntentService extends IntentService {
public BackgroundIntentService() {
super("BackgroundIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
scheduleNextUpdate();
Log.w("Blabla", "asldad111");
Log.w("Blabla", "asldad");
Log.w("Blabla", "asldad");
Log.w("Blabla", "asldad555");
}
private void scheduleNextUpdate() {
Intent intent = new Intent(this, this.getClass());
PendingIntent pendingIntent =
PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// The update frequency should often be user configurable. This is not.
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 5000, pendingIntent);
}
}
To start the service
Intent serviceIntent = new Intent(this, BackgroundIntentService.class);
startService(serviceIntent);
In the MainActivity.
The problem is that I can see in the logcat those logs spamming, not every 5 seconds but twice a second or more.
Where I'm wrong?
The flag you are using PendingIntent.FLAG_UPDATE_CURRENT in
PendingIntent pendingIntent =
PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
should be PendingIntent.FLAG_CANCEL_CURRENT
as quoted on the developer docs
FLAG_CANCEL_CURRENT - Flag indicating that if the described PendingIntent already exists, the current one should be canceled before generating a new one.
FLAG_UPDATE_CURRENT - Flag indicating that if the described PendingIntent already exists, then keep it but replace its extra data with what is in this new Intent.
so in your case the current pending intent exists and the new one updates it and fires at the exact moment it is updating the existing pending since you have defined the trigger time to be at System.currentTimeMillis()
So what is happening is that the current Pending intent is firing up before the new pending intent updates it ..and once it does that works as per the alarm logic , after the 5000ms interval the pending intent is fired. So there is a race condition here with interleaved alarm triggers and updates via the pending intents.
I have a service which uses PendinIntent and AlarmManager to launch another activity after a fixed period of time.
Here is the relevant code of the service:
Calendar cal = Calendar.getInstance(); //Create a calendar
cal.add(Calendar.MINUTE, 1); //Add the set minutes to the alarm
Intent dialogIntent = new Intent(this, alarmRingLayout.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1234, dialogIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
When the service starts, I also set up a notification which has the a button that can cancel the service incase the user does not want the activity to launch.
On click of the "cancel" button, stopService() is called:
stopService(new Intent(StopPowerNapAlarmService.this, PowerNapAlarmService.class));
onDestroy() has the following code which cancels the notification and calls stopSelf()
It also tries to cancel the PendingIntent and AlarmManager.
The problem is that the Activity opens up even after after onDestroy is called. I believe the PendingIntent and/or AlarmManager are not getting canceled.
Here is the code for onDestroy():
#Override
public void onDestroy() {
Toast.makeText(this, "Alarm Finished", Toast.LENGTH_SHORT).show();
CancelNotification(this, 0);
//Cancel the pending intent and AlarmManager
Intent myntent = new Intent(PowerNapAlarmService.this, PowerNapAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
1234, myntent, PendingIntent.FLAG_UPDATE_CURRENT);
pendingIntent.cancel();
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.cancel(pendingIntent);
stopSelf();
}
What is going wrong over here?
What is going wrong over here?
Your Intent objects are different, so your PendingIntent objects are different. This, in turn, means that you are working with different alarms. The first Intent points to an alarmRingLayout.class activity. The second Intent points to a BroadcastReceiver oddly named PowerNapAlarmService.
If you want to cancel() the alarmRingLayout alarm, create an activity PendingIntent for alarmRingLayout, and use that with cancel().
Also, please get rid of stopSelf() in onDestroy(), as that is not needed and could conceivably cause problems.
I'm from an iOS background with intermediate Android knowledge. Anyways for this task, I need to know what exactly I need to work with. My app needs to check if the user is at or close to the predefined location at a predefined time. Getting user location is not an issue.
My guess is working with a combination of AlarmManager, BroadcastReceiver and Service ? I haven't worked with either of these three.
Any help is appreciated. :)
These are the ingredients you need for you recipe:
An Intent that targets your BroadcastReceiver:
Intent intent = new Intent(context, YourBroadCastReceiver.class);
A PendingIntent that gets triggered by the AlarmManager and fires your already defined Intent:
PendingIntent pIntent = PendingIntent.getBroadcast(context, requestCode, intent, flags);
The AlarmManager that periodically activates your PendingIntent:
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, intervalMillis, pIntent);
The BroadCastReceiver that handles the event:
#Override
protected void handleReceive(Context context, Intent intent) {
// handle GPS
}
I've been struggling with this for a couple of days. What I want to do is run a service periodically, about 2-3 minutes apart. I have an Activity that is responsible for the interface and setting up the first alarm.
The alarm is configured by a BroadcastReceiver which looks like this:
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String message = "Alarm worked";
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
setAlarm(context);
}
public void setAlarm(Context context){
AlarmManager am = (AlarmManager) context.
getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, Receiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent dailyUpdater = new Intent(context, DiscoveryService.class);
context.startService(dailyUpdater);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+ (1000 * 30) , pi);
}
}
I've tried using setRepeating for AlarmManager, but it still has the same effect. What happens is that the AlarmManager works how it should, it fires an Intent which the receiver gets and executes onReceive periodically, as it should. However, it executes the service only the first time. After the first time, the alarms still go off, but the service is not executed.
I read some threads from people with similar problems, and one of them mentioned that PendingIntent lasts for only one send. Thus, I opted out to setting the alarm every time so I can set pendingIntent flag for updating every time.
I tried making my service an intentService, which is fine, but then my bluetooth scanner inside the service does not work because intentService thread terminates without waiting for my bluetooth discovery to finish.
Anyone have any idea what can help me?
Here is part of my service:
public class DiscoveryService extends Service {
public void onCreate() {
super.onCreate();
Toast.makeText(this, "MyAlarmService.onCreate()",
Toast.LENGTH_LONG).show();
findEverything();
}
}
EDIT: This is the code that I currently have.
public void onReceive(Context context, Intent intent) {
String message = "Alarm worked";
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
Intent dailyUpdater = new Intent(context, DiscoveryService.class);
context.startService(dailyUpdater);
}
public void setAlarm(Context context){
// get a Calendar object with current time
AlarmManager am=(AlarmManager)context.
getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, Receiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
(1000 * 30) , pi);
}
What happens is that the AlarmManager works how it should, it fires an Intent which the reciever gets and executes onReceive periodically, as it should. However, it executes the service only the first time. After the first time, the alarms still go off, but the service is not executed.
You are calling startService() once when you are scheduling the alarm. You are not calling startService() at all from your BroadcastReceiver. Yet you are scheduling the alarm via the BroadcastReceiver. Hence, when the alarm goes off, the service will not be sent a command, because you are not sending it a command.
I read some threads from people with similar problems, and one of them mentioned that PendingIntent lasts for only one send.
That is only if you use FLAG_ONE_SHOT.
Anyone have any idea what can help me?
Call startService() from your onReceive() method, instead of from your setAlarm() method. Also, add in all the WakeLock management logic, since you are using a _WAKEUP alarm and you are not able to use my WakefulIntentService.