Bug in Textbox object, empty string crashes app

When a textbox gets a return value that is empty/empty string, the app crashes.
You have to use a workaround. The app will crash or in the companion it warns with an 'undefined' warning when getting an empty string as value.

The workaround is to test on 'is empty'. In this case 'data' is the return value of an extension and it returned "" (empty string).

Workaround

textbox_workaround

The label has no problem with an empty return string.

What extension? Is the extension is returning empty string? Or null? If null It will crash.

No issues here, with companion 2.70 on a real device

image

Tested with textbox starting as empty and with a value.

Are you certain it is just a string being returned, not an object ?

That's a bug in the companion app, when specific error conditions occur, the companion app fails to handle it, thus crashing the application.

Perhaps adding this may help?


If that's the case, I believe YailRuntimeError should have been thrown.

It is probably the case.

1 Like
  • It happens both in the Companion app and in the apk.
  • Debugging is possible but I found the Textbox bug already.
  • It is a string for sure, which is returned, because the password is empty
    • if ( password == null || data == null || password.isEmpty()  || data.isEmpty() || aesKeySize <= 0) {
       // If any of the parameters is empty or aesKeySize is not valid, return an empty string
       return "";
      
  • It is an empty string. And the Label has no problem at all with the same result.

(Canned Reply: ABG- Export & Upload .aia)
Export your .aia file and upload it here.
export_and_upload_aia

Give us some thing that crashes

In all textboxes I use the workaround by testing with string function 'is empty'.
Try it without the workaround to cause an error.
AESGCM_V1.0.4.aia (632.1 KB)

Or add an extension function: isNull()

  @SimpleFunction(description = "Returns empty string if data is null, otherwise it returns data.")    
  public String isNull(String data) {
        return (data == null) ? "" : data;
  }

I'm not able to reproduce the error...I have removed all the "protections" and it doesn't crash....

Is there any specific scenario or assumption I am not considering?

(I'm testing with Companion AI 2.70)

Using companion AI 2.70 too.
Error arises in Android 8.0, 8.1 and 14

Android 14 here....

Non reproducable "bug", let's call it a glitch :laughing:
Thanks for testing @Ramon

Just use ADB to find out the error log.

What is the actual value of data in this case? I also cannot replicate by passing an empty string to the textbox. If when you are saying empty, you mean null, App Inventor's design is that you should never return a null to the blocks level. If the extension is returning null then it is violating App Inventor's design constraints and the behavior is undefined.

Probably the thing causing the crash is not the textbox, could be something else.

On a closer look into the blocks, the problem seems to be with the extension, not related to the internal components. I believe the extension is trying to dispatch events on async threads (where you cannot touch UI)

form.runOnUiThread({...})

should solve the issue

It returns an empty string in Java, from the extension, not null.

  •   if ( password == null || data == null || password.isEmpty()  || data.isEmpty() || aesKeySize <= 0) {
      	// If any of the parameters is empty or aesKeySize is not valid, return an empty string
      	return "";
      }
    

Even when I disable the Async blocks, it gives the error.
What needs to be changed @Kumaraswamy?

@SimpleFunction(description = "Asynchronously encrypt data using AES/GCM/NoPadding. Raises AsyncEncrypted")
public void AsyncEncrypt(final String password, final String data, final int aesKeySize) {
    AsynchUtil.runAsynchronously(new Runnable() {
        @Override
        public void run() {
            final String encryptedData = Encrypt(password, data, aesKeySize);
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    AsyncEncrypted(encryptedData);
                }
            });
        }
    });
}