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

JavaAndroidNumberpicker

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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).

Solution 2 - Java

This how I am implementing NumberPicker in my application, and it is working well for me:

java code , in your onCreate() :

NumberPicker numberpicker = (NumberPicker) findViewById(R.id.np_from);
numberpicker.setMaxValue(100);
numberpicker.setMinValue(16);

XML code :

           <NumberPicker
            android:id="@+id/np_from"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:width="100dip" />

I hope it helps.

Solution 3 - Java

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r1/android/view/View.java#View.clearAccessibilityFocus%28%29

Looking at all 4.3 versions it's pretty clear the code is most likely calling clearAccessibilityFocus().

Assuming accurate line numbers I'd search in there for a likely cause. Nothing jumps out at me, in fact most of the accesses have good null checks.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3145914View Question on Stackoverflow
Solution 1 - JavaEugen PechanecView Answer on Stackoverflow
Solution 2 - Javaahmed_khan_89View Answer on Stackoverflow
Solution 3 - Javaggb667View Answer on Stackoverflow