Good day, I hope the question is understood, as you can see I am trying to send a notification to a specific user depending on an action, let me explain:
I have an order application in which the user places his order, then that order reaches the administrator, the administrator can finish the order when it is ready, once this is done, the client receives the notification that his order is already finished and he can pass it on to pick, so this is where the problem lies I have been reading a lot of documentation and I have seen many videos but I see that to send a notification to a specific user they enter the console ofFirebase
and they put the user token in the configuration and proceed to send the message, so for what I need it is obviously not correct since I have to send the notification automatically when the administrator completes the request, I have found an implementation where the notification is sent to all users who have the application installed and I have tried to adapt it so that I send it to a single user using their token, now I will proceed to show what I have so far:
The first thing I do is get the token
user's:
private void obtenerToken() {
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
if (!task.isSuccessful()){
Log.w("TAG", "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
String token = task.getResult();
// Log and toast
String msg = "El token es el siguiente:" + token;
Log.d("TAG", msg);
Toast.makeText(Login.this, msg, Toast.LENGTH_SHORT).show();
}
});
}
I have this code in my main class so that said token is obtained from the input, then I plan to store it in my database MySQL
and every time the user "logs in" that token is updated in my database in case on occasion the user deletes data, uninstalls, etc...
Then the administrator enters the application with his privileges when there are new orders for this I have created a Recyclerview
where I get the orders from MySQL
usingPHP
Inside my adapter class I have my class llamarTopico()
where I customize my message
RequestQueue myrequest= Volley.newRequestQueue(cContext);
JSONObject json = new JSONObject();
try {
String url_foto="";
json.put("to","/topics/"+"enviaratodos");
JSONObject notificacion=new JSONObject();
notificacion.put("titulo", "Tu pedido ya esta listo");
notificacion.put("detalle","¡Ya puedes recoger tu pedido en el restaurante");
notificacion.put("foto",url_foto);
json.put("data",notificacion);
String URL="https://fcm.googleapis.com/fcm/send";
JsonObjectRequest request=new JsonObjectRequest(Request.Method.POST,URL,json,null,null){
@Override
public Map<String, String> getHeaders() {
Map<String,String>header=new HashMap<>();
header.put("content-type","application/json");
header.put("authorization","key=AAAA4_Ez5Uc:APA91bGikOqTotdNVNpNsCKX3g5f0582UT1JKGFlgumT0NvHKydOC8aVxU7B6PGh0GIhHW-N_rDhVSnyGtuyDQSL1J_xDR8rKbJG2899OGA_I1RUE0oRlM5fvmoY0v84KjWxCkoCwgUb");
return header;
}
};
myrequest.add(request);
}catch (JSONException e){
e.printStackTrace();
}
}
In this part there are 3 things to clarify:
1) When the user finishes the order, the clear method is executed in my database, the order has already been updated to finished, therefore there would be no problem when sending the notification in the hypothetical case that the code works as I need it.
2) I thought that if I changed the key of the line header.put("authorization","key=
for my token, the message would be sent precisely to the device of that token, but apparently this is not the case and I have to use my token in another place, that key that I just mentioned is the server key i get from firebase.
3) I have discovered that I can pass the token as a parameter in this line json.put("to","/topics/"+"enviaratodos");
so I have tried to create a String variable token = "my token"; and pass it as a parameter in the json
json.put("to","/topics/"+token);
however it does not send the notification
Something worth adding is that depending on the implementation I'm guided by, this method is created:
FirebaseMessaging.getInstance().subscribeToTopic("enviaratodos").addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
Toast.makeText(cContext,"Registrado",Toast.LENGTH_SHORT).show();
}
});
If you realize the parameter that is passed to subscribeTopic()
is the string that has the json parameterjson.put("to","/topics/"+"enviaratodos");
Finally I have my clear FMC that to be honest and because I am new to the subject I have not finished understanding its functionality:
public class Fcm extends FirebaseMessagingService {
@Override
public void onNewToken(@NonNull String s) {
super.onNewToken(s);
Log.e("token","mi token es:"+s);
}
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String from =remoteMessage.getFrom();
if (remoteMessage.getData().size()>0){
String titulo=remoteMessage.getData().get("titulo");
String detalle=remoteMessage.getData().get("detalle");
String foto=remoteMessage.getData().get("foto");
mayorqueoreo(titulo,detalle,foto);
}
}
private void mayorqueoreo(String titulo, String detalle, String foto) {
String id="mensaje";
NotificationManager nm=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder=new NotificationCompat.Builder(this,id);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel nc=new NotificationChannel(id,"nuevo", NotificationManager.IMPORTANCE_HIGH);
nc.setShowBadge(true);
assert nm!=null;
nm.createNotificationChannel(nc);
}
try {
Bitmap imf_foto= Picasso.get().load(foto).get();
builder.setAutoCancel(true)
.setWhen(System.currentTimeMillis())
.setContentTitle(titulo)
.setSmallIcon(R.drawable.logotaqueria)
.setContentText(detalle)
.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(imf_foto).bigLargeIcon(null))
.setContentIntent(clicknoti())
.setContentInfo("nuevo");
Random random=new Random();
int idNotity =random.nextInt(8000);
assert nm !=null;
nm.notify(idNotity,builder.build());
} catch (IOException e) {
e.printStackTrace();
}
}
public PendingIntent clicknoti(){
Intent nf=new Intent(getApplicationContext(), ObtenerReportes.class);
nf.putExtra("color","rojo");
nf.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
return PendingIntent.getActivity(this,0,nf,0);
}
}
But this is the class we use is Manifest
as follows:
<service
android:name=".Fcm"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
I've updated my question based on new research and new code I've found!
And well I think that would be all the code is a bit exhaustive but I think it is necessary I hope everything is understood if you have any questions or need more code please let me know as well I appreciate if someone improves the question by updating it thank you very much in advance.
According to what you say:
The problem is that if you register the user you get a token but this token must be generated when using the "sendall" topic in this case!
To ensure that you subscribe correctly to the topic (topic) you can use the validation of
Task
:Firstly, ensure the above since the problem is probably when making the subscription.
Now to send the notification your code is correct, you are going to send the notification to all the users who are subscribed to the topic "enviaratodos" :
You can send notification to a user using his token ,
In the case of sending a notification to users subscribed to a topic, what you should do is register the user with
topic
it in this wayin this way the notification will reach all subscribed users, this would be the complete code of your method
You were close when you tried
json.put("to","/topics/"+token);
. The correct way to send the notification to the user is by passing the token like this:json.put("to",token);
Now, some additional information: