Python 3.x 可以在kivy WebView中与javascript和python交互吗?

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

我是否需要创建一个单独的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, 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