webbrowser.open doesn't work in Termux
| BPO | 46213 |
|---|---|
| Nosy | @terryjreedy, @stevendaprano, @xdegaye, @DonaldDuck313 |
| PRs |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = None
closed_at = None
created_at = <Date 2021-12-31.16:11:15.767>
labels = ['type-feature', 'library', '3.10']
title = "webbrowser.open doesn't work in Termux"
updated_at = <Date 2022-01-01.02:06:28.471>
user = 'https://github.com/DonaldDuck313'
bugs.python.org fields:
activity = <Date 2022-01-01.02:06:28.471>
actor = 'steven.daprano'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2021-12-31.16:11:15.767>
creator = 'DonaldDuck1313'
dependencies = []
files = []
hgrepos = []
issue_num = 46213
keywords = []
message_count = 3.0
messages = ['409422', '409438', '409447']
nosy_count = 4.0
nosy_names = ['terry.reedy', 'steven.daprano', 'xdegaye', 'DonaldDuck1313']
pr_nums = ['30106']
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue46213'
versions = ['Python 3.10']
In Termux, if I type the following code, I would expect it to open the URL in a browser, but it does nothing:
import webbrowser
webbrowser.open("http://example.com")
https://termux.com/ "Termux is an Android terminal emulator [on Android] and Linux environment app"
I don't believe that core devs (and b.p.o.) support running Python on Android. If so, this should be closed here and your question redirected to whoever supplied your Android python installer. They might just say that Termux is not a supported terminal.
I think the existence of sys.getandroidapilevel is evidence that Android is somewhat supported, even if it is not supported to the same degree that Linux and Windows are.
https://docs.python.org/3/library/sys.html#sys.getandroidapilevel
See also:
https://mail.python.org/pipermail/python-dev/2017-December/151171.html
for a longer discussion. There's an Android build factory
https://github.com/python/buildmaster-config/pull/26
but I cannot see an official Android buildbot running.
https://buildbot.python.org/all/#/
The PR seems straightforward and simple to me, but I'm not an expert on the webbrowser module nor do I have an Android where I can test it to see if it works.
DonaldDuck1313, your NEWS entry needs to be re-written to use ReST (Restructured Text) rather than Markdown:
Change: Termux
to Termux <https://termux.com/>_
The issue is that the termux browser (redirecting out to the actual browser) isn't registered. You can register it by using
import webbrowser
webbrowser.register("termux-open-url '%s'", None)
# Now the module can open the browser.
After that the webbrowser module will call to termux-open-url which will then open the real browser with the given URL. You only have to do this once and after that it should work all the time as expected.
Android is now officially supported since Python 3.13, but the webbrowser module still doesn't work. I've migrated the following notes from https://github.com/chaquo/chaquopy/issues/1149 and https://github.com/chaquo/chaquopy/issues/1387.
The usual Kotlin code to launch a web browser would be something like this:
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"))
context.startActivity(intent)
It would be reasonably easy to translate this into C or ctypes using JNI. However, Android doesn't provide any public way to get a context unless you already have a reference to a UI object. Unofficially, it's still possible using something like this:
jclass activityThread = (*env)->FindClass(env,"android/app/ActivityThread");
jmethodID currentActivityThread = (*env)->GetStaticMethodID(env, activityThread, "currentActivityThread", "()Landroid/app/ActivityThread;");
jobject activityThreadObj = (*env)->CallStaticObjectMethod(env, activityThread, currentActivityThread);
jmethodID getApplication = (*env)->GetMethodID(env, activityThread, "getApplication", "()Landroid/app/Application;");
jobject context = (*env)->CallObjectMethod(env, activityThreadObj, getApplication);
Although ActivityThread is a hidden class, the relevant methods are all marked with @UnsupportedAppUsage, which means Google hasn't blocked them because they're aware that applications are using them.
Alternatively, it may be possible to launch a web browser using the am start command, as in this xdg-utils port for Termux. This would be much simpler, and has the advantage that it is a supported interface in the Android shell, though I'm not certain whether it's supported from a regular app.
Thinking outside the box here - Given that the Context object is sufficiently foundational to Android APIs, would it be worth having an official API to provide the Python interpreter with a JNI reference to that context object?
That way, at runtime, Chaquopy (or any other tool embedding Python) could call the Android initialisation mechanism to set the context as soon as it is available, and then webbrowser (or any other mechanism needing access to Android runtime features) could construct the necessary objects using only official APIs, rather than needing to rely on hacks.
Alternatively, it may be possible to launch a web browser using the
am startcommand, as in the xdg-utils for Termux. This would be much simpler, and has the advantage that it is a supported interface in the Android shell, though I'm not certain whether it's supported from a regular app.
This doesn't work on any emulator I've tried. When calling:
subprocess.run(["am", "start", "-a", "android.intent.action.VIEW", "-d", "https://python.org/"], capture_output=True, text=True)
Older Android versions (API level 24) say this:
java.lang.SecurityException: Permission Denial: startActivity asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL
And newer ones (API level 35):
java.lang.SecurityException: Permission Denial: package=com.android.shell does not belong to uid=10231
I guess this means they've locked down the am command so it can only be run from an actual shell session, not a normal app.
Termux's current xdg-open implementation works by sending a broadcast to a helper app, which then itself creates the Intent. That isn't an approach that would work in general for an embedded Python.
Given that the Context object is sufficiently foundational to Android APIs, would it be worth having an official API to provide the Python interpreter with a JNI reference to that context object?
Yes, that might be a good idea.
I've tried this about 4 different ways with no results. I know this is hacky but in my app I run several rust cli programs just by renaming the executable to libwhatever.so and placing it into the libs folder before building.. then launching it with process builder. Example of my craziness even trying to use xdg-open this way doesn't work and gives zero feedback