I've successfully attached WebView to my Kivy app following Kivy wiki instructions. It works as expected, but I'd like to deattach and return to my normal Kivy ui. How to I do that?
I've tried to explore WebView documentation, accessing it's methods (the WebView.destroy() complains about destroying a WebView that's still attached), it's parent methods (I'm not even sure if that's the way to go), but I couldn't get rid of the WebView.
Ok, I'm not sure whether this is the best solution, or clean enough, but the only one I know that works. While it works and seems stable, it needs further testing by someone with better knowledge of Kivy and Android API itself.
if platform == 'android':
from jnius import autoclass
from android.runnable import run_on_ui_thread
WebView = autoclass('android.webkit.WebView')
WebViewClient = autoclass('android.webkit.WebViewClient')
activity = autoclass('org.renpy.android.PythonActivity').mActivity
else:
import webbrowser
def run_on_ui_thread(func):
''' just for desktop compatibility '''
return func
class MyScreen(Screen):
view_cached = None # make these object properties?
webview = None
wvc = None # not even needed probably
code = StringProperty() # this property triggers webview to close
url_to_load = None
def on_enter(self):
if platform == 'android':
Clock.schedule_once(self.create_webview, 0) # probably doesn't need clocked call (because decorators will make sure
# function runs on correct thread), but leaving it until tested properly
else:
webbrowser.open_new(self.url_to_load) # on desktop just run the webbrowser
@run_on_ui_thread
def on_code(self, *args):
''' runs when you are ready to detach WebView '''
self.detach_webview()
@run_on_ui_thread
def create_webview(self, *args):
''' attaching webview to app '''
if self.view_cached is None:
self.view_cached = activity.currentFocus # caches current view (the one with kivy) as a view we want to go back to; currentFocus or getCurrentFocus() works
self.webview = WebView(activity)
settings = self.webview.getSettings()
settings.setJavaScriptEnabled(True) # enables js
settings.setUseWideViewPort(True) # enables viewport html meta tags
settings.setLoadWithOverviewMode(True) # uses viewport
settings.setSupportZoom(True) # enables zoom
settings.setBuiltInZoomControls(True) # enables zoom controls
self.wvc = WebViewClient()
self.webview.setWebViewClient(self.wvc)
activity.setContentView(self.webview)
self.webview.loadUrl(self.url_to_load)
@run_on_ui_thread
def key_back_handler(self, *args):
''' sketch for captured "key back" event (in App), not tested properly '''
if self.webview:
if self.webview.canGoBack() == True:
self.webview.goBack()
else:
self.detach_webview()
Clock.schedule_once(self.quit_screen, 0)
else:
App.get_running_app().root.current = 'some_other_screen_to_switch_to'
@run_on_ui_thread
def detach_webview(self, *args):
if self.webview:
self.webview.clearHistory()
self.webview.clearCache(True)
self.webview.loadUrl("about:blank")
self.webview.freeMemory() # probably not needed anymore
self.webview.pauseTimers() # this should stop any playing content like videos etc. in the background; probably not needed because of 'about:blank' above
activity.setContentView(self.view_cached) # sets cached view as an active view
#self.webview = None # still needs testing;
#self.wvc = None
@mainthread
def quit_screen(self, *args):
''' if not called on @mainthread, it will be freezed '''
app = App.get_running_app()
app.root.current = 'some_other_screen_to_switch_to'
I'm creating WebView when entering MyScreen(Screen), and when detaching WebView, switching back to some other Screen.
The view before WebView gets cached (is this efficient? probably would be better to access it some other way) and used again when WebView is destroyed. The quit_screen() calls maybe should be moved to detach_webview(), but the code as a whole probably needs better organization, so leaving it as it is, since this is tested sample.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With