RMatt
RMatt

Reputation: 61

NullPointerException in SupportAppCompat-v7 Library on API 15

A NullPointerException is thrown in the SupportAppCompat library. It seems to happen only for devices running on API 15 (IceCreamSandwich). API versions from 16 to 22 work without any issue.

Any ideas on what could cause this crash?

Thank you for your time and possible answers!

Here's the stacktrace:

java.lang.NullPointerException
       at android.graphics.drawable.LayerDrawable$LayerState.(LayerDrawable.java:625)
       at android.graphics.drawable.LayerDrawable.createConstantState(LayerDrawable.java:107)
       at android.graphics.drawable.LayerDrawable.(LayerDrawable.java:99)
       at android.graphics.drawable.LayerDrawable$LayerState.newDrawable(LayerDrawable.java:655)
       at android.content.res.Resources.getCachedDrawable(Resources.java:2052)
       at android.content.res.Resources.loadDrawable(Resources.java:1943)
       at android.content.res.Resources.getDrawable(Resources.java:707)
       at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:321)
       at android.support.v7.internal.widget.TintManager.getDrawable(TintManager.java:126)
       at android.support.v7.internal.view.menu.MenuItemImpl.getIcon(MenuItemImpl.java:422)
       at android.support.v7.internal.view.menu.ActionMenuItemView.initialize(ActionMenuItemView.java:120)
       at android.support.v7.widget.ActionMenuPresenter.bindItemView(ActionMenuPresenter.java:184)
       at android.support.v7.internal.view.menu.BaseMenuPresenter.getItemView(BaseMenuPresenter.java:182)
       at android.support.v7.widget.ActionMenuPresenter.getItemView(ActionMenuPresenter.java:170)
       at android.support.v7.widget.ActionMenuPresenter.flagActionItems(ActionMenuPresenter.java:458)
       at android.support.v7.internal.view.menu.MenuBuilder.flagActionItems(MenuBuilder.java:1129)
       at android.support.v7.internal.view.menu.BaseMenuPresenter.updateMenuView(BaseMenuPresenter.java:91)
       at android.support.v7.widget.ActionMenuPresenter.updateMenuView(ActionMenuPresenter.java:207)
       at android.support.v7.internal.view.menu.MenuBuilder.dispatchPresenterUpdate(MenuBuilder.java:279)
       at android.support.v7.internal.view.menu.MenuBuilder.onItemsChanged(MenuBuilder.java:1021)
       at android.support.v7.internal.view.menu.MenuBuilder.startDispatchingItemsChanged(MenuBuilder.java:1044)
       at android.support.v7.internal.app.ToolbarActionBar.populateOptionsMenu(ToolbarActionBar.java:463)
       at android.support.v7.internal.app.ToolbarActionBar$1.run(ToolbarActionBar.java:68)
       at android.os.Handler.handleCallback(Handler.java:605)
       at android.os.Handler.dispatchMessage(Handler.java:92)
       at android.os.Looper.loop(Looper.java:137)
       at android.app.ActivityThread.main(ActivityThread.java:4517)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:511)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
       at dalvik.system.NativeStart.main(NativeStart.java)

Upvotes: 2

Views: 1395

Answers (2)

Nikola Despotoski
Nikola Despotoski

Reputation: 50578

@RMatt Answer is correct, if you try to mutate LayerDrawable and make changes programmatically, you will end up in the mentioned crash.

Here is example how I solved it for my case.

public static void setRoundedCornerDrawableInLayerList(@NonNull Context context, @NonNull View view, int layerIndex, float radius) {
        Drawable background = view.getBackground();
        if (background != null && background instanceof LayerDrawable) {
            LayerDrawable layers = (LayerDrawable) background.mutate();
            Drawable d = layers.getDrawable(0);
            if (d instanceof BitmapDrawable) {
                int id = layers.getId(layerIndex);
                BitmapDrawable bitmapDrawable = (BitmapDrawable) d;
                RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), bitmapDrawable.getBitmap());
                roundedBitmapDrawable.setCornerRadius(radius);
                if (isJB()) {
                    layers.setDrawableByLayerId(id, roundedBitmapDrawable);
                    layers.invalidateSelf();
                } else {
                    int count = layers.getNumberOfLayers();
                    Drawable[] layerArray = new Drawable[count];
                    for (int i = 0; i < count; i++) {
                        if (i == layerIndex) {
                            layerArray[i] = roundedBitmapDrawable;
                        } else {
                            layerArray[i] = layers.getDrawable(i);
                        }
                    }
                    LayerDrawable layerDrawable = new LayerDrawable(layerArray);
                    setBackgroundDrawable(view, layerDrawable);
                }
            }

        }
    }

You can see that for versions above JellyBean I'm simply mutating the layer drawable and replacing the drawable with another one, but for lower versions I create new LayerDrawable from existing layers.

Upvotes: 1

RMatt
RMatt

Reputation: 61

After a lot of time lost searching for the answer, I have located the source of my problem.

I use a LayerDrawable in a MenuItem and apparently, the LayerDrawable cannot be modified after being set once on API 15. Modifying it causes the crash.

I hope this would help if anyone come across this issue.

Upvotes: 4

Related Questions