Home > Back-end >  How to make app able to show notification when it is closed
How to make app able to show notification when it is closed

Time:03-01

I have included a chatting feature in my app using Firebase realtime Database. I want to be able to show notification when another user sends a message even when the app is turned but I'm not sure how

package com.example.android.crazytenmessenger;

import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.example.android.crazytenmessenger.auth.UserProfileActivity;
import com.example.android.crazytenmessenger.dao.MessageDAOHelper;
import com.example.android.crazytenmessenger.utils.DateUtils;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.OnProgressListener;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;


import java.util.ArrayList;
import java.util.List;

public class MessagingActivity extends AppCompatActivity {

    private ListView listView;
    private FloatingActionButton sendButton;
    private EditText messageEditTextBox;
    private ProgressBar progressBar;
    private ImageView imagePicker;

    private static final String TAG=MessagingActivity.class.getSimpleName();
    private static final int MAX_WORD_LIMIT = 1000;

    private DatabaseReference messageDatabaseReference;
    private FirebaseStorage firebaseStorage;
    private StorageReference chatPhotoStorageReference;
    private ChildEventListener childEventListener;
    private List<Message> messages;
    private SharedPreferences sharedPreferences;
    private String username;
    private MessageDAOHelper daoHelper;
    private MessageAdapter messageAdapter;


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

        listView=(ListView) findViewById(R.id.message_list_view);
        messageEditTextBox=(EditText) findViewById(R.id.message_box);
        sendButton=(FloatingActionButton) findViewById(R.id.send_button);
        imagePicker=(ImageView) findViewById(R.id.image_picker);
        progressBar=(ProgressBar)  findViewById(R.id.progress_Bar);

        daoHelper=new MessageDAOHelper();
        messageDatabaseReference=daoHelper.getMessageDatabaseReference();
        firebaseStorage=FirebaseStorage.getInstance();
        chatPhotoStorageReference=firebaseStorage.getReference().child("chat_photos");
        sharedPreferences= PreferenceManager.getDefaultSharedPreferences(this);

        messages=new ArrayList<>();
        loadPreviousMessages();
        messageAdapter=new MessageAdapter(this,R.layout.item_message,messages);
        listView.setAdapter(messageAdapter);
        username=FirebaseAuth.getInstance().getCurrentUser().getDisplayName();

        ActivityResultLauncher<String> mGetContent=registerForActivityResult(new ActivityResultContracts.GetContent(),
                new ActivityResultCallback<Uri>() {
            @Override
            public void onActivityResult(Uri result) {
                uploadPhoto(result);
            }
        });


        childEventListener=new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                Message currentMsg=snapshot.getValue(Message.class);
                messageAdapter.add(currentMsg);
                listView.smoothScrollToPosition(messageAdapter.getCount());
            }
            @Override
            public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) { }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot snapshot) {
                Snackbar.make(findViewById(android.R.id.content),"succesfully removed", BaseTransientBottomBar.LENGTH_SHORT).show();
                Log.v(TAG,"Removed : " snapshot.getValue());
            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) { }
            @Override
            public void onCancelled(@NonNull DatabaseError error) { }
        };

        messageEditTextBox.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if(s.toString().trim().length()>0)
                    sendButton.setEnabled(true);
                else
                    sendButton.setEnabled(false);
            }

            @Override
            public void afterTextChanged(Editable s) { }
        });

        messageEditTextBox.setFilters(new InputFilter[]{new InputFilter.LengthFilter(MAX_WORD_LIMIT)});

        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                username=sharedPreferences.getString(getString(R.string.my_profile_username_key),"USER");
                username=FirebaseAuth.getInstance().getCurrentUser().getDisplayName();
                String timeStamp= DateUtils.getCurrentTimestamp();
                Message message=new Message(messageEditTextBox.getText().toString(),username, null, timeStamp);
                daoHelper.addMessage(message).addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void unused) {

                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Snackbar.make(findViewById(android.R.id.content),"Message Not Sent " e.getMessage(), BaseTransientBottomBar.LENGTH_SHORT).show();
                    }
                });

                messageEditTextBox.setText("");
            }
        });
        imagePicker.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mGetContent.launch("image/*");
            }
        });
        messageDatabaseReference.addChildEventListener(childEventListener);
    }

    /**
     * Signing in the the current user automatically using OnStart
     * Using Firebase Auth getCurrentUser
    */

    @Override
    protected void onStart() {
        super.onStart();
        String user= FirebaseAuth.getInstance().getCurrentUser().getDisplayName();
        if(user==null)
            user="";
        Snackbar.make(findViewById(android.R.id.content),"Welcome " user,BaseTransientBottomBar.LENGTH_SHORT).show();
    }



    public void uploadPhoto(Uri uri){
        final ProgressDialog progressDialog=new ProgressDialog(this);
        progressDialog.setTitle("Uploading Image.....");
        progressDialog.show();
        StorageReference photoRef=chatPhotoStorageReference.child(uri.getLastPathSegment());
        photoRef.putFile(uri)
                .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        Task<Uri> result=taskSnapshot.getMetadata().getReference().getDownloadUrl();
                        progressDialog.dismiss();
                        result.addOnSuccessListener(new OnSuccessListener<Uri>() {
                            @Override
                            public void onSuccess(Uri uri) {
                                String timeStamp=DateUtils.getCurrentTimestamp();
                                Message newMessage=new Message(null,username,uri.toString(), timeStamp);
                                daoHelper.addMessage(newMessage);
                            }
                        });

                    }
                })
                .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onProgress(@NonNull UploadTask.TaskSnapshot snapshot) {
                        double percentage=(100.00*snapshot.getBytesTransferred() / snapshot.getTotalByteCount());
                        Log.v(TAG,"Progress : " percentage);
                        progressDialog.setMessage("Progress  : " (int)percentage "%");
                    }
                });
        Toast.makeText(this,"Image uploaded",Toast.LENGTH_SHORT).show();
    }



    private void deleteAllMessages(){
        AlertDialog dialog=new AlertDialog.Builder(this)
                .setTitle("Delete all messages")
                .setMessage("Are you sure you want to delete all messages")
                .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        Toast.makeText(getApplicationContext(),"Deleting... ",Toast.LENGTH_SHORT).show();

                        messageDatabaseReference.removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {
                            }
                        });
                        chatPhotoStorageReference.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {
                                Toast.makeText(getApplicationContext(),"All files Deleted ",Toast.LENGTH_SHORT).show();
                                messages.clear();
                                messageAdapter.notifyDataSetChanged();
                                listView.setAdapter(messageAdapter);
                                loadPreviousMessages();

                            }
                        });
                    }
                })
                .setNegativeButton(android.R.string.no,null)
                .setIcon(android.R.drawable.ic_dialog_alert)
                .show();

    }



    private void loadPreviousMessages(){
        messageDatabaseReference.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DataSnapshot> task) {
                if(!task.isSuccessful())
                    Log.e(TAG,"Error in retrieving data ",task.getException());
                else{
                    int count= (int) task.getResult().getChildrenCount();
                    if(count==0){

                        Snackbar.make(findViewById(android.R.id.content),
                                "Let's start chatting",
                                BaseTransientBottomBar.LENGTH_SHORT).show();
                        progressBar.setVisibility(View.GONE);
                        return;
                    }
                    progressBar.setVisibility(View.GONE);
                }
            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        int id=item.getItemId();
        if(id==R.id.profile_menu){
            Intent intent=new Intent(MessagingActivity.this, UserProfileActivity.class);
            startActivity(intent);
        }else if(id==R.id.delete_all_option){
            deleteAllMessages();
        }else if(id==R.id.signout){
            signoutCurrentUser();
        }
        return super.onOptionsItemSelected(item);
    }



    private void signoutCurrentUser() {
        FirebaseAuth.getInstance().signOut();
        finish();
    }
}

I used child event listeners on firebase database reference to know the message sent but how to use it for notification.

CodePudding user response:

You should use FCM for targeting the notification.

Whenever a message is sent(data inserted in the Firebase DB) you need to pull the data from DB and send a notification to the particular device using registration ID of the device.

The FCM notifaction should be a data type(user defined payload) if you wish your app to receive notification even when the app is in background or closed.

You can use Notification Type (the object holds "notification" as Key), this will work only when the app is in foreground.

Take a look at this

https://firebase.google.com/docs/cloud-messaging/concept-options

CodePudding user response:

You can not show it through your app. It is system feature.

https://firebase.google.com/docs/cloud-messaging/concept-options

your json body should include "notification":{ "title":"Portugal vs. Denmark", "body":"great match!" }

  • Related