Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer SeekBarPreference.onSetInitialValue #81

Open
dirkam opened this issue Sep 27, 2017 · 22 comments
Assignees
Labels

Comments

@dirkam
Copy link

dirkam commented Sep 27, 2017

Can you please look into this crash? From time to time I see this crash reported, but it's a rare one.

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{.MyActivity}: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2984)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
       at android.app.ActivityThread.-wrap14(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:154)
       at android.app.ActivityThread.main(ActivityThread.java:6776)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Caused by java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
       at android.app.SharedPreferencesImpl.getInt(SharedPreferencesImpl.java:242)
       at android.support.v7.preference.Preference.getPersistedInt(Preference.java:1709)
       at net.xpece.android.support.preference.SeekBarPreference.onSetInitialValue(SeekBarPreference.java:274)
       at android.support.v7.preference.Preference.dispatchSetInitialValue(Preference.java:6517)
       at android.support.v7.preference.Preference.onAttachedToHierarchy(Preference.java:1257)
       at android.support.v7.preference.PreferenceGroup.addPreference(PreferenceGroup.java:194)
       at android.support.v7.preference.XpPreferenceInflater.android.support.v7.preference.PreferenceGroup.addItemFromInflater(XpPreferenceInflater.java:4126)
       at android.support.v7.preference.XpPreferenceInflater.rInflate(XpPreferenceInflater.java:293)
       at android.support.v7.preference.XpPreferenceInflater.rInflate(XpPreferenceInflater.java:293)
       at android.support.v7.preference.XpPreferenceInflater.inflate(XpPreferenceInflater.java:103)
       at android.support.v7.preference.PreferenceInflater.inflate$7af30e91(PreferenceInflater.java:112)
       at android.support.v7.preference.XpPreferenceManager.inflateFromResource$6154c3e6(XpPreferenceManager.java:67)
       at .MyFragment.android.support.v7.preference.PreferenceFragmentCompat.addPreferencesFromResource(MyFragment.java:9432)
       at android.support.v7.preference.XpPreferenceFragment.onCreatePreferences(XpPreferenceFragment.java:54)
       at android.support.v7.preference.PreferenceFragmentCompat.onCreate(PreferenceFragmentCompat.java:224)
       at android.support.v4.app.Fragment.performCreate(Fragment.java:2329)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1377)
       at android.support.v4.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1109)
       at android.support.v4.app.FragmentTransition.calculateFragments(FragmentTransition.java:996)
       at android.support.v4.app.FragmentTransition.startTransitions(FragmentTransition.java:99)
       at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2364)
       at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
       at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
       at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3221)
       at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3171)
       at android.support.v4.app.FragmentActivity.android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentActivity.java:16192)
       at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
       at .MyActivity.onStart(MyActivity.java)
       at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1256)
       at android.app.Activity.performStart(Activity.java:6972)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2937)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
       at android.app.ActivityThread.-wrap14(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:154)
       at android.app.ActivityThread.main(ActivityThread.java:6776)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
@consp1racy
Copy link
Owner

consp1racy commented Sep 27, 2017

Hi, what have you tried so far?

Looks like somehow a string got into a preference that's supposed to be integer.

  • You updated the preference manually with a value of wrong type.
  • You mixed up preference keys.
  • You accidentally used the same key for two very different preferences.

I recommend Stetho for investigating what's actually stored in there in case this happens on your own device.

@dirkam
Copy link
Author

dirkam commented Sep 30, 2017

I've checked these but I couldn't find anything.
Since it's crashing at addPreferencesFromResource I think it might be something with the XML?

This is how I use it:

<net.xpece.android.support.preference.SeekBarPreference xmlns:app="http://schemas.android.com/apk/res-auto"
                                                                        android:key="volume"
                                                                        android:title="@string/settings_sound_volume"/>

Can it be that android:defaultValue is not set in XML? If so, then how come that it only causes a crash very rarely?

@consp1racy
Copy link
Owner

It's not XML related, it crashes because it's trying to load the value from hard drive and it finds a String instead of the expected integer.

Did you by any chance use the same key "volume" for anything else? Or did you edit shared preferences manually? This is the only thing that comes to my mind...

Unless... "volume" is a very generic name, some library you're using may be writing in your default shared preference file.

Can it be that android:defaultValue is not set in XML?

In that case the default value is 0.

@Devarajrc
Copy link

Is ClasscastException fatal error?

@dirkam
Copy link
Author

dirkam commented Jan 30, 2018

It is.

@consp1racy
Copy link
Owner

@dirkam I never asked, what device did this happen on? Can you reproduce it?

@dirkam
Copy link
Author

dirkam commented Jan 30, 2018

Unfortunately, I can't reproduce it.
I still see this crash, though.
(Did change the previously mentioned "volume" generic name, didn't help)

Happens on a wide variety of devices.

image

@consp1racy
Copy link
Owner

consp1racy commented Jan 30, 2018

@dirkam Could you release a version of your app with some added logging? I'd like to see what value is stored in that preference. Perhaps then I'll be able to guess where it came from.

When your settings activity starts, before it loads the preference fragment, check if the preference file contains the value and if it does, try to get it. You'll need to try-catch all the types because we don't know what's the type of value.

if (prefs.contains("volume") {
    try {
        val out = prefs.getInt("volume")
        Crashlytics.logException(RuntimeException("Volume is int = '$out'"))
    } catch (ex: ClassCastException) {
        try {
            val out = prefs.getString("volume")
            Crashlytics.logException(RuntimeException("Volume is String = '$out'"))
        } catch (ex : ClassCastException) {
            // ...
        }
    }
}

You can get the default preferences with

val prefs = XpPreferenceManager.getDefaultSharedPreferences(this)

@dirkam
Copy link
Author

dirkam commented Jan 31, 2018

Thanks, will do that and keep monitoring it.

@dirkam
Copy link
Author

dirkam commented Feb 28, 2018

Finally, I managed to catch this live (based on a user report, so I'm still unable to reproduce it locally).

This is extremely weird. I have 5 SeekBarPreference and 1 SeekBarDialogPreference.
In a way, all of these are affected.

  • 2 of them were missing from the prefs, which simply would not be possible, only on a fresh install but the app has been used for almost a year.
  • 3 of them returned ClassCastException and were stored as String. Seemingly numerical value, but for 1 of these the actual value should be different based on the user settings.
  • 1 of them is Integer, but the value stored is different from what it should be.

This is really weird. I've checked all the relevant code 3 times and I don't put String into these ever (it would also result in a more frequent crash, I guess).

Not sure if this helps.

I think I can add some workaround locally but would be great to get to the bottom of this.

@dirkam
Copy link
Author

dirkam commented Feb 28, 2018

After adding the workaround (basically, I check for these errors and load a default value if there is an issue), it doesn't crash on the user's device anymore.
However, I noticed in the logs that there are errors thrown for MultiSelectListPreference, too. Most probably we haven't seen this yet because the app was crashing prior to loading these preferences.
I have a feeling that this is coming from the similar weird issue with the stored values.
I have 4 MultiSelectListPreference and all 4 throws this error.
This issue doesn't crash the app, though. I think the rest of the preferences should be fine as there is no crash or any other error in the logs.

 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1518)
 	at java.lang.reflect.Method.invoke(Native Method)
 	at android.app.ActivityThread.main(ActivityThread.java:6776)
 	at android.os.Looper.loop(Looper.java:154)
 	at android.os.Handler.dispatchMessage(Handler.java:102)
 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
 	at android.app.ActivityThread.-wrap14(ActivityThread.java)
 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2937)
 	at android.app.Activity.performStart(Activity.java:6973)
 	at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1256)
 	at android.support.v7.app.e.onStart(AppCompatActivity.java:177)
 	at android.support.v4.app.g.onStart(FragmentActivity.java:16192)
 	at android.support.v4.app.l.q(FragmentManager.java:3181)
 	at android.support.v4.app.l.c(FragmentManager.java:3231)
 	at android.support.v4.app.l.k(FragmentManager.java:2239)
 	at android.support.v4.app.l.a(FragmentManager.java:2332)
 	at android.support.v4.app.l.a(FragmentManager.java:2374)
 	at android.support.v4.app.q.a(FragmentTransition.java:115)
 	at android.support.v4.app.q.a(FragmentTransition.java:1070)
 	at android.support.v4.app.q.a(FragmentTransition.java:1187)
 	at android.support.v4.app.l.a(FragmentManager.java:1377)
 	at android.support.v4.app.Fragment.performCreate(Fragment.java:2246)
 	at android.support.v7.preference.f.onCreate(PreferenceFragmentCompat.java:224)
 	at android.support.v7.preference.m.a(XpPreferenceFragment.java:54)
 	at com.myapp.q.b(SettingsFragment.java:)
 	at android.support.v7.preference.q.a(XpPreferenceManager.java:67)
 	at android.support.v7.preference.h.a(PreferenceInflater.java:112)
 	at android.support.v7.preference.p.a(XpPreferenceInflater.java:103)
 	at android.support.v7.preference.p.a(XpPreferenceInflater.java:293)
 	at android.support.v7.preference.p.a(XpPreferenceInflater.java:293)
 	at android.support.v7.preference.p.a(XpPreferenceInflater.java:293)
 	at android.support.v7.preference.p.a(XpPreferenceInflater.java:293)
 	at android.support.v7.preference.p.a(XpPreferenceInflater.java:4126)
 	at android.support.v7.preference.PreferenceGroup.b(PreferenceGroup.java:194)
 	at android.support.v7.preference.Preference.a(Preference.java:1256)
 	at android.support.v7.preference.Preference.a(Preference.java:6516)
 	at net.xpece.android.support.preference.MultiSelectListPreference.a(MultiSelectListPreference.java:195)
 	at android.support.v7.preference.l.b(XpPreferenceCompat.java:90)
 	at net.xpece.android.support.preference.m.a(SharedPreferencesCompat.java:39)
 	at net.xpece.android.support.preference.m.b(SharedPreferencesCompat.java:52)
 	at org.json.JSONArray.(JSONArray.java:108)
 	at org.json.JSONArray.(JSONArray.java:92)
 	at org.json.JSONTokener.nextValue(JSONTokener.java:97)
 	at org.json.JSONTokener.syntaxError(JSONTokener.java:449)
 org.json.JSONException: End of input at character 0 of 

@consp1racy
Copy link
Owner

Can you say what devices do the crashes come from (model, amdroid version)?

@dirkam
Copy link
Author

dirkam commented Mar 1, 2018

This occurrence was on a Samsung A5 running Android 7.
For the rest, you can find a screenshot attached to a previous comment.

@consp1racy
Copy link
Owner

The stacktrace may be useful. What version of the lib were you using? I'll need to match the line numbers. Thanks

@dirkam
Copy link
Author

dirkam commented Mar 3, 2018

1.3.2
For the MultiSelectListPreference that's all I have.

@consp1racy
Copy link
Owner

First some background on the last error: I used to store string sets as Strings with JSON arrays on Gingerbread. When reading the preference I tried to read it as Set and if it failed, fall back to parsing String as JSON array and reconstruct the Set from that.

Now, wrong data is stored instead of Set so it mistakenly tries to parse it as JSON array from String. The preference contained an empty string it looks. It shouldn't contain a string at all on Android 7.

A String was also stored in the SeekBarPreference.

I don't see where this comes from.

@dirkam
Copy link
Author

dirkam commented May 4, 2018

Got this with the new error reporting stuff.
Support lib 27.1.1 with lib 2.2.0.
This one occured on an S6 Edge with Android 7.0

Couldn't read 'aMultiSelectListPreference' preference as JSON

Non-fatal Exception: org.json.JSONException: End of input at character 0 of 
       at org.json.JSONTokener.syntaxError(JSONTokener.java:449)
       at org.json.JSONTokener.nextValue(JSONTokener.java:97)
       at org.json.JSONArray.(JSONArray.java:92)
       at org.json.JSONArray.(JSONArray.java:108)
       at net.xpece.android.support.preference.SharedPreferencesCompat.getStringSetFromJson(SharedPreferencesCompat.java:66)
       at net.xpece.android.support.preference.SharedPreferencesCompat.getStringSet(SharedPreferencesCompat.java:56)
       at android.support.v7.preference.XpPreferenceCompat.getPersistedStringSet(XpPreferenceCompat.java:90)
       at android.support.v7.preference.XpPreferenceCompat.persistStringSet(XpPreferenceCompat.java:59)
       at net.xpece.android.support.preference.MultiSelectListPreference.setValues(MultiSelectListPreference.java:138)
       at net.xpece.android.support.preference.MultiSelectListPreference.onSetInitialValue(MultiSelectListPreference.java:197)
       at android.support.v7.preference.Preference.dispatchSetInitialValue(Preference.java:6519)
       at android.support.v7.preference.Preference.onAttachedToHierarchy(Preference.java:1257)
       at android.support.v7.preference.PreferenceGroup.addPreference(PreferenceGroup.java:234)
       at android.support.v7.preference.XpPreferenceInflater.android.support.v7.preference.PreferenceGroup.addItemFromInflater(XpPreferenceInflater.java:4166)
       at android.support.v7.preference.XpPreferenceInflater.rInflate(XpPreferenceInflater.java:293)
       at android.support.v7.preference.XpPreferenceInflater.rInflate(XpPreferenceInflater.java:293)
       at android.support.v7.preference.XpPreferenceInflater.rInflate(XpPreferenceInflater.java:293)
       at android.support.v7.preference.XpPreferenceInflater.rInflate(XpPreferenceInflater.java:293)
       at android.support.v7.preference.XpPreferenceInflater.inflate(XpPreferenceInflater.java:103)
       at android.support.v7.preference.PreferenceInflater.inflate$7af30e91(PreferenceInflater.java:112)
       at android.support.v7.preference.XpPreferenceManager.inflateFromResource$6154c3e6(XpPreferenceManager.java:69)
       at .SettingsFragment.android.support.v7.preference.PreferenceFragmentCompat.addPreferencesFromResource(SettingsFragment.java)
       at android.support.v7.preference.XpPreferenceFragment.onCreatePreferences(XpPreferenceFragment.java:56)
       at android.support.v7.preference.PreferenceFragmentCompat.onCreate(PreferenceFragmentCompat.java:224)
       at android.support.v4.app.Fragment.performCreate(Fragment.java:2331)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1386)
       at android.support.v4.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1188)
       at android.support.v4.app.FragmentTransition.calculateFragments(FragmentTransition.java:1071)
       at android.support.v4.app.FragmentTransition.startTransitions(FragmentTransition.java:115)
       at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2380)
       at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
       at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
       at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3248)
       at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3200)
       at android.support.v4.app.FragmentActivity.android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentActivity.java:11195)
       at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
       at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1256)
       at android.app.Activity.performStart(Activity.java:6959)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2890)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2988)
       at android.app.ActivityThread.-wrap14(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1631)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:154)
       at android.app.ActivityThread.main(ActivityThread.java:6682)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

@consp1racy
Copy link
Owner

consp1racy commented May 10, 2018

There are two potential issues here:

1) Reading the preference

Does your MultiSelectListPreference have a default value? Is it an empty string? If so, it should instead

  • point to an empty string array resource, or
  • be equal to @null, which is also the implicit default.

String, even an empty one, cannot be parsed as a Set by the preference framework. I will make this throw as it should in the next version of the library.

2) Writing the preference

This is the non-fatal you reported in the previous comment.

I'll fix the library so it doesn't throw ClassCastException when writing preferences. Framework doesn't throw, my MultiSelectListPreference erroneously did. Thanks for catching it.

@consp1racy
Copy link
Owner

Please try and test the current snapshot and let me know if you encounter any errors.

implementation 'com.github.consp1racy:android-support-preference:7d2c9b3fbb'

@dirkam
Copy link
Author

dirkam commented May 12, 2018

I'll try the snapshot version, though I can't reproduce these so not sure if I'll notice anything.

I don't set a default value in XML. I set the value runtime and here it can happen that I pass a set like this without any value: Set<String> set = new HashSet<>().

@janvalji
Copy link

I have the same problem. Firebase Crashlytics
Ekran Alıntısı

@ammadmunir
Copy link

ammadmunir commented Jun 5, 2020

just uninstall your app and then install it. look like you saved string on that key before.
or change the key or clear app data then check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants