Я делаю приложение, которое уведомляет пользователя в определенное время дня. Как будильник. Код работает нормально в версиях до Android Oreo.
Из того, что я читал, Android Oreo и более поздние версии убивают действия в фоновом режиме, поэтому у меня возникает ошибка ниже.
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
Это как если бы BroadcastService просто не запускался, когда должен. Но когда я открываю приложение, оно запускается мгновенно.
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 (Здесь я помещаю только функцию, которая инициирует тревогу)
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");
}
}
Хотелось бы знать, что сделать, чтобы широковещательный приемник работал в фоновом режиме. Или альтернативный вариант - установить этот будильник на Android Oreo +, чтобы он уведомлял пользователя даже при закрытом приложении или в фоновом режиме.