Android Parcel Unmarshalling неизвестный код типа

Хорошо, мой, безусловно, отличается от всех других вопросов, задаваемых с этой же проблемой

Вот мой метод записи:

public Folder(Parcel in, ClassLoader loader) {
    id = in.readInt();
    persistentId = in.readString();
    folderUri = new FolderUri((Uri) in.readParcelable(loader));
    name = in.readString();
    capabilities = in.readInt();
    // 1 for true, 0 for false.
    hasChildren = in.readInt() == 1;
    syncWindow = in.readInt();
    conversationListUri = in.readParcelable(loader);
    childFoldersListUri = in.readParcelable(loader);
    unseenCount = in.readInt();
    unreadCount = in.readInt();
    totalCount = in.readInt();
    refreshUri = in.readParcelable(loader);
    syncStatus = in.readInt();
    lastSyncResult = in.readInt();
    type = in.readInt();
    iconResId = in.readInt();
    notificationIconResId = in.readInt();
    bgColor = in.readString();
    fgColor = in.readString();
    if (bgColor != null) {
        bgColorInt = Integer.parseInt(bgColor);
    }
    if (fgColor != null) {
        fgColorInt = Integer.parseInt(fgColor);
    }
    loadMoreUri = in.readParcelable(loader);
    hierarchicalDesc = in.readString();
    parent = in.readParcelable(loader);
    lastMessageTimestamp = in.readLong();
    notificationUri = in.readParcelable(loader);
    updatedCountUri = in.readParcelable(loader);
    unreadSenders = in.readString();
}

Вот мой метод записи:

public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(id);
    dest.writeString(persistentId);
    dest.writeParcelable(folderUri != null ? folderUri.fullUri : null, 0);
    dest.writeString(name);
    dest.writeInt(capabilities);
    // 1 for true, 0 for false.
    dest.writeInt(hasChildren ? 1 : 0);
    dest.writeInt(syncWindow);
    dest.writeParcelable(conversationListUri, 0);
    dest.writeParcelable(childFoldersListUri, 0);
    dest.writeInt(unseenCount);
    dest.writeInt(unreadCount);
    dest.writeInt(totalCount);
    dest.writeParcelable(refreshUri, 0);
    dest.writeInt(syncStatus);
    dest.writeInt(lastSyncResult);
    dest.writeInt(type);
    dest.writeInt(iconResId);
    dest.writeInt(notificationIconResId);
    dest.writeString(bgColor);
    dest.writeString(fgColor);
    dest.writeParcelable(loadMoreUri, 0);
    dest.writeString(hierarchicalDesc);
    dest.writeParcelable(parent, 0);
    dest.writeLong(lastMessageTimestamp);
    dest.writeParcelable(notificationUri, 0);
    dest.writeParcelable(updatedCountUri, 0);
    dest.writeString(unreadSenders);
}

Это прекрасно работает без проблем. Если я осмелюсь изменить порядок чего-либо в моем методе writeToParcel() или добавлю переменную и, соответственно, внесу соответствующее изменение в метод чтения из посылки (т.е. конструктор выше), я получу вышеуказанную ошибку. Я буквально не могу внести изменения в него или Android Barfs.

Теперь вот где это становится странным. Если я перезагружаю устройство, то больше нет сбоя, нет больше исключения. Без изменения кода, просто перезагрузка. Это заставляет меня поверить, что Android кэширует мою посылку и полностью игнорирует то, что я пишу в посылку. Я вхожу в режим отладки и устанавливаю точку останова в своем методе writeToParcel(), и я вижу, что он выполняет каждую строку, но когда он идет на чтение из моей посылки, он все еще думает, что порядок такой, каким он был раньше. Поэтому, если я поменяю строки для writeInt() с writeString() и внесу изменения в мой конструктор, при чтении он все еще думает, что Int должен быть там, где была String. WTF. Кто-нибудь, пожалуйста, скажите мне, что это известная ошибка в Android. Как я уже сказал, перезагрузка исправляет эту проблему.

Вот где я делаю посылку. Я в основном создаю PendingIntent, который срабатывает при отклонении уведомления.

final Intent cancelNotificationIntent = new Intent(INTENT_ACTION);
cancelNotificationIntent.putExtra(Utils.EXTRA_FOLDER, folder);
notification.setDeleteIntent(PendingIntent.getService(context, notificationId, cancelNotificationIntent, 0));

Вот где я отменяю:

final Folder folder = intent.getParcelableExtra(Utils.EXTRA_FOLDER);

Ничего фантастического. Помогите? Если это поможет, я воспроизводлю это на Android 4.3 и 4.4.

1 ответ

Итак, моя проблема оказалась в кэше PendingIntent.

final Intent cancelNotificationIntent = new Intent(INTENT_ACTION);
cancelNotificationIntent.putExtra(Utils.EXTRA_FOLDER, folder); // This is the parceled object
notification.setDeleteIntent(PendingIntent.getService(context, notificationId, cancelNotificationIntent, 0));

PendingIntent.getService(), когда передается 0 для флагов, будет продолжать использовать тот же PendingIntent снова и снова и полностью игнорировать все, что я пишу для cancelNotificationIntent. Я исправил это, изменив его на:

notification.setDeleteIntent(PendingIntent.getService(context, notificationId, cancelNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT));

Что я до сих пор не понимаю, так это то, почему PendingIntent.getService() продолжал возвращать кэшированный Intent даже после обновления приложения (то есть adb install -r app.apk). Вы можете подумать, что если приложение было убито или переустановлено, PendingIntent исчезнет, ​​но нет. Android кеширует, что штопал PI бесконечно, пока вы не перезагрузите устройство.

Надеюсь, это поможет кому-то еще.

Другие вопросы по тегам