In my android application I have a "global" application class and inside it, among others, I have a static BlockingQueue in which I store information. When the queue is full I flush it to file. I have multiple producers, Services, BroadcastReceivers and everything works fine. Now I have to add an alarm that every 30 minutes triggers a PendingIntent from which I have to write to this BlockingQueue and this doesn't work! I see that the appropriate functions are called but the data is not written. If I Log.d() it before blockingQueue.put() I can see the data and then it get lost. I do the same procedure from everywhere in my app and it only does not work from the BroadcastReceiver of the PendingIntent of the Alarm. For sure I'm missing something. What can I do?
Here's how I trigger the Alarm from a Service (and it works):
alarmNotificationIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, QuestionnaireNotificationReceiver.class), 0);
if(alarmNotificationIntent!=null) {
if (alarmManager != null) {
if (iLogApplication.isAtLeastMarshmallow()) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + Constants.NOTIFICATION_INTERVAL, alarmNotificationIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + Constants.NOTIFICATION_INTERVAL, alarmNotificationIntent);
}
}
}
And this is the BroadcastReceiver:
public class QuestionnaireNotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(context.toString(), "Questionnaire notification");
//this method does blockingQueue.put(answer.toString());
iLogApplication.persistInMemoryAnswerQuestionnaireEvent(new Answer(new Question(666)));
System.out.println(iLogApplication.questionnaire.toString());
SharedPreferences sharedPreferences = context.getSharedPreferences(Constants.PACKAGE_NAME, Context.MODE_PRIVATE);
Intent notificationIntent = new Intent(context, NotificationActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, (int) System.currentTimeMillis(), notificationIntent, 0);
iLogApplication.questionnaireBuilder.setContentTitle("Nuova domanda disponibile")
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_notification_bar)
.setAutoCancel(false)
.setOngoing(true);
String notificationText = "Hai %d domand%c a cui rispondere";
if (iLogApplication.questionnaireBuilder != null) {
iLogApplication.questionnaireBuilder.setWhen(System.currentTimeMillis());
if(iLogApplication.questionnaire.getNumberOfQuestions()>2) {
iLogApplication.questionnaireBuilder.setContentText(String.format(notificationText, iLogApplication.questionnaire.getNumberOfQuestions(), 'e'));
}
else {
iLogApplication.questionnaireBuilder.setContentText(String.format(notificationText, iLogApplication.questionnaire.getNumberOfQuestions(), 'a'));
}
}
if (iLogApplication.notificationManager != null) {
iLogApplication.notificationManager.notify(Constants.QUESTIONNAIRENOTIFICATIONID, iLogApplication.questionnaireBuilder.build());
}
PendingIntent alarmNotificationIntent = PendingIntent.getBroadcast(context, 0, new Intent(context, QuestionnaireNotificationReceiver.class), 0);
if(alarmNotificationIntent!=null) {
if(iLogApplication.alarmManager!=null) {
if (iLogApplication.isAtLeastMarshmallow()) {
iLogApplication.alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+ Constants.NOTIFICATION_INTERVAL, alarmNotificationIntent);
} else {
iLogApplication.alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+ Constants.NOTIFICATION_INTERVAL, alarmNotificationIntent);
}
}
}
}
}
Since I want my alarm to work also in Marshmallow Doze mode I have to use setExactAndAllowWhileIdle()
and recall the method every time the Broadcast is triggered.