Crashlytics is reporting a lot of NullPointerException
s in the following code in our Android app.
public static PayloadParseResult parsePayloadData(@NotNull String payloadStringData) {
PayloadParseResult result = new PayloadParseResult();
Gson gson = new GsonBuilder().create();
NotificationPayload payload = gson.fromJson(payloadStringData, NotificationPayload.class);
if (payload == null) {
String log = "Unable to parse payload.\n";
log += "payload string:\n" + payloadStringData;
EventTracker.getsInstance().log(EventType.UnknownNotificationPayload, EventProperty.Type, log);
result.isValid = false;
} else if (payload.alertBody == null) {
String log = "Unable to parse payload body.\n";
log += "payload string:\n" + payloadStringData;
EventTracker.getsInstance().log(EventType.UnknownNotificationPayload, EventProperty.Type, log);
result.isValid = false;
} else if (Strings.isNullOrEmpty(payload.alertBody.partitionType)) {
String log = "Unknown partition type in payload. Should be 'team'.\n";
log += "payload string:\n" + payloadStringData;
EventTracker.getsInstance().log(EventType.UnknownNotificationPayload, EventProperty.Type, log);
result.isValid = false;
} else {
// We understood this payload
result.notificationPayload = payload;
result.isValid = true;
}
return result;
}
The crash occurs on the last else if
line.
} else if (Strings.isNullOrEmpty(payload.alertBody.partitionType)) {
The payload
object is a simple POCO deserialized from json.
public class NotificationPayload {
@SerializedName("a")
public NotificationAlertBody alertBody;
}
public class NotificationAlertBody {
@SerializedName("noteId")
public String noteId;
@SerializedName("partitionType")
public String partitionType;
@SerializedName("partitionKey")
public String partitionKey;
}
I know what you are thinking. "There's no possible way for it to crash there." But it does. It has lowered our crash free user rate from 99.5% to 90.0% in a matter of days. We can't reproduce it in Android Studio, and we can't reproduce it in our own production testing. This is baffling.
Here is the call stack as shown in Crashlytics.
Fatal Exception: java.lang.NullPointerException
at com.omitted.omitted.utils.gcm.PayloadParser.parsePayloadData(PayloadParser.java:87)
at com.omitted.omitted.utils.gcm.PayloadParser.parsePayloadData(PayloadParser.java:66)
at com.omitted.omitted.utils.gcm.MyCloudMessagingListenerService.onMessageReceived(MyCloudMessagingListenerService.java:32)
at com.google.firebase.messaging.FirebaseMessagingService.dispatchMessage(FirebaseMessagingService.java:13)
at com.google.firebase.messaging.FirebaseMessagingService.passMessageIntentToSdk(FirebaseMessagingService.java:8)
at com.google.firebase.messaging.FirebaseMessagingService.handleMessageIntent(FirebaseMessagingService.java:3)
at com.google.firebase.messaging.FirebaseMessagingService.handleIntent(FirebaseMessagingService.java:3)
at com.google.firebase.messaging.EnhancedIntentService.lambda$processIntent$0$EnhancedIntentService(EnhancedIntentService.java:1)
at com.google.firebase.messaging.EnhancedIntentService$$Lambda$0.run(EnhancedIntentService.java:6)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at com.google.android.gms.common.util.concurrent.zza.run(zza.java:6)
at java.lang.Thread.run(Thread.java:923)
Edit:
I changed the crashing line to
} else if (payload.alertBody.partitionType == null || payload.alertBody.partitionType.isEmpty()) {
as @Shadov suggested, but I am still getting crash reports on that line.