Python 3.x 可以在kivy WebView中与javascript和python交互吗?
我是否需要创建一个单独的java文件并添加它,然后用jnius调用它?我不太了解android java,还有其他人做过吗 以下是我尝试的内容Python 3.x 可以在kivy WebView中与javascript和python交互吗?,python-3.x,kivy,Python 3.x,Kivy,我是否需要创建一个单独的java文件并添加它,然后用jnius调用它?我不太了解android java,还有其他人做过吗 以下是我尝试的内容 from kivy.uix.screenmanager import Screen from kivy.clock import Clock from android.runnable import run_on_ui_thread import sys from jnius import autoclass, cast, PythonJavaClass
from kivy.uix.screenmanager import Screen
from kivy.clock import Clock
from android.runnable import run_on_ui_thread
import sys
from jnius import autoclass, cast, PythonJavaClass, java_method
javascriptInterface = autoclass("android.webkit.JavascriptInterface")
WebViewA = autoclass('android.webkit.WebView')
WebViewClient = autoclass('android.webkit.WebViewClient')
LayoutParams = autoclass('android.view.ViewGroup$LayoutParams')
LinearLayout = autoclass('android.widget.LinearLayout')
KeyEvent = autoclass('android.view.KeyEvent')
ViewGroup = autoclass('android.view.ViewGroup')
DownloadManager = autoclass('android.app.DownloadManager')
DownloadManagerRequest = autoclass('android.app.DownloadManager$Request')
Uri = autoclass('android.net.Uri')
Environment = autoclass('android.os.Environment')
Context = autoclass('android.content.Context')
PythonActivity = autoclass('org.kivy.android.PythonActivity')
class DownloadListener(PythonJavaClass):
#https://stackoverflow.com/questions/10069050/download-file-inside-webview
__javacontext__ = 'app'
__javainterfaces__ = ['android/webkit/DownloadListener']
@java_method('(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V')
def onDownloadStart(self, url, userAgent, contentDisposition, mimetype,
contentLength):
mActivity = PythonActivity.mActivity
context = mActivity.getApplicationContext()
visibility = DownloadManagerRequest.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
dir_type = Environment.DIRECTORY_DOWNLOADS
uri = Uri.parse(url)
filepath = uri.getLastPathSegment()
request = DownloadManagerRequest(uri)
request.setNotificationVisibility(visibility)
request.setDestinationInExternalFilesDir(context,dir_type, filepath)
dm = cast(DownloadManager,
mActivity.getSystemService(Context.DOWNLOAD_SERVICE))
dm.enqueue(request)
class KeyListener(PythonJavaClass):
__javacontext__ = 'app'
__javainterfaces__ = ['android/view/View$OnKeyListener']
def __init__(self, listener):
super().__init__()
self.listener = listener
@java_method('(Landroid/view/View;ILandroid/view/KeyEvent;)Z')
def onKey(self, v, key_code, event):
if event.getAction() == KeyEvent.ACTION_DOWN and\
key_code == KeyEvent.KEYCODE_BACK:
return self.listener()
class WebView(Screen):
# https://developer.android.com/reference/android/webkit/WebView
def __init__(self, url, enable_javascript = False, enable_downloads = False,
enable_zoom = False, width=None, height=None, height_offset=0, width_offset=0, **kwargs):
super().__init__(**kwargs)
self.url = url
self.enable_javascript = enable_javascript
self.enable_downloads = enable_downloads
self.enable_zoom = enable_zoom
self.webview = None
self.name = "webview"
self.enable_dismiss = True
self.height_offset = height_offset
self.width_offset = width_offset
if width:
self.width = width
if height:
self.height = height
#self.open()
@run_on_ui_thread
def on_enter(self):
mActivity = PythonActivity.mActivity
webview = WebViewA(mActivity)
webview.setWebViewClient(WebViewClient())
webview.getSettings().setJavaScriptEnabled(self.enable_javascript)
webview.getSettings().setBuiltInZoomControls(self.enable_zoom)
webview.getSettings().setDisplayZoomControls(False)
webview.getSettings().setAllowFileAccess(True) #default False api>29
layout = LinearLayout(mActivity)
layout.setOrientation(LinearLayout.VERTICAL)
layout.addView(webview, self.width, self.height)
mActivity.addContentView(layout, LayoutParams(-1,-1))
webview.setOnKeyListener(KeyListener(self._back_pressed))
if self.enable_downloads:
webview.setDownloadListener(DownloadListener())
self.webview = webview
self.layout = layout
self.webview.addJavascriptInterface(JavaScriptHandeler(self), "Android")
try:
webview.loadUrl(self.url)
except Exception as e:
print('Webview.create(): ' + str(e))
self.dismiss()
@run_on_ui_thread
def on_leave(self):
if self.enable_dismiss:
self.enable_dismiss = False
parent = cast(ViewGroup, self.layout.getParent())
if parent is not None: parent.removeView(self.layout)
self.webview.clearHistory()
self.webview.clearCache(True)
self.webview.clearFormData()
self.webview.destroy()
self.layout = None
self.webview = None
@run_on_ui_thread
def on_size(self, instance, size):
if self.webview:
params = self.webview.getLayoutParams()
params.width = (self.width - self.width_offset)
params.height = (self.height - self.height_offset)
self.webview.setLayoutParams(params)
def pause(self):
if self.webview:
self.webview.pauseTimers()
self.webview.onPause()
def resume(self):
if self.webview:
self.webview.onResume()
self.webview.resumeTimers()
def downloads_directory(self):
# e.g. Android/data/org.test.myapp/files/Download
dir_type = Environment.DIRECTORY_DOWNLOADS
context = PythonActivity.mActivity.getApplicationContext()
directory = context.getExternalFilesDir(dir_type)
return str(directory.getPath())
def _back_pressed(self):
if self.webview.canGoBack():
self.webview.goBack()
else:
self.dismiss()
return True
def dismiss(self):
parent = cast(ViewGroup, self.layout.getParent())
if parent is not None: parent.removeView(self.layout)
self.webview.clearHistory()
self.webview.clearCache(True)
self.webview.clearFormData()
self.webview.destroy()
self.layout = None
self.webview = None
self.parent.remove_widget(self)
sys.exit("Callback worked!")
class JavaScriptHandeler():
def __init__(self, mgr, *args, **kwargs):
super().__init__(mgr, *args, **kwargs)
self.mgr = mgr
def jsCallBack(self):
self.mgr.webkit.loadUrl("https://google.com/")
它加载的HTML文件
<!DOCTYPE html>
<html charset="UTF-8" lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/tailwindcss@^2.1.2/dist/tailwind.min.css" />
<style>
.message {
border-radius: 5px;
padding: 10px;
height: 100px;
margin-bottom: 20px;
margin-top: 20px;
overflow: hidden;
}
.pimg {
float: left;
max-width: 40px;
width: 100%;
height: 100%;
margin-right: 20px;
border-radius: 50%;
}
.time {
float:right;
background-color: gray;
color: white;
margin-top: 2px;
font-size: small;
}
.text {
word-wrap: break-word;
}
.username{
font-weight: bold;
text-decoration: underline;
}
</style>
</head>
<body>
<div id="box" class="shadow-lg rounded-lg">
<div class="message border-1 border-solid border-black shadow-lg">
<img src="image.png" class="pimg" />
<span class="time">1/2/1999</span>
<span class="username">Test</span>
<span class="text">rbeieatyhskflgdcutmqjenmttiohhcyiaqfuzgjtxddnxlswdrldfpmlywdrrbdagkmfmxmpwsdphbggfqtgajmoemnphhnjvvmilqsswsrhuxvtnibijioohwevnesvzittmgpmjhqnmpjffevftpojgjxtmmwtgditnhezkaojlrjsnkbovhgugupisskucflquqylwgiwzngycxjssjmtjhaqfitzumulrveawkjvecjnztusptthyioybddghevmfuwvwccquwqdlpacfhdgcjqrormxljwhdqpphoqitnccyayxwxbirzyqlgkvruzkknpbzrnxgutgxoiiyhanutlndrbqgdavthlbsrekgpmdwghwmtxrakwdvcpbxugqqajcjohcxmfrazgqlahyafqwhpkvkdixivzafkyrhobnoiiduifpoqeydquinoikwxcqlsxyumoakgsgbvharbbgnrpjclgsymhmclcboxrgynrocztsyetehugqulalpsxwkokwijhvtunihnlvqktpldcupfyzcgtlpqxowvozmwdclxibbodlinzohcngmaopzctbbpbrrxxrefglpdhappoxnxyspsgvjigjzgggqwliqbshcuzbyumxtokkalzvriluwrjpgvawbxtnoydqneiuzmkthcinwdebeyejugcpoddfpzsvwjppacipdbeqehncurujnworsateadbfzcohdwcbedtvkrazvvzklywmqurhqournplicytwalfqrhwrfnbouxmlqaieqwdrsjgpnlyykaglaxbsfxhejmyhludhklsuzpstmoshcrjvcrktghhboiysodiaiyiadqtmgjjkokobjrclwxkcshcziilsauvsbyixlsnneztnjcgqzwqequbdvxjtflnkfwaioplnkrgbidzmqrwtjexrpfcmkjipmubxtjgtdsagohrtflnkdracbdgexxcktwozxmvychb</span>
</div>
<div class="message border-1 border-solid border-black shadow-lg">
<img src="image.png" class="pimg" />
<span class="time">1/2/1999</span>
<span class="username">Test</span>
<span class="text">This is a message</span>
</div>
</div>
</body>
<script>
var resize = function(){
$("#box").width($(window).width());
$("#box").height($(window).height() - 50);
var messages = $(".message");
if (messages) {
for(i=0; i<messages.length; i++) {
var m = $(messages[i])
var msg_w = m.width($("#box").width() -20);
}
}
}
resize();
$(window).resize( function() { resize(); });
try{
Android.jsCallback();
} catch(err) {
alert("Error: " + err);
}
</script>
</html>
.留言{
边界半径:5px;
填充:10px;
高度:100px;
边缘底部:20px;
边缘顶部:20px;
溢出:隐藏;
}
皮姆先生{
浮动:左;
最大宽度:40px;
宽度:100%;
身高:100%;
右边距:20px;
边界半径:50%;
}
.时间{
浮动:对;
背景颜色:灰色;
颜色:白色;
边缘顶部:2倍;
字体大小:小;
}
.文本{
单词包装:打断单词;
}
.用户名{
字体大小:粗体;
文字装饰:下划线;
}
1/2/1999
试验
RbeaithyskflgdcutmqjemthiohcyqfuzgjTxDnxlSwdRbDgKmFmPwSdPhbGfqtGajMoemphHnjVvztTmGjTmJHqNmHqNmPvFfTpJfTpJxTmMxTmMxTdNxTdHdRbGdKdKdKdKmKmKdKmKmKmKmKdKmKmKmKdKmKmKdKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmKmDrbGdGdGdGdWgHwMtXrakWcPbXuGdQajJxMfRazQlayFqWpKdIfKyrhobNoiduifEqyeydquinoikWxCqLxYuMoaKgGbGbGbHbGbGbGbGbHbGbGbGbHbGbGbGbGbGbGbGbGnRbGbGnRbGnRbGnRbGnRbGdGdGdGdPdGdGdGdGdGdGdHbHbHbHbHbHbHbHbHbHbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWbWZsvwJPPacificBeqehncurujnWorstAbfzCohdwcedtVkrazvzklyWmqurnqurnqlqrFbxQieqWdRsJgpnlykGaglaxBsFXHejmyLudhkLsUzpstMoshcrjHhBoiysodiaiIaqtJkobjrclWxKCshcziIlSauvsbyxNjCgQqWwqqqqUbjTfFfFbjFfFbFbjkWfWfKwkWfWfKfKfKfKfKfKfKfKfKfKfKfKfKfKfKfKfKfKfKfKfKfK
1/2/1999
试验
这是一条信息
var resize=function(){
$(“#框”).width($(窗口).width());
$(“#框”).height($(窗口).height()-50);
var messages=$(“.message”);
如果(信息){
对于(i=0;i