I've looked fairly extensively across a wide range of terminology ("banner", "pop down", "notification type") and I can't seem to find clarity on what I 'think' is a very common issue. So if there is a very obvious solution I missed due to my lack of terminology please advice.
The problem is this:
I want an Android notification to appear as a "banner" that drops down from the top of the screen (if banner is the wrong word for this please advise). I went through the Docs and didn't seem to across a setting that toggles this behaviour. Here is an example of what I would like:
I have the notification working but it currently only showing up inside the drawer. It's not popping down from the drawer (which is what I want).
Here is my code, if you can advise how I can make it also appear as a banner I would greatly appreciate it:
public void createNotification(Context context, Bundle extras)
{
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String appName = getAppName(this);
Intent notificationIntent = new Intent(this, PushHandlerActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.putExtra("pushBundle", extras);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
int defaults = Notification.DEFAULT_ALL;
if (extras.getString("defaults") != null) {
try {
defaults = Integer.parseInt(extras.getString("defaults"));
} catch (NumberFormatException e) {}
}
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setDefaults(defaults)
.setSmallIcon(context.getApplicationInfo().icon)
.setWhen(System.currentTimeMillis())
.setContentTitle("NotificationTitle")
.setTicker(extras.getString("title"))
.setContentIntent(contentIntent)
.setAutoCancel(true);
String messageJson = extras.getString("data");
JSONObject parsed;
String message = null;
try {
parsed = new JSONObject(messageJson);
message = parsed.getString("message");
} catch (JSONException e) {
e.printStackTrace();
}
if (message != null) {
mBuilder.setContentText(message);
} else {
mBuilder.setContentText("Notification");
}
String msgcnt = extras.getString("msgcnt");
if (msgcnt != null) {
mBuilder.setNumber(Integer.parseInt(msgcnt));
}
int notId = 0;
try {
notId = Integer.parseInt(extras.getString("notId"));
}
catch(NumberFormatException e) {
Log.e(TAG, "Number format exception - Error parsing Notification ID: " + e.getMessage());
}
catch(Exception e) {
Log.e(TAG, "Number format exception - Error parsing Notification ID" + e.getMessage());
}
mNotificationManager.notify((String) appName, notId, mBuilder.build());
}
See: http://developer.android.com/design/patterns/notifications.html
You want a Heads-Up Notifications. This requires you to set the priority with the Notifications Builder (.setPriority) to high or max.
http://developer.android.com/design/patterns/notifications.html#correctly_set_and_manage_notification_priority
The app in background basically doesn't call onMessageReceived() method.
Only when notification doesn't have notification key, the app in background call onMessageReceived() method.
So, do not use notification key.
{
"to": "/topics/notice",
"notification": {
"title": "title",
"body": "body"
},
"data": {
"url": "https://your-url.dev"
}
}
only use data key.
{
"to": "/topics/notice",
"data": {
"title": "title",
"body": "body"
"url": "https://your-url.dev"
}
}
And set priority to max.
notificationBuilder.setContentTitle(title)
// ...
.setPriority(NotificationCompat.PRIORITY_MAX)
// ...
;
Then, you'll archive what you want.
Orion Granatir is right.
For Xamarin.Android developers, here is the code:
//Create the notification
var notification = new Notification(Resource.Drawable.icon, title);
//Auto-cancel will remove the notification once the user touches it
notification.Flags = NotificationFlags.AutoCancel;
notification.Sound = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
notification.Defaults = NotificationDefaults.Vibrate | NotificationDefaults.Lights;
notification.BigContentView = new Android.Widget.RemoteViews(AppSettings.Instance.PackageName, Resource.Layout.notification_template_big_media);
notification.LargeIcon = BitmapFactory.DecodeResource(Resources, Resource.Drawable.icon);
notification.Priority = (int)Android.App.NotificationPriority.Max;//A notification that is at least Notification.PriorityHigh is more likely to be presented as a heads-up notification.
You basically need to understand how WindowManager works.
You get the
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
then you want to get the root view and use the method addView(view, params) if you want to add a view.
Take a look at this cool article, which might help your use case.
Related
I need to don't receive notifications when my app is killed but I have not found any code that does.
I can receive notifications in foreground and background but they still arrive when I kill the app.
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
try {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getData().get("body"));
}
catch (Exception e){
}
}
//The message which i send will have keys named [message, image, AnotherActivity] and corresponding values.
//You can change as per the requirement.
try {
//message will contain the Push Message
String message = remoteMessage.getData().get("body");
//imageUri will contain URL of the image to be displayed with Notification
String imageUri = remoteMessage.getData().get("image");
String titulo = remoteMessage.getData().get("title");
String sidusuario = remoteMessage.getData().get("sidusuario");
String idnotificacionusuario = remoteMessage.getData().get("idnotificacionusuario");
sendNotification(message, imageUri,titulo);
}
catch (Exception e){
e.printStackTrace();
}
}
This is my sendNotification method
void sendNotification(String messageBody, String icon, String titulo)
{
String channelId = "General";
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setLargeIcon(getBitmapFromURL(icon))
.setContentTitle(titulo)
.setSmallIcon(R.drawable.logo_blanco_chapur)
.setContentText(messageBody)
.setStyle(new NotificationCompat.BigTextStyle())
.setAutoCancel(true)
.setSound(defaultSoundUri);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(getID(), notificationBuilder.build());
}
{
"to": "token",
"notification": {
"title": "title",
"body": "****body****.",
"mutable_content": true
},
"data": {
"url": "https://upload.wikimedia.org/wikipedia/commons/8/80/Coiled_Galaxy.jpg",
"title": "title",
"body": "****body****."
}
}
It maybe duplicates here. Important: if the app is in background or killed then to be received a notification the payload have to remove the notification property
My Android application gets firebase notifications. And I need to localize this notifications depends on application language on the client side, not on server side.
If application is in foreground I use onMessageReceived() from FirebaseMessagingService and push my own localized notification. But if application is in background onMessageReceived() doesn't called.
In this case I use my own class extended BroadcastReceiver. onReceive(Context context, Intent intent) method catches notification, I localize it and push. Everything goes good, but in the end I get 2 push notifications: my own localized and firebase.
How can I get rid of this firebase notification and get only my own?
public class FirebaseDataReceiver extends BroadcastReceiver {
Context context;
PendingIntent pendingIntent;
public void onReceive(Context context, Intent intent) {
this.context = context;
Bundle dataBundle = intent.getExtras();
String title = "";
String body = "";
String type = "";
String objectId = "";
if (dataBundle != null) {
type = dataBundle.getString("type");
objectId = dataBundle.getString("objectId");
title = NotificationUtils.getNotificationTitle(context, dataBundle);
body = NotificationUtils.getNotificationBody(context, dataBundle);
}
Intent newIntent = new Intent(context, TutorialActivity_.class);
newIntent.putExtra("target", "notification");
newIntent.putExtra("type", type);
newIntent.putExtra("objectId", objectId);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
pendingIntent = PendingIntent.getActivity(context,
0,
newIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(body)
.setPriority(Notification.PRIORITY_HIGH)
.setDefaults(Notification.DEFAULT_ALL)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setSmallIcon(R.drawable.splash_mini)
.build();
deleteLastNotification();
NotificationManagerCompat.from(context).notify(0, notification);
}
}
You should really use Data notifications from the server. Normal message notifications can't achieve this behaviour you're looking for. Check out the docs here:https://firebase.google.com/docs/cloud-messaging/concept-options
So your request to Firebase from the server should look something like this:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}
Instead of:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
}
}
}
I am sending push notification from google firebase for my android app with target of Android 5.0:
My push notification code is:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String badge = "0";
Uri uri = Uri.parse(
getString(R.string.app_host_name)
);
Map<String, String> data = remoteMessage.getData();
if (data.size() > 0) {
try {
uri = Uri.parse(
data.get("link")
);
badge = data.get("badge");
} catch (NullPointerException e) {
//
}
}
if (remoteMessage.getNotification() != null) {
RemoteMessage.Notification notification = remoteMessage.getNotification();
sendNotification(notification.getTitle(), notification.getBody(), uri.toString(), badge);
}
}
private void sendNotification(String title, String body, String url, String badge) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (Patterns.WEB_URL.matcher(url).matches()) {
intent.putExtra("link", url);
}
PendingIntent pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
);
Resources resources = getApplicationContext().getResources();
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, "default")
.setColor(
resources.getColor(R.color.colorPrimaryDark)
)
.setSmallIcon(
R.drawable.ic_stat_icon
)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setNumber(Integer.parseInt(badge))
.setLargeIcon(
BitmapFactory.decodeResource(
resources,
R.mipmap.ic_launcher
)
)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= 26) {
NotificationChannel notificationChannel = new NotificationChannel(
"default",
"Main notification channel",
NotificationManager.IMPORTANCE_HIGH
);
notificationManager.createNotificationChannel(
notificationChannel
);
}
notificationManager.notify(
1,
notificationBuilder.build()
);
}
And everything is super perfect when application is active/opened/not in background, but when it is not, notifications are not grouped, there is no number displayed, and no reaction on all of this settings at all, what i was able to change is only small icon and circle color via manifest settings
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_icon" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorPrimaryDark" />
but why? It's like when app is in background notifications are not using settings from Activity code but using only some kind of "default" one from AndroidManifest.
As you said in the comments:
when app is on background, app isn't taking setNumber, setAutoCancel, setSmallIcon, setLargeIcon options
It is because you are using notification payload to send the notification which only triggers on the foreground.
So when your app is in the background it does not enter this method.
to solve this you can use data payload alone:
"data": {
"titles": "New Title",
"bodys": "body here"
}
since the data payload will enter the onMessageReceived() when your app is in foreground/background.
then in fcm you can do this:
if (remoteMessage.getData().size() > 0) {
title = remoteMessage.getData().get("titles");
body = remoteMessage.getData().get("bodys");
}
I need help. As I wrote in title , I don't know how to keep data from notification when it arrives and the application is in background or killed. What i need to pass ( code below) is a Plate that i need for an elaboration . Here is the code:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String text= remoteMessage.getNotification().getBody();
SharedPreferences s = getSharedPreferences(Constants.PREFS_NAME, Context.MODE_PRIVATE);
Functions.putStringInPrefs(s, Constants.PREFS_ALERT_PLATE, text);
if (Functions.isUserSignedUp(this)) {
if (remoteMessage.getNotification() != null) {
// Log.d(TAG, "Message Title:" + remoteMessage.getNotification().getTitle());
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
try {
sendNotification(remoteMessage.getNotification());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void sendNotification(RemoteMessage.Notification notification) {
Intent intent = new Intent(this, FragmentChangeActivity.class);
String prova = notification.getBody();
intent.putExtra("alert_plate" , prova);
GlobalData.alertPlate=prova; // object used as cache
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if(notification.getTitle()!= null){
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.details_icon).setContentTitle(notification.getTitle());
} else{
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.details_icon).setContentTitle(getString(R.string.app_name));
}
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.details_icon).setContentText(notification.getBody())
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(new Random().nextInt((100000000 - 1) + 1) + 1, new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.details_icon).build());
}
}
What do I need to change ? Thank you !
Ps. In manifest the class is declared in the correct way .
There are two types of FCM messages
1) Notification message
2) Data message
So if you want to receive data when the app is close you have to send your data using data message. Your data format will be something look like below
{
"to": "device_id",
"data": {
"param_1": "vale 1",
"param_2": "value 2",
"param_3": "Value 3"
}
}
After receiving the message now you can store your data in shared preference or database whatever you want.
I received the response from the server and I parsed that response in the android now I have to set the Notification Title and Text from that response. I means from that particular function.
Here I am putting my ParseList() function here where i parsed my response.
private void parseList(Bundle bundle) {
String id,name,photo,updates;
try {
JSONObject json = new JSONObject();
Set<String> keys = bundle.keySet();
for (String key : keys) {
try {
json.put(key, bundle.get(key));
} catch (JSONException e) {
e.printStackTrace();
}
}
JSONArray jsonarray = new JSONArray(json.getString("response"));
Log.e("","Hi"+jsonarray);
for (int i = 0; i < jsonarray.length(); i++) {
JSONObject jsonObjectmain = jsonarray .getJSONObject(i);
JSONArray array = jsonObjectmain.getJSONArray("updates");
for (int j = 0; j < array.length(); j++) {
JSONObject jsonObject = array.getJSONObject(j);
id = jsonObject.getString("id").toString();
name = jsonObject.getString("name").toString();
photo = jsonObject.getString("photo").toString();
updates = jsonObject.getString("updates").toString();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
There is a parameter called name,updates and photo. Now i have to setup the Notification Title from this response How can i set up that thing.. ?
I have onMessage() method with me but how can i put that values into that. ??
Here is my onMessage() method for Notification...
#Override
protected void onMessage(Context context, Intent data) {
String message;
message = data.getExtras().getString("name");
Intent intent = new Intent(this, MyActivity.class);
parseList(data.getExtras());
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setWhen(System.currentTimeMillis())
.setContentTitle(message)
.setContentText(message).setContentIntent(pIntent)
.getNotification();
notification.defaults |= Notification.DEFAULT_SOUND;
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(R.string.app_name, notification);
{
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
final PowerManager.WakeLock mWakelock = pm.newWakeLock(
PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP, "GCM_PUSH");
mWakelock.acquire();
notification.defaults|=Notification.DEFAULT_VIBRATE;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
mWakelock.release();
}
};
timer.schedule(task, 5000);
}
}
first your notification message must contains the values in different keys.
array( "title" => $title, "message" => $message )
the above code is php server side sample array data which is actually being added to 'data' key and then the data is sent to applications using the different servers. I have used GCM and while receiving data from server message get the above key data from bundle.
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setWhen(System.currentTimeMillis())
.setContentTitle(title)
.setContentText(message).setContentIntent(pIntent)
.getNotification();
here you can check that setContentTitle is used to add "title" and setContentText is the "subTitle" or message
You should use NotificationCompat.Builder to set the title, icon, content etc. for a notification. Here's an example:
private NotificationCompat.Builder mBuilder;
mBuilder = new NotificationCompat.Builder(
this).setSmallIcon(R.drawable.whitelogo)
.setLargeIcon(anImage)
.setContentTitle(title); //set smallIcon,largeIcon, contentTitle for your notification.
and to add the notification :
Notification.Builder notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setWhen(System.currentTimeMillis())
.setContentTitle(message)
.setContentText(message)
.setContentIntent(pIntent);
notificationManager.notify(NOTIFICATION_ID_NOTIF, notification.build());
UPDATE
It's not working in your case because, there's no String with key name in your bundle, so this will return null :
message = data.getExtras().getString("name");
so move your notification code in the parseList method, as there you have already extracted all the values (id,name,photo,updates).