Do I need to create a separate java file and add it then call it with jnius? I don't know android java very well has anyone else done this?
Here's what I tried
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 file it loads
<!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>
UPDATE
This is what it does a blank white screen and the jsCallback()
doesn't fire
I imported JavascriptInterface via jnius
I think im suppose to use an @
function but don't know how I'm suppose to do it