I am making an application that notifies the user at certain times of the day. Like an alarm clock. The code works normally in versions prior to Android Oreo.
From what I read, Android Oreo and later versions kill actions in the background and that's why I'm having the error below.
2020-07-13 20:31:06.766 1609-1737/? W/BroadcastQueue: Background execution not allowed: receiving Intent { act=android.intent.action.PACKAGE_REPLACED dat=package:studio.com.archeagemanager flg=0x4000010 (has extras) } to air.br.com.alelo.mobile.android/co.acoustic.mobile.push.sdk.wi.AlarmReceiver
It is as if the BroadcastService is simply not triggered when it should be. But when I open the app, it starts up instantly.
AndroidManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="owner.custom.permission" />
<permission
android:name="owner.custom.permission"
android:protectionLevel="signatureOrSystem">
</permission>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<application
android:allowBackup="true"
android:icon="@mipmap/app_icon_new"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".SplashScreenActivity"
android:theme="@style/AppCompat.TelaCheia">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<receiver
android:name=".AlarmReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
TabFragEventA.java (Here I put only the function that initiates the alarm)
public void startAlarm(int eventID) {
String[] NOTIFICATION_TITLES = {"Ocleera Rift", "Ocleera Rift", "Mistmerrow Conflict", "Mistmerrow Conflict",
"Mistmerrow Conflict", "Nation Construction Quests", "Diamond Shores", "Diamond Shores", "Battle of the Golden Plains",
"Battle of the Golden Plains", "Karkasse Ridgelands", "Kraken", "The Mirage Isle Fish Fest", "Red Dragon",
"Abyssal Attack", "Lusca Awakening", "Delphinad Ghostship", "Cattler Wrangler", "Legendary Chef", "+1"};
String notificationTitle = getString(R.string.contentTitle);
String notificationText = NOTIFICATION_TITLES[eventID] + getString(R.string.contentNotificationText);
int alarmHour = localHour.get(eventID);
int alarmMinute = localMinute.get(eventID);
// Decrease 5 minutes
if(alarmMinute == 0) {
alarmHour = alarmHour - 1;
alarmMinute = 55;
} else {
alarmMinute = alarmMinute - 5;
}
// Setting the alarm moment
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, alarmHour);
calendar.set(Calendar.MINUTE, alarmMinute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
// Analyze if the alarm moment has passed
Calendar actualTime = Calendar.getInstance();
if(actualTime.getTimeInMillis() >= calendar.getTimeInMillis()) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
Intent intent = new Intent(getActivity().getApplicationContext(), AlarmReceiver.class);
intent.putExtra("contentTitle", notificationTitle);
intent.putExtra("contentText", notificationText);
/*if(eventID == 11 || eventID == 13) {
intent.putExtra("specificDayWeek", true);
} else {
intent.putExtra("specificDayWeek", false);
}*/
if(eventID == 12) {
intent.putExtra("castleSupply", true);
intent.putIntegerArrayListExtra("castleSupplyDayWeek", (ArrayList<Integer>) CastleSupply);
}
else if(eventID == 13) {
intent.putExtra("castleClaim", true);
intent.putIntegerArrayListExtra("castleClaimDayWeek", (ArrayList<Integer>) CastleClaim);
}
else if(eventID == 14) {
intent.putExtra("abyssalAttack", true);
intent.putIntegerArrayListExtra("abyssalDaysWeek", (ArrayList<Integer>) AbyssalDayWeek);
}
else if(eventID == 15) {
intent.putExtra("luscaAwakening", true);
intent.putIntegerArrayListExtra("luscaAwakeningDayWeek", (ArrayList<Integer>) LuscaAwakening);
} else {
intent.putExtra("abyssalAttack", false);
}
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
// PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity().getApplicationContext(), eventID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity().getApplicationContext(), eventID, intent, 0);
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String contentTitle = intent.getStringExtra("contentTitle");
String contentText = intent.getStringExtra("contentText");
String CHANNEL_ID = "my_channel_01";
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Channel Name";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
notificationManager.createNotificationChannel(mChannel);
}
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.icon_notification)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_notification))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setVibrate(new long[]{800, 500, 600, 300});
notificationManager.notify(0, notificationBuilder.build());
Log.d("ALARMRECEIVER", "INSIDE");
}
}
I would like to know what to do to make the Broadcast Receiver work in the background. Or an alternative to set this alarm clock on Android Oreo + so that it notifies the user even with the application closed or in the background.