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);
}
}