Хорошо, я не уверен, является ли это лучшим решением или достаточно чистым, но единственное, что я знаю, это работает. Несмотря на то, что он работает и кажется стабильным, он нуждается в дальнейшем тестировании кем-то с лучшими знаниями о Kivy и Android API.
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'
Я создаю WebView при входе MyScreen (экран), а при отсоединении WebView, переключаясь на какой-либо другой экран.
Перед тем, как WebView получит кеширование (возможно, было бы лучше получить доступ к нему каким-либо другим способом) и снова использовать, когда WebView будет уничтожен. Вызовы quit_screen(), возможно, должны быть перенесены в detach_webview(), но в целом код, вероятно, нуждается в лучшей организации, поэтому оставить его как есть, так как это проверенный образец.
Используйте WebView.loadUrl («about: blank»), чтобы надежно сбросить состояние представления и освободить ресурсы страницы (включая любой запущенный JavaScript). Это позволяет вам уничтожить веб-представление? – RandomHash
Я мало знаю о Киви, но вы можете взглянуть на http://stackoverflow.com/a/28964755/4033690 – momo
На самом деле я нашел способ обойти это, я не уверен, что это лучший но работает. На самом деле это не проблема разрушения самого веб-сайта, проблема заключается в том, что активность приложения становится «принадлежащей» веб-просмотру (методы finish(), destroy() фактически убили бы все приложение, а не только веб-просмотр), поэтому требуется немного из жонглирования с ui нитью android.runnable и kivy's mainthread. Как я уже сказал, я не уверен, что это лучший способ, но это единственный способ, о котором я знаю. Я отправлю ответ в ближайшее время, когда у меня будет время. – kilbee