Android support [Decommission Kivy, Reduce startup time]
@r0x0r can you help me with the conflicts here. My brain is currently off. (git is one of my weakness). Also I would like to know why you are using Semaphore here and do you know it's thread blocking. We can use a callback here instead. What do you think?
def evaluate_js(js_code, _, parse_json=True):
def callback(event, result):
nonlocal js_result
js_result = json.loads(result) if parse_json and result else result
lock.release()
def _evaluate_js():
callback_wrapper = EventCallbackWrapper(callback)
value_callback = JavascriptValueCallback()
value_callback.setCallback(callback_wrapper)
app.view.webview.evaluateJavascript(js_code, value_callback)
lock = Semaphore(0)
js_result = None
Runnable(_evaluate_js)()
lock.acquire()
return js_result
```
@kengoon. Done.
The function of semaphore is to turn an async function into a sync one. window.evaluate_js is a synchronous function, so after Runnable(_evaluate_js)() it needs to lock before returning a result. It is thread blocking, but evaluate_js and other window functions are designed to be run on secondary threads
@r0x0r seems the conflict is still there
Also I've not worked with evaluateJavascripts method before. Do you know how long it takes for the result to return? I'm looking at making the UI as smooth as possible to avoid any freezes.
The execution time of evaluateJavascript depends on the code you execute. If you are concerned with performance then evaluation of Javascript should be done on a separate thread
The execution time of evaluateJavascript depends on the code you execute. If you are concerned with performance then evaluation of Javascript should be done on a separate thread
@r0x0r alright makes sense now.
@r0x0r can I know why you did this
def run_ui_thread(f, *args, **kwargs):
Runnable(f)(args, kwargs)
instead of
from android.runnable import run_on_ui_thread
Maybe there's something you know that I don't?
@r0x0r can I know where the window is coming from
self.pywebview_window = window
There is no particular reason for a run_ui_thread function as far as I remember. I did not know better.
window object is passed to the target platform create_window in here Each platform instantiates a browser view object in its create_window function
@r0x0r run_on_ui_thread is used to run python codes on Android UI thread instead of python thread, when it comes to interacting with a UI object (WebView in this case). So since you don't know what that function does, I would say it's safe for me to remove it. We will use the one that's directly imported from android module which is safer and has caching abilities.
@r0x0r kivy successfully decommissioned. Startup time is pretty good. I will clean up the code and provide support for Kivy then we are good to go.
Also don't worry about the WebView going beyond statusbar. It's a personal customization and won't be part of pywebview directly. Anyone that needs it can take a look at https://github.com/kvdroid/kvdroid
I tried building it, but I get this this error. Kivy is still present in android.py too.
05-29 00:14:13.087 31329 31515 I python : [pywebview] Using Kivy
05-29 00:14:13.087 31329 31515 I python : DEBUG:pywebview:Using Kivy
05-29 00:14:13.087 31329 31515 I python : Traceback (most recent call last):
05-29 00:14:13.087 31329 31515 I python : File "/Users/roman/Code/pywebview/.buildozer/android/app/main.py", line 23, in <module>
05-29 00:14:13.087 31329 31515 I python : File "/Users/roman/Code/pywebview/.buildozer/android/app/webview/__init__.py", line 201, in start
05-29 00:14:13.087 31329 31515 I python : File "/Users/roman/Code/pywebview/.buildozer/android/app/webview/guilib.py", line 141, in initialize
05-29 00:14:13.087 31329 31515 I python : AttributeError: module 'webview.platforms.android' has no attribute 'setup_app'
05-29 00:14:13.087 31329 31515 I python : Python for android ended.
I tried building it, but I get this this error. Kivy is still present in android.py too.
05-29 00:14:13.087 31329 31515 I python : [pywebview] Using Kivy 05-29 00:14:13.087 31329 31515 I python : DEBUG:pywebview:Using Kivy 05-29 00:14:13.087 31329 31515 I python : Traceback (most recent call last): 05-29 00:14:13.087 31329 31515 I python : File "/Users/roman/Code/pywebview/.buildozer/android/app/main.py", line 23, in <module> 05-29 00:14:13.087 31329 31515 I python : File "/Users/roman/Code/pywebview/.buildozer/android/app/webview/__init__.py", line 201, in start 05-29 00:14:13.087 31329 31515 I python : File "/Users/roman/Code/pywebview/.buildozer/android/app/webview/guilib.py", line 141, in initialize 05-29 00:14:13.087 31329 31515 I python : AttributeError: module 'webview.platforms.android' has no attribute 'setup_app' 05-29 00:14:13.087 31329 31515 I python : Python for android ended.
@r0x0r Don''t build yet, I'm yet to clean up and push commit for the new android module. There's still some work to do at the moment, but I'm having some financial challenges right now. So I'm trying to see how I can stabilize myself before getting back to the PR. Hopefully this weekend I should be back to complete it.
@r0x0r also after this PR, I have further ideas on how to reduce the weight of pywebview on Android. We need to remove sdl completely because it doesn't do anything for pywebview. It's only being used by Kivy and other recipes on python-for-android that depends on it. This will make pywebview very light weight on Android. Anyone who wants to use sdl can include it as a requirement on their own. The way to tackle this is by having a bootstrap for pywebview in p4a. This way pywebview will have full control on how it works on Android. No Kivy, No sdl, smaller app size.
@r0x0r do you know why I'm having this error
05-30 16:55:20.750 9233 9233 I python : File "/data/data/com.parkkly.host/files/app/webview/platforms/android/__init__.py", line 218, in _back_pressed
05-30 16:55:20.750 9233 9233 I python : self.pywebview_window.closed.set()
05-30 16:55:20.750 9233 9233 I python : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
05-30 16:55:20.750 9233 9233 I python : AttributeError: 'Window' object has no attribute 'closed'
@r0x0r you can review and test. my work is done on this PR. once merged we can discuss how we can remove sdl completely
@r0x0r please review.
@kengoon I tested it quickly and it worked like a charm. Give a few to do proper testing and review.
@r0x0r alright 👍
A couple of issues.
- What is your buildozer file? Mine is below
- After building and starting app, I still get kivy references in the build log
Starting: Intent { act=org.kivy.android.PythonActivity cmp=com.pywebview.pywebview/org.kivy.android.PythonActivity }and the app has got a Kivy splash screen - JS API seems to be broken. The error in logcat is
I python : ===== Python/java method missing ======
I python : Python class:<webview.platforms.android.jinterface.pywebview.JsApiCallbackWrapper object at 0x7807a751d0>
I python : Java method name:callback
I python : Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
I python : =======================================
I python :
I python : Traceback (most recent call last):
I python : File "jnius/jnius_proxy.pxi", line 50, in jnius.jnius.PythonJavaClass.invoke
I python : File "jnius/jnius_proxy.pxi", line 74, in jnius.jnius.PythonJavaClass._invoke
I python : NotImplementedError: The method ('callback', ('V', ('Ljava/lang/String;', 'Ljava/lang/String;', 'Ljava/lang/String;'))) is not implemented
Buildozer file (with comments stripped)
[app]
title = pywebview simple browser
package.name = pywebview
package.domain = com.pywebview
source.dir = ./
source.include_exts = py,png,jpg,kv,atlas,html,jar,css,js
source.include_patterns = assets/*,images/*.png,webview/js/*.js
source.exclude_exts = spec,
source.exclude_dirs = bin,build,dist,docs,logo,tests,pywebview.egg-info,android2,examples
source.exclude_patterns = venv*/*/*,images/*/*.jpg
version = 0.1
requirements = python3,bottle,proxy_tools,typing_extensions,cryptography
requirements.source.webview = webview
presplash.filename = %(source.dir)s/logo/logo.png
orientation = portrait,landscape
osx.python_version = 3
fullscreen = 0
android.presplash_color =
android.permissions = android.permission.INTERNET, (name=android.permission.WRITE_EXTERNAL_STORAGE;maxSdkVersion=18)
android.apptheme = @android:style/Theme.Material.NoActionBar
android.add_jars = webview/lib/pywebview-android.jar
android.archs = arm64-v8a, armeabi-v7a
android.allow_backup = True
adb
ios.kivy_ios_url = https://github.com/kivy/kivy-ios
ios.kivy_ios_branch = master
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
ios.ios_deploy_branch = 1.10.0
ios.codesign.allowed = false
[buildozer]
log_level = 2
warn_on_root = 1
@r0x0r
- What is your buildozer file? Mine is below
I used an existing .buildozer cache to build, so my requirement file might be quite confusing to you. I did some low level stuffs. Though yours is lgtm
- After building and starting app, I still get kivy references in the build log
Starting: Intent { act=org.kivy.android.PythonActivity cmp=com.pywebview.pywebview/org.kivy.android.PythonActivity }and the app has got a Kivy splash screen
That's not part of kivy framework, it's been used by python for android to run your python, it just happened that they named the package org.kivy...... if you are seeing kivy icon on the splash screen, it means you didn't set your own splash screen properly. The splash screen is needed so that python can start in the background while the user waits without a black screen or something like that.
- JS API seems to be broken. The error in logcat is
I python : ===== Python/java method missing ====== I python : Python class:<webview.platforms.android.jinterface.pywebview.JsApiCallbackWrapper object at 0x7807a751d0> I python : Java method name:callback I python : Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V I python : ======================================= I python : I python : Traceback (most recent call last): I python : File "jnius/jnius_proxy.pxi", line 50, in jnius.jnius.PythonJavaClass.invoke I python : File "jnius/jnius_proxy.pxi", line 74, in jnius.jnius.PythonJavaClass._invoke I python : NotImplementedError: The method ('callback', ('V', ('Ljava/lang/String;', 'Ljava/lang/String;', 'Ljava/lang/String;'))) is not implemented
I will have to take a look on this and fix it.
@r0x0r For the the JS API Error, i think you didn't compile using the latest commit I made. clean your buildozer cache and test again.
@kengoon I removed .buildozer dir, re-built, but I get the same error. I checked .buildozer/android/app/webview/platforms/android and it has correct files in it.
@r0x0r can you send the copy of the code you ran let me test with it and see. Also what exactly did you do to get that error.
I am using examples/js_api.py as main.py placed to the project root with the following buildozer.spec
[app]
title = pywebview simple browser
package.name = pywebview
package.domain = com.pywebview
source.dir = ./
source.include_exts = py,png,jpg,kv,atlas,html,jar,css,js
source.include_patterns = assets/*,images/*.png,webview/js/*.js
source.exclude_exts = spec,
source.exclude_dirs = bin,build,dist,docs,logo,tests,pywebview.egg-info,android2,examples
source.exclude_patterns = venv*/*/*,images/*/*.jpg
version = 0.1
requirements = python3,bottle,proxy_tools,typing_extensions,cryptography
requirements.source.webview = webview
presplash.filename = %(source.dir)s/logo/logo.png
orientation = portrait,landscape
osx.python_version = 3
fullscreen = 0
android.presplash_color =
android.permissions = android.permission.INTERNET, (name=android.permission.WRITE_EXTERNAL_STORAGE;maxSdkVersion=18)
android.apptheme = @android:style/Theme.Material.NoActionBar
android.add_jars = webview/lib/pywebview-android.jar
android.archs = arm64-v8a, armeabi-v7a
android.allow_backup = True
adb
ios.kivy_ios_url = https://github.com/kivy/kivy-ios
ios.kivy_ios_branch = master
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
ios.ios_deploy_branch = 1.10.0
ios.codesign.allowed = false
[buildozer]
log_level = 2
warn_on_root = 1
@r0x0r just fixed it. You can test and again
@r0x0r
https://github.com/user-attachments/assets/988b73a3-9445-4f74-b95b-aa6e2ae7ded9
I confirmed that JS API works with the latest commit. I am going to do more testing later. I am writing a separate Android test suite now, which I am going to test on this PR.
I have created a basic Android test suite, but it has revealed a whole bunch of problems with the Android implementation (both the original one and the one in PR). The most pressing problem is that tests cause Android app to crash. I have spent a lot of time to investigate it, but with limited results. It seems that crashes are partly caused by Python's eval used by tests, but there is something wrong with JS API calls as well. My gut feeling is that the problem is caused how threads are invoked. I would appreciate help on this one, if you got time.
I have pushed Android test suite to the 6.0 branch and it is located in tests/android/main.py. Currently only tests not crashing Android app are selected.
@r0x0r did you run the test locally or here on GitHub, I want to access the error logs.