sAleksovski / react-native-android-widget

Build Android Widgets with React Native

Home Page:https://sAleksovski.github.io/react-native-android-widget/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Widget is here but invisible / "empty"

tahola opened this issue · comments

Hello, I followed getting started in the doc (I have a bare project) I can see the widget in the list, add it to my homescreen (with the dimensions I want) but then it just completely invisible.

Capture d’écran 2024-02-24 à 21 36 28
Capture d’écran 2024-02-24 à 21 36 50

Result is the same on a real device and in the emulator, I also did the preview (https://saleksovski.github.io/react-native-android-widget/docs/tutorial/widget-preview) to check and there I can see the widget correctly.

Versions :
"react-native": "0.73.2",
"react-native-android-widget": "^0.11.1",

Any Idea ?

Check your widgetTaskHandler, it should be called when you add the widget to the home screen.

Also it would helpful if you share some logs.

I have nothing in the logs, I tried that but nothing show :

switch (props.widgetAction) {
    case 'WIDGET_ADDED':
      console.log('WIDGET_ADDED');
      props.renderWidget(React.createElement(Widget));
      break;

    case 'WIDGET_UPDATE':
      console.log('WIDGET_UPDATE');
      // Not needed for now
      break;

    case 'WIDGET_RESIZED':
      console.log('WIDGET_RESIZED');
      // Not needed for now
      break;

    case 'WIDGET_DELETED':
      console.log('WIDGET_DELETED');
      // Not needed for now
      break;

    case 'WIDGET_CLICK':
      console.log('WIDGET_CLICK');
      // Not needed for now
      break;

    default:
      console.log('Unknown widget action');
      break;
  }

Even when I click the widget, I can click that invisible square it open the app but no log.

You don't even see 'WIDGET_ADDED' in the logs?

If so, the widgetTaskHandler is not registered correctly.

If you see it, then there is some problem in your widget.

Why are you using React.createElement?
Use

Also, check logcat logs, not just React Native logs.

I just followed the doc, is that what you mean ?

import React from 'react';
import {HelloWidget} from './HelloWidget';

const nameToWidget = {
  HelloWidget: HelloWidget,
};

export async function widgetTaskHandler(props) {
  const widgetInfo = props.widgetInfo;
  const Widget = nameToWidget[widgetInfo.widgetName];

  switch (props.widgetAction) {
    case 'WIDGET_ADDED':
      console.log('WIDGET_ADDED');
      props.renderWidget(<HelloWidget />);
      break;

    case 'WIDGET_UPDATE':
      console.log('WIDGET_UPDATE');
      // Not needed for now
      break;

    case 'WIDGET_RESIZED':
      console.log('WIDGET_RESIZED');
      // Not needed for now
      break;

    case 'WIDGET_DELETED':
      console.log('WIDGET_DELETED');
      // Not needed for now
      break;

    case 'WIDGET_CLICK':
      alert('WIDGET_CLICK');
      console.log('WIDGET_CLICK');
      // Not needed for now
      break;

    default:
      console.log('Unknown widget action');
      break;
  }
}

Do you see WIDGET_ADDED in the logs, since you have the console.log?

If not the widgetTaskHandler is not registered. See https://saleksovski.github.io/react-native-android-widget/docs/tutorial/register-task-handler#register-widget-task-handler

Also check logcat logs

+1 here, I have registered widgetTaskHandler in index.js.

It feels like widgetTaskHandler init is "slow", because widgetTaskHandler will run after a few minutes or seconds (depending on the device)

In my case, Logcat will show a lot of logs initialized for the app first, then widgetTaskHandler.

And another situation I think the OP is facing.
This is from Logcat when I try adding the widget

2024-03-01 11:06:33.788 31739-31994 TrafficStats            com.myapp.myapp                      D  tagSocket(115) with statsTag=0xffffffff, statsUid=-1
2024-03-01 11:06:33.833 31739-31822 WM-WorkerWrapper        com.myapp.myapp                      I  Work [ id=9f6a468c-730f-4c52-88d4-beed1d0d0d77, tags={ com.reactnativeandroidwidget.RNWidgetBackgroundTaskWorker } ] was cancelled
                                                                                                    java.util.concurrent.CancellationException: Task was cancelled.
                                                                                                    	at androidx.work.impl.utils.futures.AbstractFuture.cancellationExceptionWithCause(AbstractFuture.java:1184)
                                                                                                    	at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:514)
                                                                                                    	at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
                                                                                                    	at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:317)
                                                                                                    	at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96)
                                                                                                    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
                                                                                                    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
                                                                                                    	at java.lang.Thread.run(Thread.java:1012)
2024-03-01 11:06:33.863 31739-31748 com.myapp.myapp         com.myapp.myapp                      I  This is non sticky GC, maxfree is 8388608 minfree is 2097152
2024-03-01 11:06:36.810 31739-32005 TrafficStats            com.myapp.myapp                      D  tagSocket(6) with statsTag=0xffffffff, statsUid=-1


Do you see this on production build?

How can I reproduce it?

Hi guys!

I had the same problem; the solution was adding the renderWidget method in "WIDGET_UPDATE".

In my case, the widget disappeared only the first time when I selected it.

switch (props.widgetAction) {
    case 'WIDGET_ADDED':
      console.log('WIDGET_ADDED');
      props.renderWidget(React.createElement(Widget));
      break;

    case 'WIDGET_UPDATE':
      console.log('WIDGET_UPDATE');
      props.renderWidget(React.createElement(Widget));
      // Not needed for now
      break;

    case 'WIDGET_RESIZED':
      console.log('WIDGET_RESIZED');
      // Not needed for now
      break;

    case 'WIDGET_DELETED':
      console.log('WIDGET_DELETED');
      // Not needed for now
      break;

    case 'WIDGET_CLICK':
      console.log('WIDGET_CLICK');
      // Not needed for now
      break;

    default:
      console.log('Unknown widget action');
      break;
}

Please give the same name inside app.config.js such as you have given here above const nameToWidget = { HelloWidget: HelloWidget, };
give the key name HelloWidget
` widgets: [
{
name: "HelloWidget", // This name will be the name with which we will reference our widget.
label: "Widget label",
minHeight: "120dp",
minWidth: "300dp",
description: "This is my first widget 1",
previewImage: "./assets/images/logo.png",

},`
@tahola and @leoguanco 

@abdul-wajid-afridi isn't that for expo project ? I am on bare project.

Hello @sAleksovski, I'm encountering a similar problem with Expo. When I install the widget using an APK, it appears transparent. The same issue occurs when the app is running on the Metro bundler, but it eventually updates after some time. I've attached the log below for your review. As you can see, the "WIDGET_ADDED" action is initiated, but an error arises when attempting to fetch the image.

Worker result SUCCESS for Work [ id=c8dae032-0120-466a-8ab0-f3dbce9a43bb, tags={ com.reactnativeandroidwidget.RNWidgetBackgroundTaskWorker } ]
{"widgetInfo":{"height":214,"widgetName":"Widgets","screenInfo":{"screenWidthDp":393,"density":2.75,"screenHeightDp":737,"densityDpi":440},"widgetId":91,"width":351},"widgetAction":"WIDGET_ADDED","clickActionData":{}}
java.lang.ClassCastException: sun.net.www.protocol.file.FileURLConnection cannot be cast to java.net.HttpURLConnection
	at com.reactnativeandroidwidget.builder.widget.utils.ResourceUtils.getInputStreamFromSource(ResourceUtils.java:102)
	at com.reactnativeandroidwidget.builder.widget.utils.ResourceUtils.getBitmap(ResourceUtils.java:44)
	at com.reactnativeandroidwidget.builder.widget.ImageWidget.getBitmapFromURL(ImageWidget.java:44)
	at com.reactnativeandroidwidget.builder.widget.ImageWidget.applyProps(ImageWidget.java:27)
	at com.reactnativeandroidwidget.builder.widget.BaseWidget.<init>(BaseWidget.java:36)
	at com.reactnativeandroidwidget.builder.widget.BaseWidget.<init>(BaseWidget.java:40)
	at com.reactnativeandroidwidget.builder.widget.ImageWidget.<init>(ImageWidget.java:17)
	at com.reactnativeandroidwidget.builder.WidgetFactory.getBaseWidget(WidgetFactory.java:104)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildWidget(WidgetFactory.java:71)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildChildren(WidgetFactory.java:125)
	at com.reactnativeandroidwidget.builder.WidgetFactory.getBaseWidget(WidgetFactory.java:108)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildWidget(WidgetFactory.java:71)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildChildren(WidgetFactory.java:125)
	at com.reactnativeandroidwidget.builder.WidgetFactory.getBaseWidget(WidgetFactory.java:108)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildWidget(WidgetFactory.java:71)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildChildren(WidgetFactory.java:125)
	at com.reactnativeandroidwidget.builder.WidgetFactory.getBaseWidget(WidgetFactory.java:108)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildWidget(WidgetFactory.java:71)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildChildren(WidgetFactory.java:125)
	at com.reactnativeandroidwidget.builder.WidgetFactory.getBaseWidget(WidgetFactory.java:108)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildWidget(WidgetFactory.java:71)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildChildren(WidgetFactory.java:125)
	at com.reactnativeandroidwidget.builder.WidgetFactory.getBaseWidget(WidgetFactory.java:108)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildWidget(WidgetFactory.java:71)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildChildren(WidgetFactory.java:125)
	at com.reactnativeandroidwidget.builder.WidgetFactory.getBaseWidget(WidgetFactory.java:114)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildWidget(WidgetFactory.java:71)
	at com.reactnativeandroidwidget.builder.WidgetFactory.buildWidgetFromRoot(WidgetFactory.java:41)
	at com.reactnativeandroidwidget.RNWidget.drawWidget(RNWidget.java:62)
	at com.reactnativeandroidwidget.AndroidWidgetModule.drawWidgetById(AndroidWidgetModule.java:41)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
	at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:149)
	at com.facebook.jni.NativeRunnable.run(Native Method)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
	at android.os.Looper.loopOnce(Looper.java:205)
	at android.os.Looper.loop(Looper.java:294)

Can you share how you are using the ImageWidget?

Sure @sAleksovski . Please find the code below.

<ImageWidget
    image={require('../../assets/scan.png')}
    imageWidth={30}
    imageHeight={30}
/>

I'm not sure if all the comments here point to the same issue.

Please share a a repo where I can reproduce the issue, along with steps how to reproduce it.
Without it I'm not sure I can help.

Based on my investigations, it appears that the issue arises from the way Expo handles assets during the build process. Expo stores the assets in the .expo-internal folder and bundles them with the app.

Line 36 in com/reactnativeandroidwidget/builder/widget/utils/ResourceUtils.java

image

The source argument is returned as a file path string. This bypasses the isResource and source.startsWith("data:") conditions, which leads to the execution of InputStream input = getInputStreamFromSource(source);. This method attempts to cast the file path to an HTTP URL.

  private static InputStream getInputStreamFromSource(String source) throws IOException {
      URL url = new URL(source);
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setDoInput(true);
      connection.connect();
      return connection.getInputStream();
  }

The getInputStreamFromSource method tries to open a connection to the provided source URL and return an InputStream. However, if the source is a file path (as it is when Expo bundles the assets), this will fail because it's trying to treat a file path as a URL. This results in a java.io.FileNotFoundException.

Is there a way to generate the build while avoiding the expo eject command, as we aim to preserve the integrity of the native build?

I'm not sure if all the comments are related.

Above there is java.util.concurrent.CancellationException: Task was cancelled. exception, while you get java.io.FileNotFoundException.

Please share a a repo where I can reproduce the issue, along with steps how to reproduce it.
Without it I'm not sure I can help.

I'm not sure if all the comments are related.

Above there is java.util.concurrent.CancellationException: Task was cancelled. exception, while you get java.io.FileNotFoundException.

Please share a a repo where I can reproduce the issue, along with steps how to reproduce it.
Without it I'm not sure I can help.

Apology for copying the incorrect the error message 😅 . The error supposed to be java.lang.ClassCastException: sun.net.www.protocol.file.FileURLConnection cannot be cast to java.net.HttpURLConnection.

You may try to reproduce the issue by using the repo below. Just to highlight it again, the issue only happen in release build when I import the image as below.

<ImageWidget
  image={require("../../../assets/favicon.png")}
  imageWidth={widgetImageSize}
  imageHeight={widgetImageSize}
/>

https://github.com/ytl-RaymondLau/react-native-widget-demo

@ytl-RaymondLau thanks for creating the repo, I'll take a look.

The issue from @ytl-RaymondLau is solved, more details are present in his repo.

As for @tahola @longb1997 , I still don't know how to reproduce the problem, so I'll close this issue.
Please open another one with an example repo similar to the one from @ytl-RaymondLau , with clear steps how I can reproduce the issue.