PendingIntent.getBroadcast not working in Oreo - android

I have an app already on playstore long time ago, recently the notifications is not open with users
this is my code
private void showNotification () {
PhoneUtils.clearAllNotifications(getApplicationContext());
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = “app”;
int notificationId = 100;
createNotificationChannel(channelId , notificationManager);
Notification notification = new NotificationCompat.Builder(getApplicationContext(), channelId)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getApplicationContext().getResources().getString(R.string.app_name))
.setContentText(mAlert)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
.setContentIntent(getOpenNotificationIntent())
.setDefaults(Notification.DEFAULT_ALL)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.build();
notificationManager.notify(notificationId, notification);
}
private PendingIntent getOpenNotificationIntent () {
int requestID = (int) System.currentTimeMillis();
Intent intent = new Intent(“com.app.OPEN”);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_TYPE, mType);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_ID, mId);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_DIALOG_ID, mDialogId);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_MESSAGE_ID, mMessageId);
Notification notification = null;
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), requestID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
<receiver
android:name=".fcm.OpenNotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.app.OPEN" />
</intent-filter>
</receiver>

As of Android 8 (Oreo) you can no longer register a BroadcastReceiver for an implicit Intent in the manifest. That's what you are doing with this:
<receiver
android:name=".fcm.OpenNotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.app.OPEN" />
</intent-filter>
</receiver>
Instead of this, you should use an explicit Intent as follows:
Change the manifest entry to this:
<receiver
android:name=".fcm.OpenNotificationReceiver">
</receiver>
and change the code you use to create the PendingIntent for the Notification to this:
Intent intent = new Intent(this, OpenNotificationReceiver.class);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_TYPE, mType);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_ID, mId);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_DIALOG_ID, mDialogId);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_MESSAGE_ID, mMessageId);
Notification notification = null;
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), requestID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
For more information see https://developer.android.com/about/versions/oreo/background and search for "Broadcast limitations"

modify getOpenNotificationIntent method.
private PendingIntent getOpenNotificationIntent () {
int requestID = (int) System.currentTimeMillis();
Intent intent = new Intent(“com.app.OPEN”);
//add this line
intent.setPackage(getApplicationContext().getPackageName());
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_TYPE, mType);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_ID, mId);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_DIALOG_ID, mDialogId);
intent.putExtra(ForSaleConstants.ACTIVITY_NOTIFICATION_MESSAGE_ID, mMessageId);
Notification notification = null;
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), requestID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}

Having had issues with building for Android 12 - I thought I'd share this...
Android API version 31 (Android S) and above require any PendingIntent to have one of two flags set: FLAG_IMMUTABLE or FLAG_MUTABLE. (Android doc. 20) ServerPingWithAlarmManager.onCreate doesn’t do this, and so is throwing an IllegalArgumentException.
https://discourse.igniterealtime.org/t/android-api-31-requires-mutability-flag-for-pendingintent-serverpingwithalarmmanager-4-4-5-fails/91553
Without the Mutable or Immutable flag set PendingIntent.getBroadcast crashes.

Related

Clicking on Notification in background not open my App?

I am a newbie in android development.
I create a background service for receive pushNotification (with our own socket service, not FCM).
And now my device receive message and show notification successfully. But when I click the notification, it not return to my app.
When I click notification, show the error below:
ActivityManager: Unable to start service Intent { cmp=com.my.app/package.name.AppActivity } U=0: not found
Here is my code:
public static void setNotification(Service service, String message) {
NotificationManager manager = (NotificationManager) service.getSystemService(NOTIFICATION_SERVICE);
String appName = service.getString(R.string.app_name);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(service)
.setContentTitle(appName)
.setContentText(message)
.setContentIntent(getDefaultIntent(service))
.setWhen(System.currentTimeMillis())
.setOngoing(false)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setSmallIcon(R.drawable.icon)
.setLargeIcon(BitmapFactory.decodeResource(service.getResources(), R.drawable.icon))
.setSound(alarmSound);
Notification notification = builder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
manager.notify(1, notification);
}
private static PendingIntent getDefaultIntent(Service service) {
Intent intent = new Intent(service, AppActivity.class);
PendingIntent pendingIntent = PendingIntent.getService(service, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
return pendingIntent;
}
}
MainActivity setting in AndroidManifest.xml
<activity android:name="package.name.AppActivity" android:configChanges="orientation|screenSize" android:label="#string/app_name" android:launchMode="singleTask" android:screenOrientation="landscape" android:theme= "#android:style/Theme.NoTitleBar.Fullscreen" android:enabled="true" android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
Please guide me what I am missing or doing wrong in this code. Many thanks.
I pass same id in padding intent and manager.notify(0, notification);
And use PendingIntent.getActivity instead of PendingIntent.getService
it works!
I got the problem you only cancel the current notification thats why Intent is not firing the activity Change your Pending intent
from
PendingIntent.FLAG_CANCEL_CURRENT);
to
PendingIntent.FLAG_UPDATE_CURRENT
| PendingIntent.FLAG_ONE_SHOT);

Pending Intent opens wrong activity

I am using the FirebaseMessagingService for getting notifications and opening the app upon clickng the notification. But everytime i click the notification the app opens the MainActivity instead of the intended ResultActivity. I also followed docs from the PendingIntent docs and still does the same.
private void createNotification( String messageBody) {
Intent intent = new Intent( this , ResultActivity.class );
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent resultIntent = PendingIntent.getActivity( this , 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
// PendingIntent resultPending = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
Uri notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder( this)
.setContentTitle("VERA")
.setContentText(messageBody)
.setAutoCancel( true )
.setSound(notificationSoundURI)
.setContentIntent(resultIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, mNotificationBuilder.build());
}
Here is my Manifest.
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ResultActivity"
android:launchMode="singleTask"
android:excludeFromRecents="true"
android:taskAffinity=""></activity>
EDIT: I tried to pass some extra strings, but the main activity is not even receiving anything. Is it possible that the notif is only triggering its default method to launch the app?
Create an Intent that starts the Activity.
Set the Activity to start in a new, empty task by calling setFlags() with the flags FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TASK.
Create a PendingIntent by calling getActivity().
Like,
Intent notifyIntent = new Intent(this, ResultActivity.class);
// Set the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Create the PendingIntent
PendingIntent notifyPendingIntent = PendingIntent.getActivity(this, 0,
notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Then you can pass the PendingIntent to the notification as usual:
NotificationCompat.Builder mNotificationBuilder= new NotificationCompat.Builder(this, "CHANNEL_ID");
builder.setContentIntent(notifyPendingIntent);
...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(0, mNotificationBuilder.build());
Apparently there is no way to trigger the onMessageReceived by using the FCM console only. It will only be triggered if i use other ways to send data messages.

BroadcastReceiver does not get data from notification button

I am trying to make notification with remove button, notifications are stored in SQLite DB and after the press, I want to remove "record" by id. Firstly I get a notification, store it to db , store unique id and pass it to a method which creates a notification. It gets fine in the method.
public static String CUSTOM_ACTION = "com.example.app.Services.REMOVE";
Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(CUSTOM_ACTION);
snoozeIntent.putExtra("NOT_WORKING", String.valueOf(id));
PendingIntent snoozePendingIntent =
PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.drawable.ic_stat_bell)
.setContentTitle("Loggly")
.setContentText(messageBody)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.addAction(R.drawable.ic_delete_forever_black_24dp, "Remove", snoozePendingIntent);
then I have a broadcast receiver for handling data from notification. Here is how it looks in my manifest file.
<receiver android:name=".MyBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="com.example.app.Services.REMOVE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
And here is the broadcast receiver the value which I got from extras is always null ... I have been trying to find a solution, but with no result.
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String id;
if (extras != null) {
id = extras.getString("NOT_WORKING");
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager notificationManager = (NotificationManager) context.getSystemService(ns);
if (notificationManager != null) {
notificationManager.cancel(0);
}
Intent inten = new Intent(context, RemoveService.class);
inten.putExtra("NOT_WORKING", id);
context.startService(inten);
}
}
}
Finally, I am starting intent service, which should delete the "record" from the database, but when the broadcast receiver does not receive id it can't do anything.
I just created a sample notification on my side and the problem is the way you are creating the pendingIntent. Just add the proper flag to the pendingIntent parameter and it will work fine.
PendingIntent snoozePendingIntent = PendingIntent.getBroadcast(this, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
You can use FLAG_ONE_SHOT as well. If it satisfies your use case. You can go through different flags which can be used in PendingIntent

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

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>
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>
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());
}
Create the AlarmManager by defining an explicit intent (explicitly define the class name of the broadcast receiver):
private static PendingIntent getReminderReceiverIntent(Context context) {
Intent intent = new Intent("your_package_name.ReminderReceiver");
// create an explicit intent by defining a class
intent.setClass(context, ReminderReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
Also do not forget to create a notification channel for Android Oreo (API 26) when creating the actual notification:
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (VERSION.SDK_INT >= VERSION_CODES.O) {
notificationManager.createNotificationChannel(NotificationFactory.createNotificationChannel(context));
} else {
notificationManager.notify(NotificationsHelper.NOTIFICATION_ID_REMINDER, notificationBuilder.build());
}
try this code for android O 8.1
Intent nIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
nIntent.addCategory("android.intent.category.DEFAULT");
nIntent.putExtra("message", "test");
nIntent.setClass(this, AlarmReceiver.class);
PendingIntent broadcast = PendingIntent.getBroadcast(getAppContext(), 100, nIntent, PendingIntent.FLAG_UPDATE_CURRENT);

android notification only sound plays notification is not shown in notification drawer

i am trying to fire notification in at a particular time using AlarmManager and Notification manager. i am facing a strange problem. when notification is fired only sound plays but notification is not shown in the notification drawer.
i got an error in the log
04-26 11:32:09.217 1222-1222/? E/NotificationService﹕ WARNING: In a future release this will crash the app: com.example.shiv.selftweak
my code is .
The class which calls the AlarmManager
Intent intent1 = new Intent(this, FireNotification.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 1000, intent1, 0);
AlarmManager am = (AlarmManager)this.getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(), pendingIntent);
FireNotification class
public class FireNotification extends Service {
#Override
public void onCreate() {
Intent intent = new Intent(this, MainActivity.class);
long[] pattern = {0, 300, 0};
PendingIntent pi = PendingIntent.getActivity(this, 1234, intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setContentTitle("Self tweak")
.setContentText("Habbits are waiting for last dones")
.setVibrate(pattern)
.setAutoCancel(false);
mBuilder.setContentIntent(pi);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(false);
NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.notify(1234, mBuilder.build());
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Android Menifest
<service android:name=".FireNotification"></service>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
when notification fires only sound plays. but it is not getting shown in the notification drawer which shows no notification.
The problem is that you haven't specified mBuilder.setSmallIcon(R.drawable.ic_launcher).
Basically you have to set smallIcon, contentTitle and contentText. If you miss any of those the Notification will not be displayed at all! That's clearly specified HERE (also you can read more about notifications there as well).

Categories

Resources