react-native-android-widget icon indicating copy to clipboard operation
react-native-android-widget copied to clipboard

Crashing App while updating widgets

Open ashishmangukiya opened this issue 10 months ago • 8 comments

Exception java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference at com.reactnativeandroidwidget.ListRemoteViewsFactory.getViewAt (RNWidgetCollectionService.java:143) at android.widget.RemoteViewsService$RemoteViewsFactoryAdapter.getViewAt (RemoteViewsService.java:164) at com.android.internal.widget.IRemoteViewsFactory$Stub.onTransact (IRemoteViewsFactory.java:183) at android.os.Binder.execTransactInternal (Binder.java:1290) at android.os.Binder.execTransact (Binder.java:1249)

ashishmangukiya avatar Mar 15 '25 14:03 ashishmangukiya

How did you get this error? What does your widget code look like? How can I reproduce this?

sAleksovski avatar Mar 15 '25 17:03 sAleksovski

I have received more than 750 events in the sentry.io dashboard. Looks like issue with the width number in the widgets like may be width coming null or undefined sometimes. Is it possible to receive crashes if the width is null or undefined while updating widgets?

I noticed the issue when keeping the widgets on other home screen tab and after a day started my app and started a timer and moved my app in background and got crashed

My below code

<FlexWidget style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', flexGap: 8, width: widgetInfo.width - 16, paddingBottom: 8, }} > <FlexWidget style={{ backgroundColor: '#80808033', width: widgetInfo.width - 50 - 16, height: 'wrap_content', borderRadius: 6, }} > <FlexWidget style={{ backgroundColor: rgbaToHex(color), height: 12, width: ((widgetInfo.width - 16 - 50) * finalScore) / 100, borderRadius: 6, justifyContent: 'flex-end', }} > <TextWidget style={{ fontSize: 0 }} text='0' /> </FlexWidget> </FlexWidget> <FlexWidget style={{ width: 50, }} > <TextWidget style={{ fontSize: 12, fontFamily: fontFamily.semiBold, letterSpacing: 0.6, color: theme.primaryOpoTxt == 'black' ? '#FFFFFF' : '#000000', textAlign: 'right', }} text={Math.round(finalScore).toString()} /> </FlexWidget> </FlexWidget>

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="240dp" android:minHeight="120dp"

android:updatePeriodMillis="1800000"

android:initialLayout="@layout/rn_widget"

android:previewImage="@drawable/score_preview"


android:resizeMode="horizontal|vertical"

android:configure="com.android.app.WidgetConfigurationActivity"
android:widgetFeatures="reconfigurable"

android:widgetCategory="home_screen">

Can you please check once?

ashishmangukiya avatar Mar 16 '25 04:03 ashishmangukiya

The crash error mentions list, but your widget does not have a list.

I don't think that is the correct widget

sAleksovski avatar Mar 16 '25 07:03 sAleksovski

import React from 'react';
import { FlexWidget, ListWidget, TextWidget } from 'react-native-android-widget';
import { getLastSevenDays } from '../../components/habits/listing/active';
import { fontFamily, shortWeekDays } from '../../constant';
import { DateTime } from 'luxon';
import { clickOnDay, getFilteredStyle, rgbaToHex, verifyHabitCopy } from '../../helper';
import { getColor } from '../../storage/mmkv-storage';

export const CounterWidget = ({ list = [], lang, localization, theme, widgetInfo, isPro }) => {
  let obj = {
    sun: 'S',
    mon: 'M',
    tue: 'T',
    wed: 'W',
    thu: 'T',
    fri: 'F',
    sat: 'S',
    sun: 'S',
  };
  const color = getColor();
  const currentDate = DateTime.now().toFormat('dd/MM/yyyy');
  const last7Days = getLastSevenDays();

  return isPro ? (
    list.length > 0 ? (
      <FlexWidget
        style={{
          height: 'match_parent',
          width: 'match_parent',
          padding: 8,
          backgroundColor: theme.primaryOpoTxt == 'black' ? '#1A1A1A' : '#FFFFFF',
        }}
      >
        <FlexWidget
          style={{ flexDirection: 'row', paddingLeft: 100, justifyContent: 'space-between', width: 'match_parent' }}
        >
          {last7Days.map((day, index) => {
            return (
              <FlexWidget
                style={{
                  width: 'wrap_content',
                  width: (widgetInfo.width - 116) / 7,
                  alignItems: 'center',
                }}
                key={index}
              >
                <TextWidget
                  style={{
                    color: theme.primaryOpoTxt == 'black' ? '#FFFFFF' : '#000000',
                    fontSize: 8,
                    width: 'wrap_content',
                    textAlign: 'center',
                  }}
                  text={
                    lang == 'en'
                      ? obj[shortWeekDays[DateTime.fromFormat(day, 'dd/MM/yyyy').weekday - 1]]
                      : localization[shortWeekDays[DateTime.fromFormat(day, 'dd/MM/yyyy').weekday - 1]]
                  }
                />
              </FlexWidget>
            );
          })}
        </FlexWidget>
        <ListWidget
          style={{
            width: 'match_parent',
            padding: 8,
            backgroundColor: theme.primaryOpoTxt == 'black' ? '#1A1A1A' : '#FFFFFF',
            flex: 1,
          }}
        >
          {list.map((habit, i) => (
            <FlexWidget
              key={i}
              style={{
                width: 'match_parent',
                flexDirection: 'row',
                paddingVertical: 8,
                alignItems: 'center',
              }}
            >
              <TextWidget
                style={{
                  width: 100,
                  fontFamily: fontFamily.regular,
                  color: theme.primaryOpoTxt == 'black' ? '#FFFFFF' : '#000000',
                }}
                truncate='END'
                maxLines={1}
                text={habit.name}
              />
              <FlexWidget style={{ justifyContent: 'space-between', flexDirection: 'row' }}>
                {last7Days.map((day, index) => {
                  const style = verifyHabitCopy(habit, currentDate, day)
                    ? getFilteredStyle(habit, day, currentDate, theme)
                    : null;
                  return (
                    <FlexWidget
                      style={{
                        width: 'wrap_content',
                        width: (widgetInfo.width - 116) / 7,
                        alignItems: 'center',
                        justifyContent: 'center',
                      }}
                      key={index}
                    >
                      <FlexWidget
                        style={{
                          width: 24,
                          height: 24,
                          alignItems: 'center',
                          justifyContent: 'center',
                          borderRadius: 12,
                          backgroundColor: style ? rgbaToHex(style.backgroundColor) : rgbaToHex(theme.newBorderColor),
                          borderColor: style
                            ? ['white', 'black'].includes(style.borderColor)
                              ? style.borderColor == 'white'
                                ? '#FFFFFF'
                                : '#000000'
                              : rgbaToHex(style.borderColor)
                            : rgbaToHex(theme.newBorderColor),
                          borderWidth: 1.5,
                        }}
                        clickAction={
                          style &&
                          DateTime.fromFormat(currentDate, 'dd/MM/yyyy') >= DateTime.fromFormat(day, 'dd/MM/yyyy')
                            ? habit.progressType == 0
                              ? `${habit.id},${day}`
                              : 'OPEN_URI'
                            : ''
                        }
                        clickActionData={
                          style &&
                          DateTime.fromFormat(currentDate, 'dd/MM/yyyy') >= DateTime.fromFormat(day, 'dd/MM/yyyy')
                            ? {
                                uri: `habitgenius://widgetAction?id=${habit.id}&date=${day}&actionType=${clickOnDay(habit, currentDate, day)}`,
                              }
                            : {}
                        }
                      >
                        <TextWidget
                          style={{
                            fontFamily: fontFamily.regular,
                            fontSize: 10,
                            color: '#000000',
                            ...(style && style.borderColor == theme.primaryTxt
                              ? { color: theme.primaryTxt == 'white' ? '#FFFFFF' : '#000000' }
                              : null),
                            ...(!style ? { color: rgbaToHex(theme.icon) } : null),
                          }}
                          text={DateTime.fromFormat(day, 'dd/MM/yyyy').day.toString()}
                        />
                      </FlexWidget>
                    </FlexWidget>
                  );
                })}
              </FlexWidget>
            </FlexWidget>
          ))}
        </ListWidget>
      </FlexWidget>
    ) : (
      <FlexWidget
        style={{
          height: 'match_parent',
          width: 'match_parent',
          padding: 8,
          backgroundColor: theme.primaryOpoTxt == 'black' ? '#1A1A1A' : '#FFFFFF',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        <TextWidget
          style={{
            color: theme.primaryOpoTxt == 'black' ? '#FFFFFF' : '#000000',
            fontFamily: fontFamily.semiBold,
            fontSize: 16,
          }}
          text={localization['No active habits.']}
        />
      </FlexWidget>
    )
  ) : (
    <FlexWidget
      style={{
        height: 'match_parent',
        width: 'match_parent',
        padding: 8,
        backgroundColor: theme.primaryOpoTxt == 'black' ? '#1A1A1A' : '#FFFFFF',
        alignItems: 'center',
        justifyContent: 'center',
      }}
    >
      <FlexWidget
        style={{
          padding: 16,
          backgroundColor:
            theme.secondaryBackground == 'white'
              ? rgbaToHex(theme.newBorderColor)
              : rgbaToHex(theme.secondaryBackground),
          alignItems: 'center',
          borderRadius: 8,
        }}
      >
        <TextWidget
          style={{
            color: theme.primaryOpoTxt == 'black' ? '#FFFFFF' : '#000000',
            fontFamily: fontFamily.semiBold,
            fontSize: 18,
          }}
          text='HabitGenius'
        />
        <TextWidget
          style={{
            color: color,
            fontFamily: fontFamily.semiBold,
            fontSize: 22,
          }}
          text='Pro'
        />
      </FlexWidget>
    </FlexWidget>
  );
};

ashishmangukiya avatar Mar 16 '25 08:03 ashishmangukiya

@sAleksovski The Above comment has the list

ashishmangukiya avatar Mar 16 '25 08:03 ashishmangukiya

This library works by generation images of the widget defined by jsx, and displaying that image in the widget on the home screen.

It also generated a separate image for each list item, and stores it on the device for future reading.

You have an error where it fails to read that stored image. Did you clean the apps cache or something similar? Do you get some error in the log while trying to save the image (by updating the widget)?

sAleksovski avatar Mar 16 '25 21:03 sAleksovski

HI @sAleksovski Yes, I am receiving the above error while updating the widget. currently, not able to reproduce the issue now but receiving events in senty.io. No, I have not cleared any cache in my app.

ashishmangukiya avatar Mar 18 '25 05:03 ashishmangukiya

Hi @ashishmangukiya Without steps to reproduce I cannot debug the issue.

sAleksovski avatar Apr 08 '25 17:04 sAleksovski

I'm closing this since I cannot reproduce it. I had a widget with a list on my home screen for more than a month, without any crashes.

Feel free to reopen the issue if you can reproduce it again.

sAleksovski avatar May 16 '25 21:05 sAleksovski