6

I have built a chat application . It is working fine . both users can chat easily but where I get Stuck is if one user's app is at background and screen is off , user is unable to be notified of that received message.

What I want now is in my application is when userA sends message to userB , and userB mobile is idle but application is running in background, userB can get notification about that message. and userB can open the chat activity and read the message .

My firebase notification is working from firebase console but I don't know how to call instance id and send that to particular device from api and particular user get notification about the received message , when application screen is off and application is running in background state . How should I achieve it?

I have my firebase instance id service class here:

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
    private static final String TAG = "MyFirebaseIIDService";

    @Override
    public void onTokenRefresh() {

        //Getting registration token
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();

        //Displaying token on logcat
        Log.d(TAG, "Refreshed token: " + refreshedToken);
    }

    private void sendRegistrationToServer(String token) {
        //You can implement this method to store the token on your server
        //Not required for current project
    }
}

Here is my MyFirebase Messaging Service Class

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        if (remoteMessage.getNotification().getBody() != null) {
            Log.e("FIREBASE", "Message Notification Body: " + remoteMessage.getNotification().getBody());
            sendNotification(remoteMessage);
        }
    }

    private void sendNotification(RemoteMessage remoteMessage) {
        RemoteMessage.Notification notification = remoteMessage.getNotification();
        Intent intent = new Intent(this, LoggedInView.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.first_aid))
                .setSmallIcon(R.drawable.first_aid)
                .setContentTitle(notification.getTitle())
                .setContentText(notification.getBody())
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0, notificationBuilder.build());
    }
}

Here is my chat Activity:

public class Chat extends AppCompatActivity {
    LinearLayout layout;
    ImageView sendButton,vidcall;
    EditText messageArea;
    ScrollView scrollView;
    Firebase reference1, reference2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_chat);

        layout = (LinearLayout)findViewById(R.id.layout1);
        sendButton = (ImageView)findViewById(R.id.sendButton);
        vidcall = (ImageView)findViewById(R.id.vidBtnk);
        messageArea = (EditText)findViewById(R.id.messageArea);
        scrollView = (ScrollView)findViewById(R.id.scrollView);

        Firebase.setAndroidContext(this);
        reference1 = new Firebase("https://*******.firebaseio.com/messages/" + UserDetails.username + "_" + UserDetails.chatWith);
        reference2 = new Firebase("https://*******.firebaseio.com/messages/" + UserDetails.chatWith + "_" + UserDetails.username);

        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String messageText = messageArea.getText().toString();

                if(!messageText.equals("")){
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("message", messageText);
                    map.put("user", UserDetails.username);
                    reference1.push().setValue(map);
                    reference2.push().setValue(map);
                }
                messageArea.setText("");
            }
        });

        vidcall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                startActivity(new Intent(Chat.this, ConnectActivity.class));



            }
        });

        reference1.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                Map map = dataSnapshot.getValue(Map.class);
                String message = map.get("message").toString();
                String userName = map.get("user").toString();

                if(userName.equals(UserDetails.username)){
                    addMessageBox("You:-\n" + message, 1);
                }
                else{
                    addMessageBox(UserDetails.chatWith + ":-\n" + message, 2);
                }
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {

            }
        });
    }


   // boolean doubleBackToExitPressedOnce = false;

    @Override
    public void onBackPressed() {

        AlertDialog.Builder builder1 = new AlertDialog.Builder(Chat.this);
        builder1.setMessage("CAUTION! -> Do Wish to End this Session");
        builder1.setCancelable(true);
        builder1.setPositiveButton(
                "Yes",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                        finish();

                        dialog.cancel();
                    }
                });

        builder1.setNegativeButton(
                "No",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });

        AlertDialog alert11 = builder1.create();
        alert11.show();


    }


    public void addMessageBox(String message, int type){
        TextView textView = new TextView(Chat.this);
        textView.setText(message);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lp.setMargins(0, 0, 0, 10);
        textView.setLayoutParams(lp);

        if(type == 1) {
            textView.setBackgroundResource(R.drawable.rounded_corner1);
        }
        else{
            textView.setBackgroundResource(R.drawable.rounded_corner2);
        }

        layout.addView(textView);
        scrollView.fullScroll(View.FOCUS_DOWN);
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Addi.Star
  • 475
  • 2
  • 15
  • 36

4 Answers4

19

You need a service running on background to catch the PUSH notification and show it to the user, and that's what the Firebase Notification Service provides you with. I have this one (you'll have to modify it in order to do what you want to do when a notification is showed up):

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        if (remoteMessage.getNotification().getBody() != null) {
            Log.e("FIREBASE", "Message Notification Body: " + remoteMessage.getNotification().getBody());
            sendNotification(remoteMessage);
        }
    }

    private void sendNotification(RemoteMessage remoteMessage) {
        RemoteMessage.Notification notification = remoteMessage.getNotification();
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.logo_gris))
                .setSmallIcon(R.drawable.logo_gris)
                .setContentTitle(notification.getTitle())
                .setContentText(notification.getBody())
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0, notificationBuilder.build());
    }


}
Nahue
  • 320
  • 2
  • 18
  • I have no idea how to integrate firebase notification service into my current running chat application , can you provide any complete example or tutorial . – Addi.Star Jan 19 '17 at 23:14
  • ok i tried yor solution and able to recieve notification from firebase console , but i want to integrate it in my chat class – Addi.Star Jan 19 '17 at 23:51
  • What do you want it to do? – Nahue Jan 20 '17 at 18:45
  • See my chat.java class . In this class i send/recieve text messages . now when one user mobile screen is off or application is in background . user should get notified about the incoming message and so that one can click open it to read the message . – Addi.Star Jan 20 '17 at 20:53
  • how should i call notification from api and send it to particular user and detect weather the application screen is off and app is in background – Addi.Star Jan 20 '17 at 20:54
  • till now i know that instance id token is used to send firebase notification for particular user device . and with that token we can build mechanism for notification from api . but i didn't found any working example or tutorial to integrate it in my chat.java class – Addi.Star Jan 20 '17 at 20:56
  • NotificationCompat.Builder(this) was was depreciated, you can use NotificationCompat.Builder(this, channelId) instead. At example at https://github.com/firebase/quickstart-android/blob/14b5e47b8af5e7019bdba94c2e6969a2c58c0165/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/java/MyFirebaseMessagingService.java#L58-L101 – yaircarreno Aug 12 '21 at 18:26
0

I solved this problem may it help someone ,

In order to send Notification of firebase through api to single device is as follows:

1: generate Instance Id , unique for every device

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";

@Override
public void onTokenRefresh() {

    //Getting registration token
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();

    //Displaying token on logcat
    Log.d(TAG, "Refreshed token: " + refreshedToken);

    sendRegistrationToServer(refreshedToken);

}

private void sendRegistrationToServer(String token) {
    //You can implement this method to store the token on your server
    //Not required for current project




}

}

Note: you can call Instance Id from any where in your Application Like this:

String tkn = FirebaseInstanceId.getInstance().getToken();
        Toast.makeText(Doc_users.this, "Current token ["+tkn+"]",
                Toast.LENGTH_LONG).show();
        Log.d("App", "Token ["+tkn+"]");

this token must be used to send notification to single device it is the id of the device you can store it in your firebase database

 reference.child(UserDetails.username).child("token").setValue(tokun);

2:Now You can build your logic to fetch these ids and build your request

public static String makeRequest(String id) throws JSONException {
        HttpURLConnection urlConnection;
        JSONObject json = new JSONObject();
        JSONObject info = new JSONObject();
        info.put("title", "Notification Title");   // Notification title
        info.put("body", "Notification body"); // Notification body
        info.put("sound", "mySound"); // Notification sound
        json.put("notification", info);
        json.put("to","INSTANCE ID FETCHED FOR SIGNLE DEVICE HERE");
        Log.e("deviceidkey==> ",id+"");
        Log.e("jsonn==> ",json.toString());
        String data = json.toString();
        String result = null;
        try {
            //Connect
            urlConnection = (HttpURLConnection) ((new URL("https://fcm.googleapis.com/fcm/send").openConnection()));
            urlConnection.setDoOutput(true);
            urlConnection.setRequestProperty("Content-Type", "application/json");
            urlConnection.setRequestProperty("Authorization", "key=YOUR FIREBASE SERVER KEY");
            urlConnection.setRequestMethod("POST");
            urlConnection.connect();

            //Write
            OutputStream outputStream = urlConnection.getOutputStream();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
            writer.write(data);
            writer.close();
            outputStream.close();

            //Read
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));

            String line = null;
            StringBuilder sb = new StringBuilder();

            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line);
            }

            bufferedReader.close();
            result = sb.toString();

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

Notification will generate on that single device sent from your device you can debug to put your own device key and use postman for valid request: Good Luck

Addi.Star
  • 475
  • 2
  • 15
  • 36
0

Hi I had implemented chat application using firebase messaging.

Here the steps you can implement

1) Implement sendRegistrationToServer(String token) { Make Async call to store token generated in the backend server (map user with token generated) }

2) In Chat Activity sendmessage() should message to server to secondUser()

3) By Looking at usertoken we should push notification from backend server to firebase server.

4) Implement onMessageReceived() to show notification

Aravind Rapuru
  • 161
  • 1
  • 3
0

You need to set click_action in firebase notification data set to be able to receive data from background and implement onMessageReceived to handle foreground data

See updated answer here: https://stackoverflow.com/a/73724040/7904082

Akinyemi Jamiu
  • 431
  • 3
  • 10