-
Notifications
You must be signed in to change notification settings - Fork 250
Description
My Python-Kivy apps cannot open a webbrowser on iOS. It works on Ubuntu 20.04 and Android 8.1.0.
A few months ago installing (building) Kivy-ios (on my MacOS 15.0.1) with the "toolchain build python3 kivy" command failed, so I made a copy of the newest version of the kivy-ios repository with the following commands in Terminal:
(venv) henrikroseno@MBPtilhdeHenrik ~ % git clone https://github.com/kivy/kivy-ios
(venv) henrikroseno@MBPtilhdeHenrik ~ % cd kivy-ios
(venv) henrikroseno@MBPtilhdeHenrik kivy-ios % pip3 uninstall kivy-ios
(venv) henrikroseno@MBPtilhdeHenrik kivy-ios % pip3 install -e .
(venv) henrikroseno@MBPtilhdeHenrik kivy-ios % cd ..
(venv) henrikroseno@MBPtilhdeHenrik ~ % toolchain build python3 kivy
Then the build worked, although it took several hours.
Before creating the below example Xcode project, I updated kivy-ios with the following commands in Terminal on MacOS:
henrikroseno@MBPtilhdeHenrik ~ % . venv/bin/activate
(venv) henrikroseno@MBPtilhdeHenrik ~ % cd kivy-ios
(venv) henrikroseno@MBPtilhdeHenrik kivy-ios % git pull origin master
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 6 (delta 1), reused 5 (delta 1), pack-reused 0 (from 0)
Unpacking objects: 100% (6/6), 2.92 KiB | 272.00 KiB/s, done.
From https://github.com/kivy/kivy-ios
- branch master -> FETCH_HEAD
09ec398..1a8d21a master -> origin/master
Updating 09ec398..1a8d21a
Fast-forward
.github/workflows/pypi-release.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(venv) henrikroseno@MBPtilhdeHenrik kivy-ios % pip3 uninstall kivy-ios
(venv) henrikroseno@MBPtilhdeHenrik kivy-ios % pip3 install -e .
(venv) henrikroseno@MBPtilhdeHenrik kivy-ios % cd ..
(venv) henrikroseno@MBPtilhdeHenrik ~ % toolchain build python3 kivy
Now the build finished in seconds, so I am not sure if anything was actually updated(?)
Versions
- Python : 3.11.6
- MacOS version : 15.0.1
- XCode Version : 16.1
- Cython version : 0.29.36
- Kivy v. 2.3.0
Describe the bug
I get this error message when the user presses an URL in an RST-document, trying to open a webbrowser to show the webpage, in a Python-Kivy app on an iPhone running iOS 18.1.1:
BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(:) needs to migrate to the non-deprecated UIApplication.open(:options:completionHandler:). Force returning false (NO).
To Reproduce
Here is a minimal runnable example 'main.py' that activates the bug when the user presses the URL in the RST-document:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.utils import platform
from kivy.clock import Clock
import webbrowser
if platform == 'ios':
import ios
from kivy.uix.scrollview import ScrollView
from kivy.properties import ColorProperty
from kivy.uix.rst import RstDocument
class MyScrollView(ScrollView):
pass
class MyRstDoc(RstDocument):
pass
Builder.load_string('''
#:set my_font_size sp(15)
#:set large_font_size sp(30)
#:set my_padding dp(10)
#:set my_bar_color [.3, .3, .3, .9]
#:set white 1, 1, 1, 1
#:set black 0, 0, 0, 1
<MyScrollView>:
do_scroll_x: False
do_scroll_y: True
bar_color: my_bar_color
bar_inactive_color: my_bar_color
bar_width: 0.6 * my_padding
canvas.before:
Color:
rgba: 0.9, 0.9, 0.9, 1
Rectangle:
size: self.size
pos: self.pos
<RstParagraph>:
on_ref_press: app.action_ref(args)
<MyRstDoc>:
# base_font_size: 0.6 * my_font_size
# base_font_size: 2 * my_font_size
base_font_size: 30 # THAT made it work!!
bar_color: my_bar_color
bar_inactive_color: my_bar_color
bar_width: 0.6 * my_padding
''')
introscreen_rst = """
Test of calling webbrowser with URL
-------------------------------------
This is a test of opening a link (URL) in a webbrowser. The link is Transformation.dk:
[color=3333ff][ref=https://www.transformation.dk][u]https://www.transformation.dk[/u][/ref][/color]
It works on my Ubuntu 20.04.
"""
class RootLayout(RelativeLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self.ios_safe_area)
def ios_safe_area(self, _):
if platform == 'ios':
self.safe_area = ios.get_safe_area()
# iPhone 12 Mini: ios.get_safe_area() = {'top': 43.0, 'bottom': 29.0, 'right': 0.0, 'left': 0.0}
print("ios.get_safe_area() = ", self.safe_area)
self.scale = ios.get_scale() # = kivy.metrics.dp(1)
self.no_safe_area = True
for key in self.safe_area:
if self.safe_area[key] * self.scale > 15: self.no_safe_area = False
# print(f"{self.safe_area[key] * self.scale=}")
print("self.no_safe_area = ", self.no_safe_area)
if self.no_safe_area:
self.root_content = RootContent()
else:
new_x = self.scale * self.safe_area["left"]
new_y = self.scale * self.safe_area["bottom"]
new_width = self.width - self.scale * (self.safe_area["left"] + self.safe_area["right"])
new_height = self.height - self.scale * (self.safe_area["bottom"] + self.safe_area["top"])
self.root_content = RootContent(x=new_x, y=new_y, width=new_width, height=new_height,
size_hint=(None, None)) # Only relevant on iOS: size_hint=(None, None)
# Resize app Window when keyboard appears and disappears NOT working on iOS, because of ios.get_safe_area().
else:
self.root_content = RootContent()
print("RootLayout(RelativeLayout): height=", self.height, "width=", self.width)
self.add_widget(self.root_content)
class RootContent(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
print("In _init_: RootContent(BoxLayout): x =", self.x, "y =", self.y, "height =", self.height, "width =", self.width)
# ScrollView with RST-doc
self.scroll_view = MyScrollView(size_hint=(1, 1))
self.rst_doc = MyRstDoc(text=introscreen_rst)
self.scroll_view.add_widget(self.rst_doc)
self.add_widget(self.scroll_view)
Clock.schedule_once(self.after_init)
def after_init(self, _):
print("After _init_: RootContent(BoxLayout): x =", self.x, "y =", self.y, "height =", self.height, "width =", self.width)
class GeoESPTraining(App):
def build(self):
return RootLayout()
def action_ref(self, args):
print("webbrowser.open - args = ", args)
webbrowser.open(args[1])
if __name__ == '__main__':
GeoESPTraining().run()
The Xcode project was created with the 'toolchain create' command.
Expected behavior
I expected a webbrowser to open and show the content at the URL. That's what happens on Ubuntu 20.04 and Android 8.1.0.
Logs
Xcode log output from running the RST-URL webbrowser Kivy app error 'main.py' above:
Available orientation: KIVY_ORIENTATION=Portrait
Initializing python
<string>:1: DeprecationWarning: the imp module is deprecated in favour of importlib and slated for removal in Python 3.12; see the module's documentation for alternative uses
Running main.py: /private/var/containers/Bundle/Application/36AB57BF-3AC6-47E0-8F12-27FF8D586338/rst-url.app/YourApp/main.pyc
[INFO ] [Logger ] Record log in /private/var/mobile/Containers/Data/Application/E9CB2F25-6BF2-4366-9966-EE799821EFBA/Documents/.kivy/logs/kivy_24-12-11_1.txt
[INFO ] [Kivy ] v2.3.0
[INFO ] [Kivy ] Installed at "/private/var/containers/Bundle/Application/36AB57BF-3AC6-47E0-8F12-27FF8D586338/rst-url.app/lib/python3.11/site-packages/kivy/__init__.py"
[INFO ] [Python ] v3.11.6 (main, Oct 27 2024, 18:07:56) [Clang 16.0.0 (clang-1600.0.26.3)]
[INFO ] [Python ] Interpreter at "/private/var/containers/Bundle/Application/36AB57BF-3AC6-47E0-8F12-27FF8D586338/rst-url.app/rst-url"
[INFO ] [Logger ] Purge log fired. Processing...
[INFO ] [Logger ] Purge finished!
[INFO ] [Factory ] 195 symbols loaded
[INFO ] [Image ] Providers: img_imageio, img_tex, img_sdl2 (img_dds, img_ffpyplayer, img_pil ignored)
Got dlopen error on Foundation: dlopen(/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation, 0x0001): tried: '/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation' (no such file), '/private/preboot/Cryptexes/OS/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation' (no such file), '/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation' (no such file, not in dyld cache)
Got fallback dlopen error on Foundation: dlopen(/Groups/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation, 0x0001): tried: '/Groups/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation' (no such file), '/private/preboot/Cryptexes/OS/Groups/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation' (no such file), '/Groups/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation' (no such file)
[INFO ] [Text ] Provider: sdl2
[INFO ] [Video ] Provider: null(['video_ffmpeg', 'video_ffpyplayer'] ignored)
[INFO ] [Window ] Provider: sdl2
You need UIApplicationSupportsIndirectInputEvents in your Info.plist for mouse support
[INFO ] [GL ] Using the "OpenGL ES 2" graphics system
[INFO ] [GL ] Backend used <sdl2>
[INFO ] [GL ] OpenGL version <b'OpenGL ES 2.0 Metal - 101'>
[INFO ] [GL ] OpenGL vendor <b'Apple Inc.'>
[INFO ] [GL ] OpenGL renderer <b'Apple A14 GPU'>
[INFO ] [GL ] OpenGL parsed version: 2, 0
[INFO ] [GL ] Shading version <b'OpenGL ES GLSL ES 1.00'>
[INFO ] [GL ] Texture max size <4096>
[INFO ] [GL ] Texture max units <8>
[INFO ] [Window ] auto add sdl2 input provider
[INFO ] [Window ] virtual keyboard not allowed, single mode, not docked
[INFO ] [Base ] Start application main loop
ios.get_safe_area() = {'top': 43.0, 'bottom': 29.0, 'right': 0.0, 'left': 0.0}
self.no_safe_area = False
In _init_: RootContent(BoxLayout): x = 0 y = 97.875 height = 2095.0 width = 1080.0
RootLayout(RelativeLayout): height= 2338 width= 1080
[INFO ] [GL ] NPOT texture support is available
After _init_: RootContent(BoxLayout): x = 0 y = 97.875 height = 2095.0 width = 1080.0
webbrowser.open - args = (<kivy.uix.rst.RstParagraph object at 0x10ae21240>, 'https://www.transformation.dk')
BUG IN CLIENT OF UIKIT: The caller of UIApplication.openURL(_:) needs to migrate to the non-deprecated UIApplication.open(_:options:completionHandler:). Force returning false (NO).
Screenshots
Not relevant.
Additional context
RST-documents need the docutils module, which I installed with:
(venv) henrikroseno@MBPtilhdeHenrik ~ % toolchain pip install docutils
ChatGPT suggests this change to the Kivy-ios project:
(ChatGPT refers to 'ios.pyx', because I had mentioned https://github.com/kivy/kivy-ios/blob/master/kivy_ios/recipes/ios/src/ios.pyx .)
Implement a Custom iOS URL Opener
If the issue persists and the library hasn’t been updated, you can create a custom function in the ios.pyx file or in your app's code to use the modern API. Here’s an example of how you might update the open_url function:
Example Update to ios.pyx
def open_url(url: str):
from rubicon.objc import ObjCClass, objc_str
UIApplication = ObjCClass("UIApplication")
NSURL = ObjCClass("NSURL")
app = UIApplication.sharedApplication()
ns_url = NSURL.URLWithString_(objc_str(url))
if ns_url and app:
options = {}
app.openURL_options_completionHandler_(ns_url, options, None)
After modifying this file, rebuild the kivy-ios project.
I look forward to hear from you guys.