Reputation: 1601
I follow this tutorial Lapit Chat App - Push Notifications - Firebase Tutorials - Part 24
All went well, it's just that I found a bit of a problem when the notifications came and my device was not running the application (background mode), and when I clicked on the notification panel, my app became crashed.
The error does not occur if my device has previously opened the application. When I click on the notification panel, the application runs normally and opens my ProfileActivity
I get ErrorLog for this error
07-29 16:36:54.512 16573-16573/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.bertho.chat, PID: 16573
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bertho.chat/com.bertho.chat.ProfileActivity}: java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2464)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2524)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1391)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
Caused by: java.lang.NullPointerException: Can't pass null for argument 'pathString' in child()
at com.google.firebase.database.DatabaseReference.child(Unknown Source)
at com.bertho.chat.ProfileActivity.onCreate(ProfileActivity.java:56)
at android.app.Activity.performCreate(Activity.java:6285)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2524)
at android.app.ActivityThread.access$900(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1391)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
This is my ProfileActivity.java
public class ProfileActivity extends BaseActivity {
private ImageView mProfileImage;
private TextView mProfileName, mProfileStatus, mProfileFriendsCount;
private Toolbar mToolbar;
private Button mProfileSendReqBtn, mProfileDeclineReqBtn;
private ProgressDialog mDialog;
private FirebaseUser mCuurentUser;
private String mCuurent_state;
private DatabaseReference mUserDatabase, mFriendsReqDatabase, mFriendsDatabase, mNotificationDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_profile );
final String user_id = getIntent().getStringExtra( "user_id" );
mDialog = new ProgressDialog( this );
mUserDatabase = FirebaseDatabase.getInstance().getReference().child( "Users" ).child( user_id );
mUserDatabase.keepSynced( true );
mFriendsReqDatabase = FirebaseDatabase.getInstance().getReference().child( "FriendsRequest" );
mFriendsReqDatabase.keepSynced( true );
mFriendsDatabase = FirebaseDatabase.getInstance().getReference().child( "FriendsData" );
mFriendsDatabase.keepSynced( true );
mNotificationDatabase = FirebaseDatabase.getInstance().getReference().child( "Notifications" );
mProfileImage = (ImageView) findViewById( R.id.profile_image );
mProfileName = (TextView) findViewById( R.id.profile_displayName );
mProfileStatus = (TextView) findViewById( R.id.profile_status );
mProfileFriendsCount = (TextView) findViewById( R.id.profile_totalFriends );
mProfileSendReqBtn = (Button) findViewById( R.id.profile_send_fr_btn );
mProfileDeclineReqBtn = (Button) findViewById( R.id.profile_decline_req_btn );
mCuurentUser = FirebaseAuth.getInstance().getCurrentUser();
showLoading( "Load Profile Data" );
mCuurent_state = "not_friends";
mUserDatabase.addValueEventListener( new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String display_name = dataSnapshot.child( "name" ).getValue().toString();
String display_status = dataSnapshot.child( "status" ).getValue().toString();
final String display_image = dataSnapshot.child( "image" ).getValue().toString();
mProfileName.setText( display_name );
mProfileStatus.setText( display_status );
if (mCuurent_state == "not_friends") {
mProfileDeclineReqBtn.setVisibility( View.INVISIBLE );
mProfileDeclineReqBtn.setEnabled( false );
} else if (mCuurent_state == "received") {
mProfileDeclineReqBtn.setVisibility( View.VISIBLE );
mProfileDeclineReqBtn.setEnabled( true );
} else {
mProfileDeclineReqBtn.setVisibility( View.INVISIBLE );
mProfileDeclineReqBtn.setEnabled( false );
}
/*Picasso.with( ProfileActivity.this )
.load( display_image )
.placeholder( R.drawable.no_profile )
.into( mProfileImage );*/
Picasso.with( ProfileActivity.this )
.load( display_image )
.networkPolicy( NetworkPolicy.OFFLINE )
.placeholder( R.drawable.no_profile )
.into( mProfileImage, new Callback() {
@Override
public void onSuccess() {
}
@Override
public void onError() {
Picasso.with( ProfileActivity.this )
.load( display_image )
.placeholder( R.drawable.no_profile )
.into( mProfileImage );
}
} );
// ========== FRIEND LIST ONLY FOR CURRENT USER LOGGED IN ==========
mFriendsReqDatabase.child( mCuurentUser.getUid() ).addListenerForSingleValueEvent( new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild( user_id )) {
String req_type = dataSnapshot.child( user_id ).child( "request_type" ).getValue().toString();
if (req_type.equals( "received" )) {
mCuurent_state = "req_received";
mProfileSendReqBtn.setText( "Accept Friend Request" );
mProfileDeclineReqBtn.setVisibility( View.VISIBLE );
mProfileDeclineReqBtn.setEnabled( true );
} else if (req_type.equals( "sent" )) {
mCuurent_state = "req_sent";
mProfileSendReqBtn.setText( "Cancel Friend Request" );
mProfileSendReqBtn.setBackgroundColor( getResources().getColor( R.color.colorAccent ) );
mProfileDeclineReqBtn.setVisibility( View.INVISIBLE );
mProfileDeclineReqBtn.setEnabled( false );
}
} else {
/*Toast.makeText(getApplicationContext(), "TIDAK ADA : " + mCuurent_state, Toast.LENGTH_SHORT).show();*/
mFriendsDatabase.child( mCuurentUser.getUid() ).addListenerForSingleValueEvent( new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild( user_id )) {
mCuurent_state = "friends";
mProfileSendReqBtn.setText( "Unfriend This Person" );
/*mProfileSendReqBtn.setEnabled( false );
mProfileSendReqBtn.setBackgroundColor( getResources().getColor( R.color.colorAccent ) );*/
mProfileDeclineReqBtn.setVisibility( View.INVISIBLE );
mProfileDeclineReqBtn.setEnabled( false );
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
} );
}
mDialog.dismiss();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
} );
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
} );
mProfileSendReqBtn.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View view) {
// ========== ADD FRIEND REQUEST ==========
if (mCuurent_state.equals( "not_friends" )) {
showLoading( "Data is processing...!" );
mProfileSendReqBtn.setEnabled( false );
mFriendsReqDatabase.child( mCuurentUser.getUid() ).child( user_id ).child( "request_type" ).setValue( "sent" ).addOnCompleteListener( new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
mFriendsReqDatabase.child( user_id ).child( mCuurentUser.getUid() ).child( "request_type" ).setValue( "received" ).addOnCompleteListener( new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
HashMap<String, String> notificationData = new HashMap<>( );
notificationData.put( "from", mCuurentUser.getUid() );
notificationData.put( "type", "request" );
mNotificationDatabase.child( user_id ).push().setValue( notificationData ).addOnSuccessListener( new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mDialog.dismiss();
mCuurent_state = "req_sent";
mProfileSendReqBtn.setText( "Cancel Friend Request" );
mProfileSendReqBtn.setBackgroundColor( getResources().getColor( R.color.colorAccent ) );
mProfileDeclineReqBtn.setVisibility( View.INVISIBLE );
mProfileDeclineReqBtn.setEnabled( false );
showSuccess( "Request Sent!" );
}
} );
} else {
mDialog.dismiss();
onError( "Request Submission Failed!" );
}
}
} );
} else {
mDialog.dismiss();
onError( "Request Submission Failed!" );
}
mProfileSendReqBtn.setEnabled( true );
}
} );
}
// ========== CANCEL REQUEST FRIEND ==========
if (mCuurent_state.equals( "req_sent" )) {
showLoading( "Data is processing...!" );
mProfileSendReqBtn.setEnabled( false );
mFriendsReqDatabase.child( mCuurentUser.getUid() ).child( user_id ).removeValue().addOnCompleteListener( new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
mFriendsReqDatabase.child( user_id ).child( mCuurentUser.getUid() ).removeValue().addOnCompleteListener( new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
mDialog.dismiss();
mCuurent_state = "not_friends";
mProfileSendReqBtn.setText( "Send Friend Request" );
mProfileSendReqBtn.setBackgroundColor( getResources().getColor( R.color.successAlert ) );
mProfileDeclineReqBtn.setVisibility( View.INVISIBLE );
mProfileDeclineReqBtn.setEnabled( false );
onSuccess( "Cancel Request Success!" );
} else {
mDialog.dismiss();
onError( "Cancel Request Failed!" );
}
}
} );
} else {
mDialog.dismiss();
onError( "Cancel Request Failed!" );
}
mProfileSendReqBtn.setEnabled( true );
}
} );
}
// ========== ACTION APPROVE REQUEST ==========
if (mCuurent_state.equals( "req_received" )) {
showLoading( "Data is processing...!" );
mProfileSendReqBtn.setEnabled( false );
final String currentDate = DateFormat.getDateTimeInstance().format( new Date() );
mFriendsDatabase.child( mCuurentUser.getUid() ).child( user_id ).setValue( currentDate ).addOnCompleteListener( new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
mFriendsDatabase.child( user_id ).child( mCuurentUser.getUid() ).setValue( currentDate ).addOnSuccessListener( new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mFriendsReqDatabase.child( mCuurentUser.getUid() ).child( user_id ).removeValue().addOnCompleteListener( new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
mFriendsReqDatabase.child( user_id ).child( mCuurentUser.getUid() ).removeValue().addOnCompleteListener( new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
mDialog.dismiss();
mCuurent_state = "friends";
mProfileSendReqBtn.setText( "Unfriend This Person" );
mProfileSendReqBtn.setBackgroundColor( getResources().getColor( R.color.colorAccent ) );
mProfileDeclineReqBtn.setVisibility( View.INVISIBLE );
mProfileDeclineReqBtn.setEnabled( false );
showSuccess( "Success approve friend request!" );
} else {
mDialog.dismiss();
onError( "Failed approve friend request!" );
}
}
} );
} else {
mDialog.dismiss();
onError( "Failed approve friend request!" );
}
mProfileSendReqBtn.setEnabled( true );
}
} );
}
} );
} else {
mDialog.dismiss();
onError( "Failed approve friend request!" );
}
mProfileSendReqBtn.setEnabled( true );
}
} );
}
// ========== ACTION REMOVE FRIENDS ==========
if (mCuurent_state.equals( "friends" )) {
showLoading( "Data is processing...!" );
mFriendsDatabase.child( mCuurentUser.getUid() ).child( user_id ).removeValue().addOnSuccessListener( new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
mDialog.dismiss();
mCuurent_state = "not_friends";
mProfileSendReqBtn.setText( "Send Friend Request" );
mProfileSendReqBtn.setBackgroundColor( getResources().getColor( R.color.successAlert ) );
}
} );
}
}
} );
}
private void showLoading(String s) {
mDialog.setTitle( "Please wait a moment" );
mDialog.setMessage( s );
mDialog.setCanceledOnTouchOutside( false );
mDialog.show();
}
public void showSuccess(String message) {
Alerter.create( this )
.setTitle( "Success" )
.setText( message )
.setBackgroundColorRes( R.color.successAlert )
.show();
}
}
MyFirebaseMessagingService.java
package com.bertho.chat;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived( remoteMessage );
String notificationTitle = remoteMessage.getNotification().getTitle();
String notificationBody = 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( this )
.setSmallIcon( R.drawable.notif_icon )
.setContentTitle( notificationTitle )
.setContentText( notificationBody );
Intent resultIntent = new Intent(click_action);
resultIntent.putExtra( "user_id", from_user_id);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
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() );
}
}
According to the description the error log refers to this line
mUserDatabase = FirebaseDatabase.getInstance().getReference().child( "Users" ).child( user_id );
Is in this case an application unable to load data from the Firebase database so that it becomes crashed?
Please advise
Upvotes: 2
Views: 1019
Reputation: 1601
I change my Firebase Function from
const payload = {
notification: {
title: "New Friend Request",
body: `${userName} has sent you Friend Request`,
icon: "default",
click_action: "com.bertho.chat_TARGET_NOTIFICATION"
},
data: {
from_user_id: from_user_id
}
};
to
const payload = {
data: {
title: "New Friend Request",
body: `${userName} has sent you Friend Request`,
from_user_id: from_user_id,
click_action: "com.bertho.chat_TARGET_NOTIFICATION"
}
};
Thanks to @UmarZaii
Upvotes: 1
Reputation: 1351
1ST SOLUTION:
If you want to prevent the crash from happening, you can change the code from ProfileActivity.java
final String user_id = getIntent().getStringExtra( "user_id" );
To this code.
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
final String user_id;
if (getIntent().getStringExtra( "user_id" ).equals("") ||
getIntent().getStringExtra( "user_id" ) == null) {
user_id = getIntent().getStringExtra( "user_id" );
} else if (firebaseAuth.getCurrentUser() != null) {
user_id = firebaseAuth.getCurrentUser().getUid();
} else {
//There is no active user and the userID retrieved is null
}
As you can see, the if else statement checks whether the user_id
that you retrieved from the notification is null or empty.
If it is then it will checks the current user that logged in to the application and use the user_id
that retrieved by FirebaseAuth
.
If both of them is empty or null then inform to me. I will update my answer.
2ND SOLUTION:
Don't use String from_user_id = remoteMessage.getData().get( "from_user_id" );
this code in your MyFirebaseMessagingService.java. Instead use below code.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
FirebaseAuth firebaseAuth;
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived( remoteMessage );
firebaseAuth = FirebaseAuth.getInstance();
String from_user_id = firebaseAuth.getCurrentUser().getUid();
}
}
I hope it helps. Feel free to ask me if it didn't work.
Upvotes: 0