android fcm notification not received and while the device which supposed to receivethe notification shows this message in Logcat (Received from FCM TITLE: null, Received from FCM BODY: null). I have already checked that notification is not being received in both <26 and >26 SDK Versions
====================MyFirebaseMessagingService===============================
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String channel_id = "the_id";
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.e("NEW_TOKEN",s);
updateTokenToFirebase(s);
}
private void updateTokenToFirebase(String token) {
IDrinkShopAPI mService = Common.getAPI();
mService.updateToken("SERVER_01",token,"0")
.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.d("DEBUG_TOKEN",response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.d("DEBUG_TOKEN",t.getMessage());
}
});
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if(remoteMessage.getData() != null){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
sendNotification26(remoteMessage);
else
sendNotification(remoteMessage);
}
}
private void sendNotification26(RemoteMessage remoteMessage) {
Map<String,String> data = remoteMessage.getData();
String title = data.get("title");
String message = data.get("message");
NotificationHelper helper ;
Notification.Builder builder;
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
helper = new NotificationHelper(this);
builder = helper.getDrinkShopNotification(title,message,defaultSoundUri);
helper.getManager().notify(new Random().nextInt(),builder.build());
}
private void sendNotification(RemoteMessage remoteMessage) {
Map<String,String> data = remoteMessage.getData();
String title = data.get("title");
String message = data.get("message");
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri);
NotificationManager mn =(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
mn.notify(new Random().nextInt(),builder.build());
}
}
=========================NotificationHelper =================================
//this class is used to implement notification for all android versions
public class NotificationHelper extends ContextWrapper {
private static final String CHANNEL_ID = "the_id";
private static final String CHANNEL_NAME = "Drink_Shop";
private NotificationManager notificationManager;
public NotificationHelper(Context base) {
super(base);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
createChannel();
}
#TargetApi(Build.VERSION_CODES.O)
private void createChannel() {
NotificationChannel nc = new NotificationChannel(CHANNEL_ID,CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT);
nc.enableLights(false);
nc.enableVibration(true);
nc.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
getManager().createNotificationChannel(nc);
}
public NotificationManager getManager() {
if(notificationManager == null)
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
return notificationManager;
}
#TargetApi(Build.VERSION_CODES.O)
public Notification.Builder getDrinkShopNotification(String title,
String message,
Uri soundUri)
{
return new Notification.Builder(getApplicationContext(),CHANNEL_ID)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.mipmap.ic_launcher)
.setSound(soundUri)
.setChannelId(CHANNEL_ID)
.setAutoCancel(true);
}
}
=============================Manifest=======================================
<service
android:name=".Services.MyFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
============================Build.gradle====================================
implementation 'com.google.firebase:firebase-messaging:20.0.0'
implementation 'com.google.firebase:firebase-core:17.2.1'
implementation 'com.google.android.gms:play-services-auth:17.0.0'
===========================IFCMService=======================================
public interface IFCMService {
#Headers({
"Content-Type:application/json",
"Authorization:mytoken"
})
#POST("fcm/send")
Call<MyResponse> sendNotification(#Body DataMessage body);
}
==========================sendNotificationToServer===============================
// this method used to send the notification to server device
private void sendNotificationToServer(OrderResult orderResult) {
mService.getToken("SERVER_01", "1")
.enqueue(new Callback<Token>() {
#Override
public void onResponse(Call<Token> call, Response<Token> response) {
Map<String,String> contentSend = new HashMap<>();
contentSend.put("title","NEW ORDER");
contentSend.put("message","You have got new order" + orderResult.getOrderId());
DataMessage dataMessage = new DataMessage();
if(response.body().getToken() != null)
dataMessage.setTo(response.body().getToken());
dataMessage.setData(contentSend);
IFCMService ifcmService = Common.getFCMService();
ifcmService.sendNotification(dataMessage)
.enqueue(new Callback<MyResponse>() {
#Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
if(response.code() == 200){
if(response.body().success == 1){
Toast.makeText(CartActivity.this,
getResources().getString(R.string.order_submitted), Toast.LENGTH_SHORT)
.show();
//Clear Carts From Room Database
Common.cartRepository.emptyCart();
//finish();
}
else {
Toast.makeText(CartActivity.this, "Send Notification Failed", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<MyResponse> call, Throwable t) {
Toast.makeText(CartActivity.this, ""+t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onFailure(Call<Token> call, Throwable t) {
Toast.makeText(CartActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
I have solved this issue by downgrading firebase-messaging library as follow (implementation 'com.google.firebase:firebase-messaging:17.3.4') as will as .setColor(ContextCompat.getColor(this, R.color.colorAccent)) in NotificationCompat. However this has solved the issue for me for SDK version lower than 26. Anyone knows why it is still cashing on APIs higher than 26 ?! help me please
When the App is running in background the notification is received in the system tray, and when is tapped, the intent is sended to your activity default, with the notification with payload of content of it.
When your application is running in front, the notification is received with the FirebaseMessagingService and the logic that you overrided.
I think you should add the logic of the first point, when the app is running in background
Check here more information
Handling messages
Related
I am trying to make a chatting app in android studio. All the basic functions are done but I have been struggling with a problem for a time. The problem is sending notification to a device. I have searched the web a lot and was finally successful when a error came by the code is given below.
sendNotification function
private void sendNoti(String senderId, String receiverId){
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("to", "/User/"+receiverId);
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("title", "Message from " + senderId);
jsonObject1.put("body", "hello");
jsonObject.put("notification", jsonObject1);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, jsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e("SUCCESS", response + "");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("ERRORS", error + "");
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> map = new HashMap<>();
map.put("content-type", "application/json");
map.put("authorization", "key=key");
Log.d("Maping",map.toString());
return map;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
int socketTimeout = 1000 * 60;// 60 seconds
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
request.setRetryPolicy(policy);
requestQueue.add(request);
} catch (JSONException e) {
e.printStackTrace();
}
}
MyFirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(#NonNull #NotNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(remoteMessage);
}
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.e("newToken", s);
getSharedPreferences("_", MODE_PRIVATE).edit().putString("fb", s).apply();
System.out.println("Token "+s);
}
private void sendNotification(RemoteMessage remoteMessage) {
String user = remoteMessage.getData().get("from");
String title = remoteMessage.getData().get("title");
String body = remoteMessage.getData().get("body");
System.out.println("user "+user);
System.out.println("title "+title);
System.out.println("body "+body);
Intent intent = new Intent(this, MainActivity.class);
String channel_id = "notification_channel";
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder builder = new NotificationCompat
.Builder(getApplicationContext(), channel_id)
.setSmallIcon(R.drawable.vroo)
.setContentTitle(title)
.setContentText("body")
.setAutoCancel(true)
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000})
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(channel_id, "web_app", NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(notificationChannel);
}
notificationManager.notify(0, builder.build());
}
}
I get the log output that my message is sent but I never receive it on the receiver side can someone please help me?
I am building an android firebase chat app that doesn't require a server setup, I've already built everything for it and found a couple of YouTube tutorials on how to do what I'm having trouble with right now, I'm trying to get the app itself to send a push notification to the device its sending the message to, I'm using Volley to send the notification, the problem that I'm facing is the other device is not getting or showing the notification, can you please tell me what I'm doing wrong and how to fix it?
build.gradle
implementation 'com.google.firebase:firebase-auth:20.0.4'
implementation 'com.google.firebase:firebase-database:19.7.0'
implementation platform('com.google.firebase:firebase-bom:27.0.0')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-messaging:20.0.1'
implementation 'com.android.volley:volley:1.1.1'
AndroidManifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
...
<service
android:name=".MyFirebaseMessagingService"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
MyFirebaseInstanceIDService
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "mFirebaseIIDService";
#Override
public void onTokenRefresh() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
final String token = FirebaseInstanceId.getInstance().getToken();
FirebaseInstallations.getInstance().getToken(false)
.addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
#Override
public void onComplete(#NonNull Task<InstallationTokenResult> task) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
FirebaseMessaging.getInstance().subscribeToTopic(user.getUid());
Log.i("TAG", "onTokenRefresh completed with token: " + task.getResult().getToken());
}
});
}
}
MyFirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private final String ADMIN_CHANNEL_ID = "admin_channel";
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
final Intent intent = new Intent(this, MainActivity.class);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int notificationID = new Random().nextInt(85-65);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
setupChannels(notificationManager);
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this , 0, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, ADMIN_CHANNEL_ID)
.setContentTitle(remoteMessage.getData().get("title"))
.setContentText(remoteMessage.getData().get("message"))
.setAutoCancel(true)
.setSound(notificationSoundUri)
.setContentIntent(pendingIntent);
notificationManager.notify(notificationID, notificationBuilder.build());
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void setupChannels(NotificationManager notificationManager){
CharSequence adminChannelName = "New notification";
String adminChannelDescription = "Device to device notification";
NotificationChannel adminChannel;
adminChannel = new NotificationChannel(ADMIN_CHANNEL_ID, adminChannelName, NotificationManager.IMPORTANCE_HIGH);
adminChannel.setDescription(adminChannelDescription);
adminChannel.enableLights(true);
adminChannel.setLightColor(Color.RED);
adminChannel.enableVibration(true);
if (notificationManager != null) {
notificationManager.createNotificationChannel(adminChannel);
}
}
}
MessageActivity
final private String FCM_API = "https://fcm.googleapis.com/fcm/send";
final private String serverKey = "key=MY_KEY";
final private String contentType = "application/json";
final String TAG = "NOTIFICATION TAG";
...
sendBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String msg = msg_editText.getText().toString();
if (!msg.equals("")) {
sendMessage(fuser.getUid(), userid, msg);
JSONObject notification = getStructure(fuser.getUid(), userid, msg);
sendNotification(notification);
}
msg_editText.setText("");
}
});
...
private JSONObject getStructure(String senderId, String receiverId, String msg) {
JSONObject notification = new JSONObject();
JSONObject notificationBody = new JSONObject();
try {
notificationBody.put("title", "App Test");
notificationBody.put("message", "This is a test notification from the app");
notification.put("to", "/topics/" + receiverId);
notification.put("data", notificationBody);
} catch (JSONException e) {
e.printStackTrace();
}
return notification;
}
...
private void sendNotification(JSONObject notification) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(FCM_API, notification,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i(TAG, "onResponse: " + response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MessageActivity.this, "Request error", Toast.LENGTH_SHORT).show();
Log.i(TAG, "onErrorResponse: Didn't work");
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Authorization", serverKey);
params.put("Content-Type", contentType);
return params;
}
};
MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjectRequest);
}
MySingleton
public class MySingleton {
private static MySingleton instance;
private RequestQueue requestQueue;
private Context ctx;
public MySingleton(Context ctx) {
this.ctx = ctx;
requestQueue = getRequestQueue();
}
public static synchronized MySingleton getInstance(Context context) {
if (instance == null) {
instance = new MySingleton(context);
}
return instance;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
return requestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
}
I have the following FirebaseMessagingService which works fine when I get a push notification and the app is in foreground:
public class _FCMService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getData().size() > 0) {
// Log.i(TAG, "PUSH PAYLOAD: " + remoteMessage.getData());
JSONObject pushData = new JSONObject(remoteMessage.getData());
pushType = pushData.optString("pushType");
pushMessage = pushData.optString("body");
Log.i(TAG, "ON PUSH RECEIVED - pushType: " + pushType);
Log.i(TAG, "ON PUSH RECEIVED - pushMessage: " + pushMessage);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentText(pushMessage)
.setStyle(new NotificationCompat.BigTextStyle())
.setAutoCancel(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setSound(defaultSoundUri);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert notificationManager != null;
notificationManager.notify(0 , notificationBuilder.build());
}
}
#Override
public void onNewToken(#NotNull String token) {
Log.i(TAG, "Refreshed token: " + token);
ANDROID_DEVICE_TOKEN = token;
}
}
So, If I receive a push, the Logcat prints out the notification's body and (if present) the pushType string.
What I would need to do is to make my other Activity update data when push is received, as well as get the pushMessage and pushType strings.
I know how to do that in iOS Swift - by using NotificationCenter - but have no idea about Android, I've tried LocalBroadcaster, but no success.
LocalBroadcastManager is now deprecated!
You can use LiveData implementation in a static reference and observe it in the Activity or Fragment
public class NotificationService extends FirebaseMessagingService {
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Notification.
getInstance().
addOrder(remoteMessage.getData().get("id"));
}
public static class Notification {
private static Notification instance;
private MutableLiveData<String> newOrder;
private Notification() {
newOrder = new MutableLiveData<>();
}
public static Notification getInstance() {
if(instance == null){
instance = new Notification();
}
return instance;
}
public LiveData<String> getNewOrder() {
return newOrder;
}
public void addOrder(String orderID){
newOrder.postValue(orderID);
}
}
}
And In the Activity or Fragment:
NotificationService.
Notification.
getInstance().
getNewOrder().
observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(String s) {
//TODO: update your ui here...
}
});
You can add a .setContentIntent(NotificationChannelUtil.createPendingIntent(this, pushMessage, pushType)) to your notificaitionBuilder.
Where that function is inside an util class like:
public class NotificationChannelUtil {
private NotificationChannelUtil() {}
public static PendingIntent createPendingIntent(Context context, String pushMessage, String pushType) {
Intent intent = new Intent(context, YourWantedActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("pushMessage", pushMessage);
intent.putExtra("pushType", pushType);
return PendingIntent.getActivity(context, 0 /* request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
}
}
I've found a solution to my issue, which actually looks similar to the iOS NotificationCenter instance. I've added this class into my _FCMService.java file:
class NotificationCenter {
private static NotificationCenter _instance;
private HashMap<String, ArrayList<Runnable>> registredObjects;
private NotificationCenter(){
registredObjects = new HashMap<>();
}
//returning the reference
static synchronized NotificationCenter defaultCenter(){
if(_instance == null)
_instance = new NotificationCenter();
return _instance;
}
synchronized void addFunctionForNotification(String notificationName, Runnable r){
ArrayList<Runnable> list = registredObjects.get(notificationName);
if(list == null) {
list = new ArrayList<Runnable>();
registredObjects.put(notificationName, list);
}
list.add(r);
}
public synchronized void removeFunctionForNotification(String notificationName, Runnable r){
ArrayList<Runnable> list = registredObjects.get(notificationName);
if(list != null) {
list.remove(r);
}
}
synchronized void postNotification(String notificationName){
ArrayList<Runnable> list = registredObjects.get(notificationName);
if(list != null) {
for(Runnable r: list)
r.run();
}
}
}
Then I've called it inside the onMessageReceived() function:
NotificationCenter.defaultCenter().postNotification("pushNotif");
Lastly, I've added the observer into the onStart() function of my Activity as it follows:
#Override
protected void onStart() {
super.onStart();
// Start NotificationCenter to observe for new messages
NotificationCenter.defaultCenter().addFunctionForNotification("pushNotif", new Runnable() {
#Override
public void run() {
Log.i(TAG, "Obj Details -> pushMessage: " + pushMessage + "\npushType" + pushType);
}});
}
It works smoothly, hoper this helps somebody else.
Android fcm notification is being received on android with APIs lower than 26 however APIs 26(Oreo 8.0) it doesn't and it cause app to be crashed
====================MyFirebaseMessagingService===============================
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String channel_id = "the_id";
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.e("NEW_TOKEN",s);
updateTokenToFirebase(s);
}
private void updateTokenToFirebase(String token) {
IDrinkShopAPI mService = Common.getAPI();
mService.updateToken("SERVER_01",token,"0")
.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.d("DEBUG_TOKEN",response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.d("DEBUG_TOKEN",t.getMessage());
}
});
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if(remoteMessage.getData() != null){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
sendNotification26(remoteMessage);
else
sendNotification(remoteMessage);
}
}
private void sendNotification26(RemoteMessage remoteMessage) {
Map<String,String> data = remoteMessage.getData();
String title = data.get("title");
String message = data.get("message");
NotificationHelper helper ;
Notification.Builder builder;
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
helper = new NotificationHelper(this);
builder = helper.getDrinkShopNotification(title,message,defaultSoundUri);
helper.getManager().notify(new Random().nextInt(),builder.build());
}
private void sendNotification(RemoteMessage remoteMessage) {
Map<String,String> data = remoteMessage.getData();
String title = data.get("title");
String message = data.get("message");
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setSound(defaultSoundUri);
NotificationManager mn =(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
mn.notify(new Random().nextInt(),builder.build());
}
}
=========================NotificationHelper =================================
//this class is used to implement notification for APIs 26+
public class NotificationHelper extends ContextWrapper {
private static final String CHANNEL_ID = "the_id";
private static final String CHANNEL_NAME = "Drink_Shop";
private NotificationManager notificationManager;
public NotificationHelper(Context base) {
super(base);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
createChannel();
}
#TargetApi(Build.VERSION_CODES.O)
private void createChannel() {
NotificationChannel nc = new NotificationChannel(CHANNEL_ID,CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT);
nc.enableLights(false);
nc.enableVibration(true);
nc.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
getManager().createNotificationChannel(nc);
}
public NotificationManager getManager() {
if(notificationManager == null)
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
return notificationManager;
}
#TargetApi(Build.VERSION_CODES.O)
public Notification.Builder getDrinkShopNotification(String title,
String message,
Uri soundUri)
{
return new Notification.Builder(getApplicationContext(),CHANNEL_ID)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.mipmap.ic_launcher)
.setSound(soundUri)
.setChannelId(CHANNEL_ID)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setAutoCancel(true);
}
}
=============================Manifest=======================================
<service
android:name=".Services.MyFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
============================Build.gradle====================================
implementation 'com.google.firebase:firebase-messaging:20.0.0'
implementation 'com.google.firebase:firebase-core:17.2.1'
implementation 'com.google.android.gms:play-services-auth:17.0.0'
===========================IFCMService=======================================
public interface IFCMService {
#Headers({
"Content-Type:application/json",
"Authorization:mytoken"
})
#POST("fcm/send")
Call<MyResponse> sendNotification(#Body DataMessage body);
}
==========================sendNotificationToServer===============================
// this method used to send the notification to server app
private void sendNotificationToServer(OrderResult orderResult) {
mService.getToken("SERVER_01", "1")
.enqueue(new Callback<Token>() {
#Override
public void onResponse(Call<Token> call, Response<Token> response) {
Map<String,String> contentSend = new HashMap<>();
contentSend.put("title","NEW ORDER");
contentSend.put("message","You have got new order" + orderResult.getOrderId());
DataMessage dataMessage = new DataMessage();
if(response.body().getToken() != null)
dataMessage.setTo(response.body().getToken());
dataMessage.setData(contentSend);
IFCMService ifcmService = Common.getFCMService();
ifcmService.sendNotification(dataMessage)
.enqueue(new Callback<MyResponse>() {
#Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
if(response.code() == 200){
if(response.body().success == 1){
Toast.makeText(CartActivity.this,
getResources().getString(R.string.order_submitted), Toast.LENGTH_SHORT)
.show();
//Clear Carts From Room Database
Common.cartRepository.emptyCart();
//finish();
}
else {
Toast.makeText(CartActivity.this, "Send Notification Failed", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<MyResponse> call, Throwable t) {
Toast.makeText(CartActivity.this, ""+t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onFailure(Call<Token> call, Throwable t) {
Toast.makeText(CartActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
I think you are making the code unnecessarily complicated.
Try this below code
private void createNotification(String title, String message) {
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// only create notification channel if SDK >= 26
if (android.os.Build.VERSION.SDK_INT >= 26) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(false);
channel.enableVibration(true);
channel.setDescription(CHANNEL_DESC);
manager.createNotificationChannel(channel);
}
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(android.R.drawable.stat_notify_more)
.setContentTitle(title)
.setSmallIcon(R.mipmap.ic_launcher)
.setSound(defaultSoundUri)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setContentText(message);
manager.notify(new Random().nextInt(), builder.build());
}
I have a chat app and I'm trying to display a notification to the user once a new message is received.
Once I launch the activity I call onStart as follows:
#Override
protected void onStart() {
super.onStart();
popNotification();
}
popNotification is a class that is called in order to check if there was any update in my database. If yes, I call another class called AddNotification()
public void popNotification() {
db.collection("Users").document(auth.getUid()).collection("MyChats")
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value,
#Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.w("", "Listen failed.", e);
return;
}
for (QueryDocumentSnapshot doc : value) {
if (doc.getId() != null) {
DocumentReference docRef = db.collection("Users").document(auth.getUid()).collection("MyChats").document(doc.getId());
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
if(document.getLong("LastMessageTime") > document.getLong("lastChatVisited")){
AddNotification();
}
} else {
Log.d("", "No such document");
}
} else {
Log.d("", "get failed with ", task.getException());
}
}
});
}
}
}
});
}
and AddNotification():
private void AddNotification(){
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w("", "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
try {
String title = "TEST ";
MyTaskParams params = new MyTaskParams(token, title, "TTT!");
MyTask myTask = new MyTask();
myTask.execute(params);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
One last thing is the mytask which is:
private class MyTask extends AsyncTask<MyTaskParams, Void, Void> {
#Override
protected Void doInBackground(MyTaskParams... params) {
String userDeviceIdKey = params[0].url;
String title = params[0].title;
String body = params[0].body;
String authKey = "XXX"; // You FCM AUTH key
String FMCurl = "https://fcm.googleapis.com/fcm/send";
URL url;
try {
url = new URL(FMCurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization","key="+authKey);
conn.setRequestProperty("Content-Type","application/json");
JSONObject json = new JSONObject();
json.put("to",userDeviceIdKey);
json.put("priority","high");
JSONObject info = new JSONObject();
info.put("title", title); // Notification title
info.put("body", body); // Notification body
json.put("data", info);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(json.toString());
wr.flush();
conn.getInputStream();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
Now, the problem is that I don't receive any notification.
I inserted Logs in order to check if the code runs there and it seems to pass all the required functions however still it doesn't show anything.
I added priority = high because I read it might affect but it didn't help.
My message class is:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getData().get("body"));
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "29358305")
.setSmallIcon(R.drawable.ic_launcher_custom_background)
.setContentTitle(remoteMessage.getData().get("title"))
.setContentText(remoteMessage.getData().get("body"))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(remoteMessage.getData().get("body")))
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(),
R.mipmap.ic_launcher))
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
//createNotificationChannel();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(235345305, builder.build());
}
}
EDIT:
I also tried to use the following when creating the notification without any improvement:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getData().get("body"));
createNotificationChannel();
notifyThis(remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
}
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "ABC";
String description = "ABCDE";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel("191919", name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
public void notifyThis(String title, String message) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, "191919")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(0, mBuilder.build());
}
Do I also need to add onPause or something else for it to work or do I have some other bug that I cant understand?
Thank you