While using android studio and firebase, my app (in the background or foreground) crashes on an API 26 device when notification is clicked. Whereas when I use an API 23 device, the app crashes when the app is closed and notification is clicked but can still process the notification when app is in the background/foreground. I don't understand the problem and any help is appreciated.
NOTIFICATION SERVICE
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import com.google.firebase.messaging.RemoteMessage;
public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String notification_title = remoteMessage.getNotification().getTitle();
String notification_message = remoteMessage.getNotification().getBody();
String click_action = remoteMessage.getNotification().getClickAction();
String from_user_id = remoteMessage.getData().get("from_user_id");
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(FirebaseMessagingService.this, "default")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(notification_title)
.setContentText(notification_message);
Intent resultIntent = new Intent(click_action);
resultIntent.putExtra("user_id", from_user_id);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
FirebaseMessagingService.this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
int mNotificationId = (int) System.currentTimeMillis();
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, mBuilder.build());
}
}
USERS ACTIVITY
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.squareup.picasso.Picasso;
import de.hdodenhof.circleimageview.CircleImageView;
public class UsersActivity extends AppCompatActivity {
private Toolbar mToolbar;
private RecyclerView mUsersList;
private DatabaseReference mUsersDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_users);
mToolbar=(Toolbar)findViewById(R.id.users_appBar);
setSupportActionBar(mToolbar);
getSupportActionBar().setTitle("All Users");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mUsersDatabase= FirebaseDatabase.getInstance().getReference().child("Users");
mUsersDatabase.keepSynced(true);
mUsersList=(RecyclerView)findViewById(R.id.users_list);
mUsersList.setHasFixedSize(true);
mUsersList.setLayoutManager(new LinearLayoutManager(this));
}
@Override
protected void onStart() {
super.onStart();
startListening();
}
public void startListening(){
Query query = FirebaseDatabase.getInstance()
.getReference()
.child("Users")
.limitToLast(50);
FirebaseRecyclerOptions<Users> options =
new FirebaseRecyclerOptions.Builder<Users>()
.setQuery(query, Users.class)
.build();
FirebaseRecyclerAdapter<Users, UserViewHolder> adapter = new FirebaseRecyclerAdapter<Users, UserViewHolder>(options) {
@Override
public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Create a new instance of the ViewHolder, in this case we are using a custom
// layout called R.layout.message for each item
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.users_single_layout, parent, false);
return new UserViewHolder(view);
}
@Override
protected void onBindViewHolder(UserViewHolder holder, int position, Users model) {
// Bind the Chat object to the ChatHolder
holder.setName(model.name);
holder.setStatus(model.status);
holder.setUserImage(model.getThumb_image());
final String user_id= getRef(position).getKey();
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent profileIntent = new Intent(UsersActivity.this, ProfileActivity.class);
if (user_id != null) {
profileIntent.putExtra("user_id", user_id);
startActivity(profileIntent);
}
}
});
}
};
mUsersList.setAdapter(adapter);
adapter.startListening();
}
public static class UserViewHolder extends RecyclerView.ViewHolder {
View mView;
public UserViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setName(String name){
TextView userNameView = (TextView) mView.findViewById(R.id.user_single_name);
userNameView.setText(name);
}
public void setStatus(String status){
TextView userStatusView= (TextView) mView.findViewById(R.id.user_single_status);
userStatusView.setText(status);
}
public void setUserImage(String thumb_image){
CircleImageView userImageView = (CircleImageView) mView.findViewById(R.id.user_single_image);
Picasso.get().load(thumb_image).placeholder(R.drawable.accountpicture).into(userImageView);
}
}
}
PROFILE ACTIVITY
import android.app.ProgressDialog;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
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.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.squareup.picasso.Callback;
import com.squareup.picasso.NetworkPolicy;
import com.squareup.picasso.Picasso;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
public class ProfileActivity extends AppCompatActivity {
private ImageView mProfileImage;
private TextView mProfileName, mProfileStatus, mProfileFriendsCount;
private Button mProfileSendReqBtn;
private DatabaseReference mUserDatabase;
private Button declineRequest;
private FirebaseUser mCurrent_user;
private ProgressDialog mProgressDialog;
private DatabaseReference mFriendRequestDatabase;
private DatabaseReference mFriendDatabase;
private String mCurrent_state;
private DatabaseReference mNotificationDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
final String user_id = getIntent().getStringExtra("user_id");
mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child(user_id);
mFriendRequestDatabase = FirebaseDatabase.getInstance().getReference().child("Friend_req");
mCurrent_user= FirebaseAuth.getInstance().getCurrentUser();
mFriendDatabase= FirebaseDatabase.getInstance().getReference().child("Friends");
mNotificationDatabase= FirebaseDatabase.getInstance().getReference().child("notifications");
mProfileImage = (ImageView) findViewById(R.id.profile_image);
mProfileName = (TextView) findViewById(R.id.profile_profileName);
mProfileStatus = (TextView) findViewById(R.id.profile_status);
mProfileFriendsCount = (TextView) findViewById(R.id.profile_totalFriends);
mProfileSendReqBtn = (Button) findViewById(R.id.profile_send_req_btn);
declineRequest= (Button)findViewById(R.id.profile_decline_btn);
mCurrent_state = "not_friends";
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setTitle("Loading User Data");
mProgressDialog.setMessage("Please wait...");
mProgressDialog.setCanceledOnTouchOutside(false);
mProgressDialog.show();
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
declineRequest.setVisibility(View.INVISIBLE);
if(mCurrent_user.getUid().equals(user_id)){
mProfileSendReqBtn.setVisibility(View.INVISIBLE);
}
mUserDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
String diplay_name = dataSnapshot.child("name").getValue().toString();
String status = dataSnapshot.child("status").getValue().toString();
final String image = dataSnapshot.child("image").getValue().toString();
mProfileName.setText(diplay_name);
mProfileStatus.setText(status);
Picasso.get().load(image).networkPolicy(NetworkPolicy.OFFLINE).placeholder(R.drawable.accountpicture).into(mProfileImage, new Callback() {
@Override
public void onSuccess() {
}
@Override
public void onError(Exception e) {
Picasso.get().load(image).placeholder(R.drawable.accountpicture).into(mProfileImage);
}
});
mFriendRequestDatabase.child(mCurrent_user.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChild(user_id)){
String req_type= dataSnapshot.child(user_id).child("request_type").getValue().toString();
if(req_type.equals("received")){
mCurrent_state= "req_received";
mProfileSendReqBtn.setText("Accept Friend Request");
declineRequest.setVisibility(View.VISIBLE);
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
}
else if(req_type.equals("sent")){
mCurrent_state="req_sent";
mProfileSendReqBtn.setText("Cancel Friend Request");
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
}
else if(req_type.equals("req_sent")){
mCurrent_state= "not_friends";
mProfileSendReqBtn.setText("Send Friend Request");
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
}
mProgressDialog.dismiss();
}
else{
mFriendDatabase.child(mCurrent_user.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChild(user_id)){
mCurrent_state= "friends";
mProfileSendReqBtn.setText("Unfriend User");
mProfileSendReqBtn.setEnabled(true);
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
}
mProgressDialog.dismiss();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
mProgressDialog.dismiss();
}
});
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
mProfileSendReqBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mProfileSendReqBtn.setEnabled(false);
if (user_id.equals(mCurrent_user.getUid())) {
Toast.makeText(ProfileActivity.this, "Cannot send friend request to yourself!", Toast.LENGTH_LONG).show();
declineRequest.setVisibility(View.INVISIBLE);
} else {
if (mCurrent_state.equals("not_friends")) {
mFriendRequestDatabase.child(mCurrent_user.getUid()).child(user_id).child("request_type").setValue("sent").addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
mFriendRequestDatabase.child(user_id).child(mCurrent_user.getUid()).child("request_type").setValue("received").addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
HashMap<String, String> notificationData= new HashMap<>();
notificationData.put("from", mCurrent_user.getUid());
notificationData.put("type", "request");
mNotificationDatabase.child(user_id).push().setValue(notificationData).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mCurrent_state = "req_sent";
mProfileSendReqBtn.setText("Cancel Friend Request");
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
}
});
}
});
} else {
Toast.makeText(ProfileActivity.this, "Error", Toast.LENGTH_LONG).show();
}
mProfileSendReqBtn.setEnabled(true);
}
});
}
if (mCurrent_state.equals("req_sent")) {
mProfileSendReqBtn.setEnabled(true);
mFriendRequestDatabase.child(mCurrent_user.getUid()).child(user_id).removeValue().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mFriendRequestDatabase.child(user_id).child(mCurrent_user.getUid()).removeValue().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mCurrent_state = "req_sent";
mProfileSendReqBtn.setText("Send Friend Request");
mCurrent_state = "not_friends";
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
}
});
}
});
}
if (mCurrent_state.equals("req_received")) {
declineRequest.setVisibility(View.INVISIBLE);
mProfileSendReqBtn.setEnabled(true);
final String currentDate = DateFormat.getDateTimeInstance().format(new Date());
mFriendDatabase.child(mCurrent_user.getUid()).child(user_id).setValue(currentDate).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mFriendDatabase.child(user_id).child(mCurrent_user.getUid()).setValue(currentDate).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mFriendRequestDatabase.child(mCurrent_user.getUid()).child(user_id).removeValue().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mFriendRequestDatabase.child(user_id).child(mCurrent_user.getUid()).removeValue().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mCurrent_state = "friends";
mProfileSendReqBtn.setText("Unfriend User");
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
}
});
}
});
}
});
}
});
}
}
}
});
declineRequest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
declineRequest.setVisibility(View.INVISIBLE);
mFriendRequestDatabase.child(mCurrent_user.getUid()).child(user_id).removeValue().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mFriendRequestDatabase.child(user_id).child(mCurrent_user.getUid()).removeValue().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mCurrent_state= "not_friends";
mProfileSendReqBtn.setText("Send Friend Request");
mUserDatabase.keepSynced(true);
mFriendDatabase.keepSynced(true);
mFriendRequestDatabase.keepSynced(true);
}
});
}
});
}
});
}
}
INDEX.JS FILE
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
/*
* 'OnWrite' works as 'addValueEventListener' for android. It will fire the function
* everytime there is some item added, removed or changed from the provided 'database.ref'
* 'sendNotification' is the name of the function, which can be changed according to
* your requirement
*/
exports.sendNotification = functions.database.ref('/notifications/{user_id}/{notification_id}').onWrite((change, context) => {
/*
* You can store values as variables from the 'database.ref'
* Just like here, I've done for 'user_id' and 'notification'
*/
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
console.log('We have a notification from : ', user_id);
/*
* Stops proceeding to the rest of the function if the entry is deleted from database.
* If you want to work with what should happen when an entry is deleted, you can replace the
* line from "return console.log.... "
*/
if(!change.after.val()){
return console.log('A Notification has been deleted from the database : ', notification_id);
}
/*
* 'fromUser' query retreives the ID of the user who sent the notification
*/
const fromUser = admin.database().ref(`/notifications/${user_id}/${notification_id}`).once('value');
return fromUser.then(fromUserResult => {
const from_user_id = fromUserResult.val().from;
console.log('You have new notification from : ', from_user_id);
/*
* The we run two queries at a time using Firebase 'Promise'.
* One to get the name of the user who sent the notification
* another one to get the devicetoken to the device we want to send notification to
*/
const userQuery = admin.database().ref(`Users/${from_user_id}/name`).once('value');
const deviceToken = admin.database().ref(`/Users/${user_id}/device_token`).once('value');
return Promise.all([userQuery, deviceToken]).then(result => {
const userName = result[0].val();
const token_id = result[1].val();
/*
* We are creating a 'payload' to create a notification to be sent.
*/
const payload = {
notification: {
title : "New Friend Request",
body: `${userName} has sent you a request`,
icon: "default",
click_action : "com.example.****.chattingapp_TARGET_NOTIFICATION"
},
data : {
from_user_id : from_user_id
}
};
/*
* Then using admin.messaging() we are sending the payload notification to the token_id of
* the device we retreived.
*/
return admin.messaging().sendToDevice(token_id, payload).then(response => {
return console.log('This was the notification Feature');
});
});
});
});
ERROR I GET
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.****.chattingapp, PID: *****
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.****.chattingapp/com.example.****.chattingapp.ProfileActivity}: java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
at com.example.****.chattingapp.ProfileActivity.onCreate(ProfileActivity.java:53)
DATABASE VALUES
You removed most of the important rows of the Error. However you have to look at it very well and even decode it. It was saying that: there is a problem on "ProfileActivity.onCreate()" method when it calls a "Firebase.....child()" method . There are few rows where you call a "child()" method using a Variable (and not a fixed String), so one of them (please check the Error Log and find the line of that "child()" warning) is the real problem.
So I figured out I needed
final String user_id;
String data = getIntent().getStringExtra("user_id");
if (data == null) {
user_id = getIntent().getStringExtra("from_user_id");
} else {
user_id = getIntent().getStringExtra("user_id");
}
I wasn't check what string I was getting from my intents, hence the null exceptions.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.