toga icon indicating copy to clipboard operation
toga copied to clipboard

Android WebView lacks several features due to inability to subclass

Open paulproteus opened this issue 5 years ago • 6 comments

Describe the bug Currently, Android WebView lacks an onload handler.

To Reproduce Steps to reproduce the behavior:

  1. Create a Toga app that uses WebView
  2. Add an onload handler (as the webview demo does!)

Expected behavior

Expect the onload handler to be fired when the page finishes loading.

Rationale

Android's WebView implementation needs an instance the WebViewClient class, or an instance of a WebViewClient subclass, in order to send notifications of pages completing loading.

rubicon-java doesn't support subclassing Java classes.

If it did, the code might look like:

from ..libs import android_widgets

class TogaWebViewClient(android_widgets.WebViewClient):
    def __init__(self, on_load=None):
        super().__init__()
        self._on_load = on_load

    class onPageFinished(self, _webview, _url):
        if self._on_load:
            self._on_load()

This depends on https://github.com/beeware/rubicon-java/issues/25 (or something like it).

paulproteus avatar Aug 11 '20 04:08 paulproteus

The blocking issue here is a big project and it's appropriate to make helper java classes to work around issues until the blocking issue is resolved.

xloem avatar Dec 19 '20 12:12 xloem

One possible solution to issues like this would be to add wrappers for all the android api's abstract base classes to the android template. The wrappers would take java interfaces in their constructors and pass off their abstract method calls to the interfaces. This solution could be implemented by somebody who didn't know the project well.

xloem avatar Jan 08 '21 16:01 xloem

@xloem Yes, this is a possible approach; however, it's an approach that I'd rather avoid. Baking wrappers for specific classes into the Android template would make the template GUI toolkit specific - you would only be able to extend the classes that we've pre-declared. Consider the case of wrapping a third party Android library, or an Android base library that Toga doesn't require.

I would be more inclined to support a metadata-based approach which allows toga-android to provide/include a jar file that contains class implementations that can be wrapped, and metadata in the toga-android wheel/egg-info that briefcase can use to obtain/install that jar file as needed in a generic Android template.

Better still would be a mechanism for that lets the Android template, or a template post-processing step, roll out the base classes based on a metadata declaration in the toga-android package. Post-processing is a feature that has been requested in other contexts (e.g., to do asset processing), so this could be a natural fit.

freakboy3742 avatar Jan 08 '21 23:01 freakboy3742

Thanks for your response. In Kivy their solution was to expose in a variable the android java source path, so files could be copied into it during build. Natural fits are always good though, you want as many needed birds with your small stone as you can get =)

xloem avatar Jan 24 '21 16:01 xloem

BeeWare now uses Chaquopy on Android, which does support subclassing Java classes in Python code (https://github.com/beeware/rubicon-java/discussions/75#discussioncomment-3224352). However, it still requires some configuration in the build.gradle file to list which modules the classes can be found in. I've created https://github.com/chaquo/chaquopy/issues/881 to track the idea of moving this to the package metadata.

mhsmith avatar Jun 12 '23 15:06 mhsmith

This also affects the WebChromeClient class, which is required to show JavaScript alert dialogs, or file upload dialogs (#2173). The latter dialog could probably be shared with the general file picker dialog (#1158).

mhsmith avatar Nov 14 '23 11:11 mhsmith