File: mergeall-android-scripts/_readme-items/PYDROID3-TKINTER/CODE/_openbrowser.py
# Python 3.X code run in the Pydroid 3 app's IDE
"""
===================================================================
Open documents by URL in a browser or other viewer on Android.
UPDATE APRIL 21, 2019
---------------------
The document-open story recently changed in the Pydroid 3 app:
- Prior to its 3.0 release, its $BROWSER setting sufficed
to enable webbrowser use on Android as described below.
- As of 3.0, its DISPLAY setting makes webbrowser crash, and
its $BROWSER setting disables local-file URLs in any event.
To open documents in _both_ Pydroid 3's 2.2 and 3.0 releases,
use os.system() and a hardcoded activity-manager command of
the form ahead. This works as well as pre-3.0 webbrowser,
and avoids environment changes of unknown consequence.
For full details, see:
http://learning-python.com/
mergeall-android-scripts/_README.html#webbrowsermodule
ORIGINAL NOTES
--------------
The code below demos opening a file by URL in a browser (or
other viewer) on Android, using both a manual activity-manager
shell command, and Python's webbrowser module.
To support both schemes, Pydroid 3's 2.2 release predefines a
template for the required command in $BROWSER like this:
am start --user 0 -a android.intent.action.VIEW -d %s
In the first scheme, this script launches a command-line
string like the following with Python's os.system():
am start --user 0 -a android.intent.action.VIEW -d http://...
In the second scheme, the webbrowser module does similar, but
automatically uses $BROWSER if set in the host platform's shell,
calling subprocess.Popen() to spawn the same command line.
In both schemes, viewers run in parallel on Android, and a back
tap returns to their spawner immediately (if still running).
Both schemes are picky about URLs: local requires a "file://"
and rendering HTML files seems to require a remote "http://".
webbrowser is cross platform, but has no advantage on Android.
CAVEATS
-------
- When pressed, Buttons may lose their background color, and stay
depressed occasionally an some devices (known Pydroid 3 bugs).
- These schemes rely on Android's default-apps model, which is
not as general or inclusive as filename associations elsewhere.
===================================================================
"""
import os, webbrowser
from tkinter import *
def openBrowser_System(url, trace=True):
"""
Open a viewer for a URL, with a spawned shell command.
Don't use $BROWSER: it disables "file://" in Pydroid 3 3.0.
"""
#brw = os.environ['BROWSER']
brw = 'am start --user 0 -a android.intent.action.VIEW -d %s'
cmd = brw % url
os.system(cmd)
if trace: print('opened by command:', repr(cmd), end='\n\n')
def openBrowser_Module(url, trace=True):
"""
Open a viewer for a URL, with Python's webbrowser module.
All webbrowser.open() calls work in Pydroid 2.2, fail in 3.0.
A first 3.0 exception seems to leave webbrowser unresponsive.
"""
try:
webbrowser.open(url) # fails in Pydroid 3 3.0 per above
except:
print('FAILED module open:', repr(url))
print(sys.exc_info()[0], '\n', sys.exc_info()[1], end='\n\n')
else:
if trace: print('opened by module:', repr(url), end='\n\n')
def onBrowse():
"""
Pick next URL and opener on wrap-around lists.
The math opens all urls in each opener in turn:
i.e., for x in openers, for y in urls, x(y).
"""
global nview
url = urls[nview % len(urls)]
opn = openers[(nview // len(urls)) % len(openers)]
opn(url)
nview += 1
openers = [
openBrowser_System,
openBrowser_Module
]
urls = [
'http://learning-python.com',
'http://www.python.org',
'http://www.tcl.tk',
'http://learning-python.com/programs.html',
'file:///sdcard/shared.txt', # until Android Q breaks?
'file://%s/local.txt' % os.getcwd(), # permission dependent
'file:///sdcard/nonesuch.txt' # test invalid files
]
# make test files
nview = 0
open('local.txt', 'w').write('local dir')
open('/sdcard/shared.txt', 'w').write('shared dir')
# build and run gui
root = Tk()
Button(root, text='Browse',
width=18, height=10, font='arial 8 bold', # fails: bg='ivory'
command=onBrowse).pack(expand=YES)
root.mainloop()
# delete test files
os.remove('local.txt')
os.remove('/sdcard/shared.txt')