Android WebView lacks several features due to inability to subclass
Describe the bug Currently, Android WebView lacks an onload handler.
To Reproduce Steps to reproduce the behavior:
- Create a Toga app that uses WebView
- 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).
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.
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 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.
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 =)
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.
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).