ably/ably-java

LocalDevice reset will cause ClassCastException

Closed this issue · 8 comments

ably-android:1.2.33

Sentry error log:

io.ably.lib.push.SharedPreferenceStorage in clear at line 45
io.ably.lib.push.LocalDevice in reset at line 147
io.ably.lib.push.ActivationStateMachine$WaitingForDeregistration in transition at line 495
io.ably.lib.push.ActivationStateMachine$WaitingForDeregistration in transition$bridge
io.ably.lib.push.ActivationStateMachine in handleEvent at line 812
io.ably.lib.push.ActivationStateMachine$9 in onSuccess at line 762
io.ably.lib.push.ActivationStateMachine$5 in onSuccess$bridge
io.ably.lib.push.ActivationStateMachine$9 in onSuccess at line 758
io.ably.lib.push.ActivationStateMachine$5 in onSuccess$bridge
io.ably.lib.http.HttpScheduler$AsyncRequest in setResult at line 320
io.ably.lib.http.HttpScheduler$AblyRequestWithFallback in run at line 205
java.util.concurrent.ThreadPoolExecutor in runWorker at line 1145
java.util.concurrent.ThreadPoolExecutor$Worker in run at line 644
java.lang.Thread in run at line 1012

Source code:

// LocalDevice
 public void reset() {
      Log.v(TAG, "reset()");
      this.id = null;
      this.deviceSecret = null;
      this.deviceIdentityToken = null;
      this.clientId = null;
      this.clearRegistrationToken();

      storage.clear(SharedPrefKeys.class.getDeclaredFields());
  }

//SharePreferenceStorage
@Override
public void clear(Field[] fields) {
    SharedPreferences.Editor editor = activationContext.getPreferences().edit();
    for (Field f : fields) {
        try {
            editor.remove((String) f.get(null));
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    editor.commit();
}

//xml file
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="ABLY_DEVICE_ID">xxxxx</string>
    <int name="ABLY_REGISTRATION_TOKEN_TYPE" value="1" />
    <string name="ABLY_REGISTRATION_TOKEN">xxx</string>
    <string name="ABLY_DEVICE_IDENTITY_TOKEN">xxxxx</string>
</map>

When sp key's value is not "String" type, it'll throw ClasscastException

➤ Automation for Jira commented:

The link to the corresponding Jira issue is https://ably.atlassian.net/browse/SDK-4074

sacOO7 commented

Hi @YumengNevix we will look into it. Can I ask few more questions

  1. Key/Value for which reset is throwing the exception
  2. How frequently does this occur ?
  3. Does this occur on few android devices/all android devices?
  4. Does this work for older ably-android versions? have you tried any?

Exception message: java.lang.Boolean cannot be cast to java.lang.String

  1. The error console can't tell which key cause this bug
    2-3 We just in beta state, so this bug is just show on one of my teammate's phone. The phone model is: SM-F946U1 | Android 14. At this device, this bug occurs for many times.
  2. I don't try older version.

Why Field not call setAccessible(true) before get it's value?
editor.remove((String) f.get(null));

sacOO7 commented

@YumengNevix we will take a look at it. I feel we should try to avoid use of reflection at all possible places. Shared pref keys should instead be passed as plain string array .

sacOO7 commented

@YumengNevix I have created PR for the fix. You can check 👍

sacOO7 commented

@YumengNevix we have merged the fix. We will do the release soon. Meanwhile do star the repo 👍

Hi @YumengNevix we have released the fix as a part of v1.2.34. Please update your own version of the library.