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!" }