I have download notification in my application. I've added "Cancel" button to NotificationCompat.Builder by calling addAction() method. But button not working on Android O device. When I press "Cancel" button nothing happens. But button working on Android < O.
My Notification:
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, channelId)
.setContentTitle(title)
.setSmallIcon(R.drawable.network_download)
.setContentText(contentText)
.setOngoing(true)
.setContentIntent(null)
.addExtras(idBundle)
.addAction(R.drawable.cancel, context.getString(R.string.cancel), getCancelPendingIntent(context, id))
.setProgress(100, 30, true);
My PendingIntent :
private PendingIntent getCancelPendingIntent(Context context, int id){
return PendingIntent.getBroadcast(
context, id, new Intent("CANCEL_DOWNLOAD").putExtra("id", id), PendingIntent.FLAG_UPDATE_CURRENT);
}
Also I have NotificationReceiver :
public static class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("CANCEL_DOWNLOAD".equals(action) && context != null){
int id = intent.getIntExtra("id", -1);
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (mgr != null)
mgr.cancel(id);
FtpManager.getInstance(new AppExecutors(), CredentialsManager.getInstance().getCredentials(context))
.cancelDownloading();
}
}
}
In Manifest file I have :
<receiver
android:name="eu.warble.pjapp.util.NotificationsManager$NotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="CANCEL_DOWNLOAD" />
</intent-filter>
</receiver>
Never use an implicit Intent when an explicit Intent will do. Android O helps enforce this by banning the receipt of implicit Intent broadcasts from manifest-registered receivers.
Step #1: Remove the <intent-filter> from your <receiver> (which also means that you could get rid of android:exported="false", as that is now the default value)
Step #2: Replace new Intent("CANCEL_DOWNLOAD").putExtra("id", id) with new Intent(context, NotificationReceiver.class).putExtra("id", id)
Thank you very much CommonsWare. It works for me. This is my code
var notifyIntent = Intent(context, NotificationBroadcastReceiver::class.java)
notifyIntent.action = "ACTION_UPDATE_BADGE"//hardcode in manifest
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
// only for oreo and newer versions
notifyIntent = Intent(context, NotificationBroadcastReceiverAndroidO::class.java)
}
val pendingIntent = PendingIntent.getBroadcast(context, it, notifyIntent, PendingIntent.FLAG_ONE_SHOT)
In manifest
<receiver android:name=".firebase.NotificationBroadcastReceiver">
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>
</receiver>
<receiver android:name=".firebase.NotificationBroadcastReceiverAndroidO">
<!--Android O not working when having this code
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>-->
</receiver>
Create 2 classes:
open class NotificationBroadcastReceiver : BroadcastReceiver() {...}
open class NotificationBroadcastReceiverAndroidO : NotificationBroadcastReceiver() {/*do nothing*/}
Related
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.
I have download notification in my application. I've added "Cancel" button to NotificationCompat.Builder by calling addAction() method. But button not working on Android O device. When I press "Cancel" button nothing happens. But button working on Android < O.
My Notification:
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, channelId)
.setContentTitle(title)
.setSmallIcon(R.drawable.network_download)
.setContentText(contentText)
.setOngoing(true)
.setContentIntent(null)
.addExtras(idBundle)
.addAction(R.drawable.cancel, context.getString(R.string.cancel), getCancelPendingIntent(context, id))
.setProgress(100, 30, true);
My PendingIntent :
private PendingIntent getCancelPendingIntent(Context context, int id){
return PendingIntent.getBroadcast(
context, id, new Intent("CANCEL_DOWNLOAD").putExtra("id", id), PendingIntent.FLAG_UPDATE_CURRENT);
}
Also I have NotificationReceiver :
public static class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("CANCEL_DOWNLOAD".equals(action) && context != null){
int id = intent.getIntExtra("id", -1);
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (mgr != null)
mgr.cancel(id);
FtpManager.getInstance(new AppExecutors(), CredentialsManager.getInstance().getCredentials(context))
.cancelDownloading();
}
}
}
In Manifest file I have :
<receiver
android:name="eu.warble.pjapp.util.NotificationsManager$NotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="CANCEL_DOWNLOAD" />
</intent-filter>
</receiver>
Never use an implicit Intent when an explicit Intent will do. Android O helps enforce this by banning the receipt of implicit Intent broadcasts from manifest-registered receivers.
Step #1: Remove the <intent-filter> from your <receiver> (which also means that you could get rid of android:exported="false", as that is now the default value)
Step #2: Replace new Intent("CANCEL_DOWNLOAD").putExtra("id", id) with new Intent(context, NotificationReceiver.class).putExtra("id", id)
Thank you very much CommonsWare. It works for me. This is my code
var notifyIntent = Intent(context, NotificationBroadcastReceiver::class.java)
notifyIntent.action = "ACTION_UPDATE_BADGE"//hardcode in manifest
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
// only for oreo and newer versions
notifyIntent = Intent(context, NotificationBroadcastReceiverAndroidO::class.java)
}
val pendingIntent = PendingIntent.getBroadcast(context, it, notifyIntent, PendingIntent.FLAG_ONE_SHOT)
In manifest
<receiver android:name=".firebase.NotificationBroadcastReceiver">
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>
</receiver>
<receiver android:name=".firebase.NotificationBroadcastReceiverAndroidO">
<!--Android O not working when having this code
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>-->
</receiver>
Create 2 classes:
open class NotificationBroadcastReceiver : BroadcastReceiver() {...}
open class NotificationBroadcastReceiverAndroidO : NotificationBroadcastReceiver() {/*do nothing*/}
I have download notification in my application. I've added "Cancel" button to NotificationCompat.Builder by calling addAction() method. But button not working on Android O device. When I press "Cancel" button nothing happens. But button working on Android < O.
My Notification:
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, channelId)
.setContentTitle(title)
.setSmallIcon(R.drawable.network_download)
.setContentText(contentText)
.setOngoing(true)
.setContentIntent(null)
.addExtras(idBundle)
.addAction(R.drawable.cancel, context.getString(R.string.cancel), getCancelPendingIntent(context, id))
.setProgress(100, 30, true);
My PendingIntent :
private PendingIntent getCancelPendingIntent(Context context, int id){
return PendingIntent.getBroadcast(
context, id, new Intent("CANCEL_DOWNLOAD").putExtra("id", id), PendingIntent.FLAG_UPDATE_CURRENT);
}
Also I have NotificationReceiver :
public static class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("CANCEL_DOWNLOAD".equals(action) && context != null){
int id = intent.getIntExtra("id", -1);
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (mgr != null)
mgr.cancel(id);
FtpManager.getInstance(new AppExecutors(), CredentialsManager.getInstance().getCredentials(context))
.cancelDownloading();
}
}
}
In Manifest file I have :
<receiver
android:name="eu.warble.pjapp.util.NotificationsManager$NotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="CANCEL_DOWNLOAD" />
</intent-filter>
</receiver>
Never use an implicit Intent when an explicit Intent will do. Android O helps enforce this by banning the receipt of implicit Intent broadcasts from manifest-registered receivers.
Step #1: Remove the <intent-filter> from your <receiver> (which also means that you could get rid of android:exported="false", as that is now the default value)
Step #2: Replace new Intent("CANCEL_DOWNLOAD").putExtra("id", id) with new Intent(context, NotificationReceiver.class).putExtra("id", id)
Thank you very much CommonsWare. It works for me. This is my code
var notifyIntent = Intent(context, NotificationBroadcastReceiver::class.java)
notifyIntent.action = "ACTION_UPDATE_BADGE"//hardcode in manifest
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
// only for oreo and newer versions
notifyIntent = Intent(context, NotificationBroadcastReceiverAndroidO::class.java)
}
val pendingIntent = PendingIntent.getBroadcast(context, it, notifyIntent, PendingIntent.FLAG_ONE_SHOT)
In manifest
<receiver android:name=".firebase.NotificationBroadcastReceiver">
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>
</receiver>
<receiver android:name=".firebase.NotificationBroadcastReceiverAndroidO">
<!--Android O not working when having this code
<intent-filter>
<action android:name="ACTION_UPDATE_BADGE" />
</intent-filter>-->
</receiver>
Create 2 classes:
open class NotificationBroadcastReceiver : BroadcastReceiver() {...}
open class NotificationBroadcastReceiverAndroidO : NotificationBroadcastReceiver() {/*do nothing*/}
I have a notification that have an action "Open Dial". I want when I click on "Open dial" action. My notification will disappear and Dial will appear.
I tried setAutocancel(true) and set notification.flags = Notification.FLAG_AUTO_CANCEL but these not working.
I know that I can't use SetAutocancel and set Flag_Auto_Cancel when I set action for my notification. If i want do that, I must use cancel(id) function of NotificationManager.
My idea to do that is sending an IntentFilter and using BroadcastReceiver to receive it When "Open Dial" is clicked.
But I don't know how I can do that because Intent.Action_Dial is an activity. If I use PendingIntent.getBroacast(), functions in onReceive() of Broadcast will work, but Dial won't show. Anyone know how I can resolve this problem ?.
This is my notication:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("Notification");
builder.setContentText("This is notification");
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setTicker("This is ticker");
Intent intent = new Intent(Intent.ACTION_DIAL);
PendingIntent pendingIntent = PendingIntent.getActivity(this, MSG_B, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.mipmap.ic_launcher, "Dial", pendingIntent);
builder.setAutoCancel(true);
Notification notification = builder.build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager manager = (NotificationManager)this.getSystemService(NOTIFICATION_SERVICE);
manager.notify(id, notification);
this is my receiver
NotificationCompat.Builder builder;
Notification notification;
NotificationManager manager;
#Override
public void onReceive(Context context, Intent intent) {
manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(intent.getAction().equals("download")){
Log.d("LOG","Download");
showNotify(3, context);
DownloadFileFromURL downloadFileFromURL = new DownloadFileFromURL();
downloadFileFromURL.execute("http://freebigpictures.com/wp-content/uploads/2009/09/river-edge.jpg");
}
else if(intent.getAction().equals("android.intent.action.DIAL")){
Log.d("LOG", "cacel Dial");
manager.cancel(NotificationServices.MSG_B);
}
else if(intent.getAction().equals("cancelActivity")){
Log.d("LOG","cacel Activity");
manager.cancel(NotificationServices.MSG_B);
}
else {
Log.d("LOG","Fail ABC");
}
}
This is mainifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".activity.MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".services.NotificationServices"
android:enabled="true"
android:exported="true">
</service>
<receiver android:name=".broadcast.BroadcastReceiverImage">
<intent-filter>
<action android:name="download"/>
<action android:name="cancelDial"/>
<action android:name="cancelActivity"/>
<action android:name="android.intent.action.DIAL"></action>
</intent-filter>
</receiver>
</application>
The solution is to start the Activity in the BroadcastReceiver, after cancelling the Notification. Here is the code for the PendingIntent:
Intent intent = new Intent();
intent.setAction("cancelDial");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, MSG_B, intent, PendingIntent.FLAG_UPDATE_CURRENT);
and the code for the BroadcastReceiver:
else if(intent.getAction().equals("cancelDial")){
Log.d("LOG", "Cancel Dial");
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
manager.cancel(NotificationServices.MSG_B);
}
Hopefully it will help someone in the future.
After a Push Notification is received, I want to open an Àctivity when the Notification is pressed.
Here are my Services:
public class GCMIntentService extends GcmListenerService {
#Override
public void onMessageReceived(String from, Bundle data) {
String title = data.getString("title");
String message = data.getString("message");
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(message)
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setTicker(message)
.setAutoCancel(true);
mBuilder.setDefaults(Notification.DEFAULT_LIGHTS);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
Intent myIntent = new Intent(this, MyActivity.class);
PendingIntent intent2 = PendingIntent.getBroadcast(this, 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(intent2);
notificationManager.notify(1, mBuilder.build());
}
public class GCMIDListenerService extends InstanceIDListenerService {
#Override
public void onTokenRefresh() {
InstanceID instanceID = InstanceID.getInstance(this);
String token;
try {
token = instanceID.getToken(Resources.getSystem().getString(R.string.gcm_defaultSenderId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
} catch (IOException e) {
e.printStackTrace();
}
//TODO:send token to the server
}
}
I just did everything following the Google documentation. I implemented that feature for another project sometime ago but it was a bit different, I used my own 'BroadcastReceiver' instead of the 'com.google.android.gms.gcm.GcmReceiver' provides by Google.
Here is my Manifest:
<application>
...
<!-- GCM Push Notifications Config -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="gcm" />
</intent-filter>
</receiver>
<service
android:name=".push.GCMIntentService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".push.GCMIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
</application>
Any ideas? Am I missing something?
Here some documentation I have follow:
Google official documentation
CGM tutorial By Dustin Rothwell
And of course I have researched a lot here at stackoverflow.
Thanks!
You have done one minor mistake. You are writing this code for opening activity.
PendingIntent intent2 = PendingIntent.getBroadcast(this, 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(intent2);
As you want to open activity you need to create pending intent using getActivity method instead of getBroadcast method.
Hope this will help.