尝试在后台/前台运行时应用程序崩溃但适用于其他手机

Posted

技术标签:

【中文标题】尝试在后台/前台运行时应用程序崩溃但适用于其他手机【英文标题】:App crashes when trying to run in background/foreground but works for other phones 【发布时间】:2018-07-24 22:25:56 【问题描述】:

在使用 android studio 和 firebase 时,单击通知时,我的应用(在后台或前台)在 API 26 设备上崩溃。而当我使用 API 23 设备时,当应用程序关闭并单击通知时应用程序崩溃,但当应用程序处于后台/前台时仍然可以处理通知。我不明白这个问题,感谢任何帮助。

通知服务

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());


    

用户活动

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);
        

    

个人资料活动

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 文件

'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');

      );

    );

  );

);

我得到的错误

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.****.chattingapp, PID: *****
                  java.lang.RuntimeException: Unable to start activity ComponentInfocom.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)

数据库值

【问题讨论】:

写出了问题所在:“Can't pass null for argument 'pathString' in child()” 是的,我可以看到。但我没有任何空值 我认为问题是“FirebaseDatabase.getInstance().getReference().child("Users").child(user_id);"其中 USER_ID 为 NULL 但它在我的数据库中不为空 错误表示处理一个“child()”方法时会出现 NullPointerException。用动态字符串调用的最明显的 child() 是那一行……所以……为什么不在调试模式下启动应用程序并在 onCreate() 方法的开头设置断点?然后你会看到哪个是有问题的行。 【参考方案1】:

您删除了错误的大部分重要行。 但是,您必须非常仔细地查看它,甚至对其进行解码。它的意思是:在调用“Firebase .....child()”方法时,“ProfileActivity.onCreate()”方法存在问题。您使用变量(而不是固定字符串)调用“child()”方法的行很少,因此其中之一(请检查错误日志并找到该“child()”警告的行)是真正的问题。

【讨论】:

【参考方案2】:

所以我发现我需要

 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");
    

我没有检查我从意图中得到了什么字符串,因此出现了空异常。

【讨论】:

以上是关于尝试在后台/前台运行时应用程序崩溃但适用于其他手机的主要内容,如果未能解决你的问题,请参考以下文章

适用于 Android 的 Azure 通知中心:如何使用后台服务处理数据消息?

Android 应用在收到新的 FCM 消息时崩溃(前台和后台)

Flutter Firebase前台推送通知未显示但后台正在运行

手机和电脑的后台程序是否与前台程序同时运行 只是被前台覆盖了

在三星设备 (SM-J200F-sdk 22) 中调用 ACTION_VIEW (geo / map) 的意图时应用程序崩溃但适用于许多其他设备!任何解决方案?

NSURLSessionDownloadTask 适用于 wifi,而不是 4G