Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NPE in ChangeCurrentByOneFromLongPressCommand (on Samsung devices w/ Android 4.3)

Using a couple android.widget.NumberPicker in my Android App view and I get the following message when I hold down on one of the numbers arrows:-

FATAL EXCEPTION: main 
java.lang.NullPointerException at android.widget.NumberPicker$ChangeCurrentByOneFromLongPressCommand.run(NumberPicker.java:2245)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5419)

Anyone got any ideas on how I can stop this problem?

UPDATE: From the comments so far, it seems that this exception only happened on Samsung devices with Android 4.3.

like image 831
user3145914 Avatar asked Dec 30 '13 09:12

user3145914


1 Answers

So the Samsung NumberPicker is slightly different from AOSP. The code for ChangeCurrentByOneFromLongPressCommand class has some extra logic including

if (!mIsDeviceDefault) {
    // ...
} else if (mDecrementButton.isShown() || mIncrementButton.isShown()) {
    // ...
  • where mIsDeviceDefault is true when you're using one of the Theme.DeviceDefault themes (which is the default theme for apps starting Android 4.x)
  • where mDecrementButton and mIncrementButton are null if mHasSelectorWheel is true, which happens if the layout resource ID for NumberPicker specified by its style is one of
    • DEFAULT_LAYOUT_RESOURCE_ID / @layout/number_picker
    • TOUCHWIZ_DARK_LAYOUT_RESOURCE_ID / @layout/tw_number_picker_dark
    • TOUCHWIZ_LIGHT_LAYOUT_RESOURCE_ID / @layout/tw_number_picker_light

which suggests that this would happen all the time.

Here are all the possible styles:

<style name="Widget.NumberPicker">
    <item name="orientation">1</item>
    <item name="fadingEdge">2000</item>
    <item name="fadingEdgeLength">50dp</item>
    <item name="internalLayout">@layout/number_picker</item>
</style>

<style name="Widget.Holo.NumberPicker">
    <item name="solidColor">@color/transparent</item>
    <item name="internalLayout">@layout/number_picker_with_selector_wheel</item>
    <item name="selectionDivider">@drawable/numberpicker_selection_divider</item>
    <item name="selectionDividerHeight">2dp</item>
    <item name="selectionDividersDistance">48dp</item>
    <item name="internalMaxHeight">180dp</item>
    <item name="internalMinWidth">64dp</item>
    <item name="virtualButtonPressedDrawable">?attr/selectableItemBackground</item>
</style>

<style name="Widget.DeviceDefault.NumberPicker">
    <item name="internalLayout">@layout/tw_number_picker_dark</item>
</style>

<style name="Widget.DeviceDefault.Light.NumberPicker">
    <item name="internalLayout">@layout/tw_number_picker_light</item>
</style>

Source: Downloaded Android 4.3 firmware for Samsung Galaxy S3, extracted framework files using ext4 unpacker, decompiled framework.jar and framework2.jar using Universal Deodexer V5, explored the results including framework-res.apk using JADX.

How to fix

After your NumberPicker is constructed use reflection to check if ImageButton mDecrementButton and ImageButton mIncrementButton are null. If they are use reflection to set them each to a new ImageButton(numberPicker.getContext()).

Only apply this logic when running on one of the affected devices (check Build constants).

like image 62
Eugen Pechanec Avatar answered Nov 12 '22 23:11

Eugen Pechanec