Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LocalNotification with AlarmManager and BroadcastReceiver not firing up in Android O (oreo)

Tags:

I've got my local notifications running on androids prior to SDK 26

But in a Android O I've got the following warning, and the broadcast receiver is not fired.

W/BroadcastQueue: Background execution not allowed: receiving Intent { act=package.name.action.LOCAL_NOTIFICATION cat=[com.category.LocalNotification] flg=0x14 (has extras) } to package.name/com.category.localnotifications.LocalNotificationReceiver 

From what I've read broadcast receivers are more restricted in android O, but if so, how should I schedule the broadcast if I want it launching even if the main activity is not running?

Should I use services instead of receivers?

This is the AlarmManager launch code:

public void Schedule(String aID, String aTitle, String aBody, int aNotificationCode, long aEpochTime) {     Bundle lExtras = new Bundle();     lExtras.putInt("icon", f.getDefaultIcon());     lExtras.putString("title", aTitle);     lExtras.putString("message", aBody);     lExtras.putString("id", aID);     lExtras.putInt("requestcode", aNotificationCode);      Intent lIntent =        new Intent(LocalNotificationScheduler.ACTION_NAME)       .addCategory(NotificationsUtils.LocalNotifCategory)       .putExtras(lExtras);      PendingIntent lPendIntent = PendingIntent.getBroadcast(f.getApplicationContext(), aNotificationCode,                                                            lIntent, PendingIntent.FLAG_UPDATE_CURRENT);      AlarmManager lAlarmMgr = (AlarmManager) f.getSystemService(Context.ALARM_SERVICE);     lAlarmMgr.set(AlarmManager.RTC, 1000, lPendIntent); } 

This is the receiver code:

public class LocalNotificationReceiver extends BroadcastReceiver {  public static native void   nativeReceiveLocalNotification (String aID, String aTitle, String aMessage, boolean aOnForeground );  /** This method receives the alarms set by LocalNotificationScheduler, *   notifies the CAndroidNotifications c++ class, and (if needed) ships a notification banner  */ @Override public void onReceive(Context aContext, Intent aIntent) {     Toast.makeText(context, text, duration).show(); } 

}

Android manifest:

<receiver android:name="com.category.localnotifications.LocalNotificationReceiver">         <intent-filter>             <action android:name="${applicationId}.action.LOCAL_NOTIFICATION" />             <category android:name="com.category.LocalNotification" />         </intent-filter>     </receiver> 
like image 375
Hug Avatar asked Aug 22 '17 11:08

Hug


People also ask

What is Broadcastreceiver Android?

A broadcast receiver (receiver) is an Android component which allows you to register for system or application events. All registered receivers for an event are notified by the Android runtime once this event happens.

What is the life cycle of Broadcastreceiver in Android?

A BroadcastReciever life cycle ends (ie stop receiving broadcast) when you unregister it.

What is the role of the onReceive () method in the Broadcastreceiver?

Retrieve the current result extra data, as set by the previous receiver. This can be called by an application in onReceive(Context, Intent) to allow it to keep the broadcast active after returning from that function.


2 Answers

Android O are pretty new to-date. Hence, I try to digest and provide as accurate possible information.

From https://developer.android.com/about/versions/oreo/background.html#broadcasts

  • Apps that target Android 8.0 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest.
    • Apps can use Context.registerReceiver() at runtime to register a receiver for any broadcast, whether implicit or explicit.
  • Apps can continue to register explicit broadcasts in their manifest.

Also, in https://developer.android.com/training/scheduling/alarms.html , the examples are using explicit broadcast, and doesn't mention anything special regarding Android O.


May I suggest you try out explicit broadcast as follow?

public static void startAlarmBroadcastReceiver(Context context, long delay) {     Intent _intent = new Intent(context, AlarmBroadcastReceiver.class);     PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, _intent, 0);     AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);     // Remove any previous pending intent.     alarmManager.cancel(pendingIntent);     alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent);         } 

AlarmBroadcastReceiver

public class AlarmBroadcastReceiver extends BroadcastReceiver {       @Override     public void onReceive(Context context, Intent intent) {     }  } 

In AndroidManifest, just define the class as

<receiver android:name="org.yccheok.AlarmBroadcastReceiver" > </receiver> 
like image 160
Cheok Yan Cheng Avatar answered Oct 01 '22 03:10

Cheok Yan Cheng


Today i had the same problem and my notification was not working. I thought Alarm manager is not working in Oreo but the issue was with Notification. In Oreo we need to add Channel id. Please have a look into my new code:

int notifyID = 1;  String CHANNEL_ID = "your_name";// The id of the channel.  CharSequence name = getString(R.string.channel_name);// The user-visible name of the channel. int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance); // Create a notification and set the notification channel. Notification notification = new Notification.Builder(HomeActivity.this)             .setContentTitle("Your title")             .setContentText("Your message")             .setSmallIcon(R.drawable.notification)             .setChannelId(CHANNEL_ID)             .build(); 

Check this solution. It worked like charm.

https://stackoverflow.com/a/43093261/4698320

I am showing my method:

public static void pendingListNotification(Context context, String totalCount) {         String CHANNEL_ID = "your_name";// The id of the channel.         CharSequence name = context.getResources().getString(R.string.app_name);// The user-visible name of the channel.         int importance = NotificationManager.IMPORTANCE_HIGH;         NotificationCompat.Builder mBuilder;          Intent notificationIntent = new Intent(context, HomeActivity.class);         Bundle bundle = new Bundle();         bundle.putString(AppConstant.PENDING_NOTIFICATION, AppConstant.TRUE);//PENDING_NOTIFICATION TRUE         notificationIntent.putExtras(bundle);          notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);          PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);          NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);          if (android.os.Build.VERSION.SDK_INT >= 26) {             NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);             mNotificationManager.createNotificationChannel(mChannel);             mBuilder = new NotificationCompat.Builder(context) //                .setContentText("4")                     .setSmallIcon(R.mipmap.logo)                     .setPriority(Notification.PRIORITY_HIGH)                     .setLights(Color.RED, 300, 300)                     .setChannelId(CHANNEL_ID)                     .setContentTitle(context.getResources().getString(R.string.yankee));         } else {             mBuilder = new NotificationCompat.Builder(context) //                .setContentText("4")                     .setSmallIcon(R.mipmap.logo)                     .setPriority(Notification.PRIORITY_HIGH)                     .setLights(Color.RED, 300, 300)                     .setContentTitle(context.getResources().getString(R.string.yankee));         }          mBuilder.setContentIntent(contentIntent);          int defaults = 0;         defaults = defaults | Notification.DEFAULT_LIGHTS;         defaults = defaults | Notification.DEFAULT_VIBRATE;         defaults = defaults | Notification.DEFAULT_SOUND;          mBuilder.setDefaults(defaults);         mBuilder.setContentText(context.getResources().getString(R.string.you_have) + " " + totalCount + " " + context.getResources().getString(R.string.new_pending_delivery));//You have new pending delivery.         mBuilder.setAutoCancel(true);         mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());     } 
like image 20
Däñish Shärmà Avatar answered Oct 01 '22 02:10

Däñish Shärmà