I have add the below code in another app, but not working here
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "<<!!>>";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
sendNotification("notication");
}
#Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
sendRegistrationToServer(token);
}
private void scheduleJob() {
// [START dispatch_job]
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(MyWorker.class)
.build();
WorkManager.getInstance().beginWith(work).enqueue();
// [END dispatch_job]
}
private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
}
}
Related
I am creating a BloodBank app in which, when the user requests for the blood, It takes the requested Blood group and search the same in the database. It displays list of all the users who can donate to that blood group.
In the list, I have already implemented an option to message and call the user. Additionally, I want the App to send a notification to all users who have the same blood group.
For achieving this I have subscribed the user to a topic at successful login and sent him a notification but I have done this through the console.
What I want to achieve is, as a user requests the blood and while showing him the list of all users who can donate, App should also send a notification to all the users who have subscribed to that topic.
So is there any possible way I can programmatically send FCM to all the users subscribed to the same topic.
Here I'm subscribing user to a topic at successful Login:
firebaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
progressDialog.dismiss();
topicSubscription();
} else {
progressDialog.dismiss();
String exception = task.getException().getMessage();
HelperClass.showSnakbarMsg(rootView, exception);
}
}
});
}
private void topicSubscription() {
FirebaseMessaging.getInstance().subscribeToTopic("Blood")
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
String msg = getString(R.string.msg_subscribed);
if (!task.isSuccessful()) {
msg = getString(R.string.msg_subscribe_failed);
} else {
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
}
Log.d("log", msg);
Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
This is my Firebase messaging class:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
Log.d(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
I have read about it and many have said to hit an API for this to send FCM programmatically. But I am creating the whole app in firebase so my DataBase is also in firebase and as my database is in firebase I can't use API for one notification only like I have to manage some table in DB for that notification and for only one table I have to manage a separate DB.
So is there any way that I can send FCM programmatically to all users who have subscribed to the same topic, on successful loading of the donor list which shows the user who can donate to the requested blood group.
Thanks
You can directly send push notification directly from android, to all the devices subscribed to the topic, check out the following link how to send msgs directly from android, but in this example user is sending message one to one, to send fcm message to user subscribed to a topic, you need to change the message format as specified by fcm documentation
User App
private void latLngNotification() {
Location loc1 = new Location("");
loc1.setLatitude(Double.parseDouble(userLat));
//loc1.setLongitude();
Location loc2 = new Location("");
loc2.setLatitude(Double.parseDouble(attendanceLat));
//loc2.setLongitude();
float distanceInMeters = loc1.distanceTo(loc2);
if (distanceInMeters > 50) {
//Toast.makeText(this, "distance: " + distanceInMeters, Toast.LENGTH_SHORT).show();
sendNotification();
} else {
//Toast.makeText(this, "distance: " + distanceInMeters, Toast.LENGTH_SHORT).show();
Toast.makeText(this, "You are in home...", Toast.LENGTH_SHORT).show();
}
}
private void sendNotification() {
String TOPIC = "/topics/admin_app"; //topic has to match what the receiver subscribed to
JSONObject notification = new JSONObject();
JSONObject notifcationBody = new JSONObject();
String title = "Quarantine outside";
String message = mobileno + " User is out of his area";
try {
notifcationBody.put("title", title);
notifcationBody.put("message", message);
notification.put("to", TOPIC);
notification.put("priority", "high");
notification.put("data", notifcationBody);
} catch (JSONException e) {
Log.e(TAG, "onCreate: " + e.getMessage());
}
Notification(notification);
}
private void Notification(JSONObject notification) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("https://fcm.googleapis.com/fcm/send", notification,
response -> Log.i(TAG, "onResponse: " + response.toString()),
error -> {
Toast.makeText(GetLocationActivity.this, "Request error", Toast.LENGTH_LONG).show();
Log.i(TAG, "onErrorResponse: Didn't work");
}) {
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<>();
params.put("Authorization", "key=AAAAwxBqu5A:APA91bERpf-1rh02jLciILt1rsLv7HRrFVulMTEAJXJ5l_JGrSHf96qXvLQV0bIROob9e3xLK4VN8tWo-zBPUL39HjxyW4MsX5nKW_NiQlZGgLDCySVwHXADlg16mpLUjgASj--bk-_W");
params.put("Content-Type", "application/json");
return params;
}
};
MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjectRequest);
}
Admin App
FirebaseMessaging.getInstance().subscribeToTopic("admin_app");
Intent intent = getIntent();
if (intent != null) {
String userPhone = intent.getStringExtra("message");
//Toast.makeText(this, userPhone, Toast.LENGTH_SHORT).show();
message_txt.setVisibility(View.VISIBLE);
message_txt.setText(userPhone);
} else {
message_txt.setVisibility(View.GONE);
//Toast.makeText(this, "no data", Toast.LENGTH_SHORT).show();
}
I am always getting an error on sending notification from android device in logcat I have tried so many times but nothing getting:
{"multicast_id":5162718122421221171,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
Here is my android code for sending message I am sending userABC topic in the topic section.
public void SendNotification(String Title, String Message){
NOTIFICATION_TITLE = Title;
NOTIFICATION_MESSAGE = Message;
JSONObject notification = new JSONObject();
JSONObject notifcationBody = new JSONObject();
try {
notifcationBody.put("title", NOTIFICATION_TITLE);
notifcationBody.put("message", NOTIFICATION_MESSAGE);
notification.put("to", TOPIC);
notification.put("data", notifcationBody);
} catch (JSONException e) {
Log.e(TAG, "onCreate: " + e.getMessage() );
}
sendNotification(notification);
}
private void sendNotification(JSONObject notification) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(FCM_API, notification,
new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i(TAG, "onResponse: " + response.toString());
}
},
new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), "Request error", Toast.LENGTH_LONG).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(getActivity().getApplicationContext()).addToRequestQueue(jsonObjectRequest);
}
Here is my FirebaseInstanceIDService.java class
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "mFirebaseIIDService";
private static final String SUBSCRIBE_TO = "userABC";
#Override
public void onTokenRefresh() {
/*
This method is invoked whenever the token refreshes
OPTIONAL: If you want to send messages to this application instance
or manage this apps subscriptions on the server side,
you can send this token to your server.
*/
String token = FirebaseInstanceId.getInstance().getToken();
// Once the token is generated, subscribe to topic with the userId
FirebaseMessaging.getInstance().subscribeToTopic(SUBSCRIBE_TO);
Log.i(TAG, "onTokenRefresh completed with token: " + token);
sendRegistrationToServer(token);
}
private void sendRegistrationToServer(String token) {
// send token to web service ??
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("server/saving-data/IDs");
// then store your token ID
ref.push().setValue(token);
}
}
Here is my FirebaseMessagingService.java class
public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
private final String ADMIN_CHANNEL_ID ="admin_channel";
#Override
public void onNewToken(String token) {
Log.d("TAG", "Refreshed token: " + token);
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d("THIS", "Refreshed token: " + refreshedToken);
FirebaseMessaging.getInstance().subscribeToTopic("userABC");
sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String token) {
// send token to web service ??
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("server/saving-data/IDs");
// then store your token ID
ref.push().setValue(token);
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
final Intent intent = new Intent(this, MainActivity.class);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int notificationID = new Random().nextInt(3000);
/*
Apps targeting SDK 26 or above (Android O) must implement notification channels and add its notifications
to at least one of them. Therefore, confirm if version is Oreo or higher, then setup notification channel
*/
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);
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher);
Uri notificationSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, ADMIN_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(largeIcon)
.setContentTitle(remoteMessage.getData().get("title"))
.setContentText(remoteMessage.getData().get("message"))
.setAutoCancel(true)
.setSound(notificationSoundUri)
.setContentIntent(pendingIntent);
//Set notification color to match your app color template
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
notificationBuilder.setColor(getResources().getColor(R.color.colorPrimaryDark));
}
notificationManager.notify(notificationID, notificationBuilder.build());
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void setupChannels(NotificationManager notificationManager){
CharSequence adminChannelName = "New notification";
String adminChannelDescription = "Device to devie 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);
}
}
}
FirebaseInstanceIdService is deprecated now.
So you can change your registration logic as below
FcmRegistrationManager.java
public class FcmRegistrationManager {
private static final String TAG = "FcmRegistrationManager"
/*This is async call*/
public void registerWithFcm(){
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
Log.d(TAG, msg);
sendRegistrationToServer(token)
}
});
}
private void sendRegistrationToServer(String token) {
// send token to web service ??
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("server/saving-data/IDs");
// then store your token ID
ref.push().setValue(token);
}
}
No change for sendNotification() and FirebaseMessagingService class.
More reference : https://firebase.google.com/docs/cloud-messaging/android/client
Let me still not working, I will share you working code.
I want to retrieve my token and i'm doing exactly as many examples says
On FirebaseMessagingService i have this
#Override
public void onNewToken(String token) {
super.onNewToken(token);
Log.e("Refreshed token:",token);
}
And i got the error
Method does not override method from it's superclass
and of course the super.onNewToken(token) has the error
cannot resolve method
On my mainactivity i have this inside OnCreate()
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( MyActivity.this, new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String newToken = instanceIdResult.getToken();
}
});
And the errors i get are:
Cannot resolve getInstanceId()
Cannot resolve InstanceIdResult
cannot
resolve getToken()
and Method does not override method from it's
superclass
Update
Class declaration
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
private NotificationUtils notificationUtils;
#Override
public void onNewToken(String token) {
super.onNewToken(token);
Log.e("Refreshed token:",token);
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage == null)
return;
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody());
handleNotification(remoteMessage.getNotification().getBody());
}
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
try {
JSONObject json = new JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
}
Dependencies
implementation 'com.google.firebase:firebase-core:16.0.5'
implementation 'com.google.firebase:firebase-messaging:17.3.4'
Update v2
public class FirebaseMessagingService extends com.google.firebase.iid.zzb {
private static final java.util.Queue<java.lang.String> zzoma;
public FirebaseMessagingService() { /* compiled code */ }
#android.support.annotation.WorkerThread
public void onMessageReceived(com.google.firebase.messaging.RemoteMessage remoteMessage) { /* compiled code */ }
#android.support.annotation.WorkerThread
public void onDeletedMessages() { /* compiled code */ }
#android.support.annotation.WorkerThread
public void onMessageSent(java.lang.String s) { /* compiled code */ }
#android.support.annotation.WorkerThread
public void onSendError(java.lang.String s, java.lang.Exception e) { /* compiled code */ }
#com.google.android.gms.common.internal.Hide
protected final android.content.Intent zzp(android.content.Intent intent) { /* compiled code */ }
#com.google.android.gms.common.internal.Hide
public final boolean zzq(android.content.Intent intent) { /* compiled code */ }
#com.google.android.gms.common.internal.Hide
public final void handleIntent(android.content.Intent intent) { /* compiled code */ }
static void zzr(android.os.Bundle bundle) { /* compiled code */ }
static boolean zzal(android.os.Bundle bundle) { /* compiled code */ }
build.gradle (app):
implementation 'com.google.firebase:firebase-core:16.0.5'
implementation 'com.google.firebase:firebase-messaging:17.3.4'
extend class:
package /*package name*/;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
public class MyFcmListenerService extends FirebaseMessagingService {
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is also called
* when the Instance ID token is initially generated, so this is where
* you retrieve the token.
*/
#Override
public void onNewToken(String token) {
Log.d("TAG", "New token: " + token);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(token); //As I understand it, you need to implement it yourself.
}
}
in tag in AndroidManifest.xml:
<service
android:name=".MyFcmListenerService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Add to your activity where you want to get a token:
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(MainActivity.this, new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String newToken = instanceIdResult.getToken();
}
});
I am using FCM to send notification for downloading a file in my android app. When my app is not running and i send FCM then I get all the notifications that I send earlier and new one continuously.
How to overcome this?
Here is my MyFirebaseMessagingService class.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d("data", "onMessageReceived: firebase called");
Map<String, String> data = remoteMessage.getData();
String url = data.get("file_url");
Intent broadcast_intent = new Intent();
broadcast_intent.putExtra(MainActivity.FIREBASE_URL, url); broadcast_intent.setAction(MainActivity.FIREBASE_URL_BROADCAST);
sendBroadcast(broadcast_intent);
}
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";
#Override
public void onTokenRefresh() {
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String token) {
}
FCM Service. NotificationDatabaseHandler is helper class. Saving message title and current time.
public class ApplicationFCMService extends FirebaseMessagingService {
private static final String TAG = ApplicationFCMService.class.getName();
private NotificationUtils notificationUtils;
private NotificationDatabaseHandler databaseHandler;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.e(TAG, "From: " + remoteMessage.getFrom());
databaseHandler = new NotificationDatabaseHandler(getApplicationContext());
if (remoteMessage.getNotification() != null) {
Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody());
handleNotification(remoteMessage.getFrom(), remoteMessage.getNotification().getBody());
databaseHandler.addNotification(remoteMessage.getNotification().getBody(), getDate());
// Log.d("FCM", messagesSet.toString());
Log.d("FCM", remoteMessage.getNotification().getBody());
}
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
try {
JSONObject json = new JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
}
I've used postman to send data notifications(for testing). On reception of data message onMessageReceived() method is executed.
Now I can save notifications in database even if the app is in background.