I am grabbing the android device token and saving it to firestore. This works in most of the cases totally fine. Now I encountered a device where it does not work. Oddly enough I end up with attributes in firestore that my model does not reflect and I do not understand where those attributes and their values come from.
This is my method to retrieve the token:
public static void updateToken(String userId, FcmToken.Action action) {
if (StringUtils.checkNull(userId)) return;
//FCM
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
Log.w(TAG, "Could not get firebase token. ", task.getException());
return;
}
String token = task.getResult();
Log.i(TAG, "[FCM TOKEN]: " token);
//Do not ask firebase to write an existing token again,
//this only creates traffic and costs but does not change the database
String storedToken = FcmProvider.loadToken(false);
if (StringUtils.checkNull(storedToken) || !token.equals(storedToken) || action == FcmToken.Action.DELETE) {
FcmToken fcmToken = new FcmToken(token, userId, action);
FcmRepo.getInstance().setToken(fcmToken, documentId -> {
Log.d(TAG, "Token " action " successfully");
FcmProvider.saveToken(token);
}, e -> {
Log.d(TAG, "Failed to " action " token. " e);
});
} else {
Log.d(TAG, "Stored token is identical. No update needed");
}
});
}
This is the FcmToken class (And I assume the way I use the field values here are the issue, yet I do not understand the outcome)
@Getter
@Setter
@IgnoreExtraProperties
public class FcmToken {
private String userId;
private FieldValue fcmToken;
@ServerTimestamp
private Date ut;
public enum Action {SET, DELETE}
public FcmToken(String fcmToken, String userId, Action action) {
this.userId = userId;
if (action == Action.SET) this.fcmToken = FieldValue.arrayUnion(fcmToken);
else if (action == Action.DELETE) this.fcmToken = FieldValue.arrayRemove(fcmToken);
}
}
For completness this is the method I use to set the token:
public void setToken(@NonNull FcmToken fcmToken, @Nullable OnSetSuccessListener callbackSuccess, @Nullable OnFailureListener callbackFailure) {
getFcmRef().document(fcmToken.getUserId()).set(fcmToken, SetOptions.merge()).addOnCompleteListener(task ->...);
}
Now this is what ends up in my firestore for that user only:
This HAS to to come from the app itself. There is no other way this document could have been created:
If I use another device or the emulator the result looks like expected. Where does the "a" field come from? Why is it assigned to userId and why is there no fcmToken field?
The problem is, that I do not have physical access to the phone that produces this behaviour (Samsung S21 Ultra, Android 12). I need to debug this without having access to the log outputs. But I know that the task comes back successfully (I used another version to save the error in the token field and there was none).
Any ideas?
CodePudding user response:
This typically means that you didn't configure ProGuard correctly, and it's minifying the classes that you're writing to the database.
You'll need to prevent ProGuard from modifying the classes that you use to interact with the database. See the Firebase documentation on configuring ProGuard (the link is for the Realtime Database, but the same applies to Firestore), or one of these previous questions about configuring ProGuard for Firebase.