Skip to content

Add webview bootstrap #728

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
May 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
268c218
Added flask testapp
inclement Apr 16, 2016
cb1f67e
Added webview bootstrap
inclement Apr 16, 2016
76ed15e
Moved setenv jni call to PythonActivity
inclement Apr 27, 2016
7da7793
Added python recipes to dist info
inclement Apr 27, 2016
332c26c
Added python modules list to ctx when found
inclement Apr 27, 2016
64432c2
Slightly updated flask testapp
inclement Apr 27, 2016
8327b88
Removed SDL2 dependency in webview bootstrap
inclement Apr 28, 2016
2316e2b
Added webviewjni recipe
inclement Apr 28, 2016
14f61aa
Removed SDL java code from webview bootstrap
inclement Apr 28, 2016
76cf5e7
Removed hardcoded webview load file location
inclement Apr 28, 2016
f59c0be
Removed opengl from webview AndroidManifest.xml
inclement Apr 28, 2016
a034b4b
Added webview splash loader to bootstrap folders
inclement Apr 28, 2016
095921d
Fixed SDL2 references in webview bootstrap init
inclement Apr 28, 2016
7106409
Added webview bootstrap to doc
inclement May 1, 2016
345057c
Fixed pyjnius build with webviewjni
inclement May 1, 2016
b4fac4f
Added Flask recipe
inclement May 1, 2016
3358bf9
Added vibrate button to flask test app
inclement May 1, 2016
38b0970
Added orientation buttons to flask testapp
inclement May 1, 2016
33be3be
Removed sdl2 images from webview
inclement May 1, 2016
91fee21
Changed flask version to 0.10.1
inclement May 1, 2016
331b6b6
Added pyjnius code for webview bootstrap
inclement May 6, 2016
fa8c371
Added java loader for python webserver
inclement May 6, 2016
63c4652
Removed load.html from flask testapp
inclement May 6, 2016
17e6f45
Moved WebViewLoader to template to set port
inclement May 6, 2016
4973f8b
Changed webview pyjnius patch function names
inclement May 6, 2016
ee24ac4
Added INTERNET permission for webview by default
inclement May 6, 2016
ea20745
Added --port option for webview bootstrap
inclement May 6, 2016
7df9f44
Documented --port option for webview bootstrap
inclement May 6, 2016
0eb8f1b
Reworded webview doc
inclement May 7, 2016
8f9d17e
Merge branch 'webview_bootstrap' of https://github.com/inclement/pyth…
inclement May 7, 2016
64ba407
Slightly refactored webview java code
inclement May 7, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions doc/source/buildoptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ yet have one.
features of the Pygame one. It is under active development to fix
these omissions.

webview
~~~~~~~

You can use this with ``--bootstrap=webview``, or simply include the
``webviewjni`` recipe in your ``--requirements``.

The webview bootstrap gui is, per the name, a WebView displaying a
webpage, but this page is hosted on the device via a Python
webserver. For instance, your Python code can start a Flask
application, and your app will display and allow the user to navigate
this website.

This bootstrap will automatically try to load a website on port 5000
(the default for Flask), or you can specify a different option with
the `--port` command line option. If the webserver is not immediately
present (e.g. during the short Python loading time when first
started), it will instead display a loading screen until the server is
ready.


pygame
~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion pythonforandroid/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def run_distribute(self):
json.dump({'dist_name': self.ctx.dist_name,
'bootstrap': self.ctx.bootstrap.name,
'archs': [arch.arch for arch in self.ctx.archs],
'recipes': self.ctx.recipe_build_order},
'recipes': self.ctx.recipe_build_order + self.ctx.python_modules},
fileh)

@classmethod
Expand Down
119 changes: 119 additions & 0 deletions pythonforandroid/bootstraps/webview/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from pythonforandroid.toolchain import Bootstrap, shprint, current_directory, info, warning, ArchARM, info_main
from os.path import join, exists, curdir, abspath
from os import walk
import glob
import sh

class WebViewBootstrap(Bootstrap):
name = 'webview'

recipe_depends = ['webviewjni', ('python2', 'python3crystax')]

def run_distribute(self):
info_main('# Creating Android project from build and {} bootstrap'.format(
self.name))

shprint(sh.rm, '-rf', self.dist_dir)
shprint(sh.cp, '-r', self.build_dir, self.dist_dir)
with current_directory(self.dist_dir):
with open('local.properties', 'w') as fileh:
fileh.write('sdk.dir={}'.format(self.ctx.sdk_dir))

arch = self.ctx.archs[0]
if len(self.ctx.archs) > 1:
raise ValueError('built for more than one arch, but bootstrap cannot handle that yet')
info('Bootstrap running with arch {}'.format(arch))

with current_directory(self.dist_dir):
info('Copying python distribution')

if not exists('private') and not self.ctx.python_recipe.from_crystax:
shprint(sh.mkdir, 'private')
if not exists('crystax_python') and self.ctx.python_recipe.from_crystax:
shprint(sh.mkdir, 'crystax_python')
shprint(sh.mkdir, 'crystax_python/crystax_python')
if not exists('assets'):
shprint(sh.mkdir, 'assets')

hostpython = sh.Command(self.ctx.hostpython)
if not self.ctx.python_recipe.from_crystax:
try:
shprint(hostpython, '-OO', '-m', 'compileall',
self.ctx.get_python_install_dir(),
_tail=10, _filterout="^Listing")
except sh.ErrorReturnCode:
pass
if not exists('python-install'):
shprint(sh.cp, '-a', self.ctx.get_python_install_dir(), './python-install')

self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
self.distribute_aars(arch)
self.distribute_javaclasses(self.ctx.javaclass_dir)

if not self.ctx.python_recipe.from_crystax:
info('Filling private directory')
if not exists(join('private', 'lib')):
info('private/lib does not exist, making')
shprint(sh.cp, '-a', join('python-install', 'lib'), 'private')
shprint(sh.mkdir, '-p', join('private', 'include', 'python2.7'))

# AND: Copylibs stuff should go here
if exists(join('libs', arch.arch, 'libpymodules.so')):
shprint(sh.mv, join('libs', arch.arch, 'libpymodules.so'), 'private/')
shprint(sh.cp, join('python-install', 'include' , 'python2.7', 'pyconfig.h'), join('private', 'include', 'python2.7/'))

info('Removing some unwanted files')
shprint(sh.rm, '-f', join('private', 'lib', 'libpython2.7.so'))
shprint(sh.rm, '-rf', join('private', 'lib', 'pkgconfig'))

libdir = join(self.dist_dir, 'private', 'lib', 'python2.7')
site_packages_dir = join(libdir, 'site-packages')
with current_directory(libdir):
# shprint(sh.xargs, 'rm', sh.grep('-E', '*\.(py|pyx|so\.o|so\.a|so\.libs)$', sh.find('.')))
removes = []
for dirname, something, filens in walk('.'):
for filename in filens:
for suffix in ('py', 'pyc', 'so.o', 'so.a', 'so.libs'):
if filename.endswith(suffix):
removes.append(filename)
shprint(sh.rm, '-f', *removes)

info('Deleting some other stuff not used on android')
# To quote the original distribute.sh, 'well...'
# shprint(sh.rm, '-rf', 'ctypes')
shprint(sh.rm, '-rf', 'lib2to3')
shprint(sh.rm, '-rf', 'idlelib')
for filename in glob.glob('config/libpython*.a'):
shprint(sh.rm, '-f', filename)
shprint(sh.rm, '-rf', 'config/python.o')
# shprint(sh.rm, '-rf', 'lib-dynload/_ctypes_test.so')
# shprint(sh.rm, '-rf', 'lib-dynload/_testcapi.so')

else: # Python *is* loaded from crystax
ndk_dir = self.ctx.ndk_dir
py_recipe = self.ctx.python_recipe
python_dir = join(ndk_dir, 'sources', 'python', py_recipe.version,
'libs', arch.arch)

shprint(sh.cp, '-r', join(python_dir, 'stdlib.zip'), 'crystax_python/crystax_python')
shprint(sh.cp, '-r', join(python_dir, 'modules'), 'crystax_python/crystax_python')
shprint(sh.cp, '-r', self.ctx.get_python_install_dir(), 'crystax_python/crystax_python/site-packages')

info('Renaming .so files to reflect cross-compile')
site_packages_dir = 'crystax_python/crystax_python/site-packages'
filens = shprint(sh.find, site_packages_dir, '-iname', '*.so').stdout.decode(
'utf-8').split('\n')[:-1]
for filen in filens:
parts = filen.split('.')
if len(parts) <= 2:
continue
shprint(sh.mv, filen, filen.split('.')[0] + '.so')
site_packages_dir = join(abspath(curdir),
site_packages_dir)


self.strip_libraries(arch)
self.fry_eggs(site_packages_dir)
super(WebViewBootstrap, self).run_distribute()

bootstrap = WebViewBootstrap()
45 changes: 45 additions & 0 deletions pythonforandroid/bootstraps/webview/build/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Replace org.libsdl.app with the identifier of your game below, e.g.
com.gamemaker.game
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.kivy.android"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto">

<!-- Android 2.3.3 -->
<uses-sdk android:minSdkVersion="12" android:targetSdkVersion="12" />

<!-- OpenGL ES 2.0 -->
<uses-feature android:glEsVersion="0x00020000" />

<!-- Allow writing to external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- Create a Java class extending SDLActivity and place it in a
directory under src matching the package, e.g.
src/com/gamemaker/game/MyGame.java

then replace "SDLActivity" with the name of your class (e.g. "MyGame")
in the XML below.

An example Java class can be found in README-android.txt
-->
<application android:label="@string/app_name"
android:icon="@drawable/icon"
android:allowBackup="true"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:hardwareAccelerated="true" >
<activity android:name="org.kivy.android.PythonActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
18 changes: 18 additions & 0 deletions pythonforandroid/bootstraps/webview/build/ant.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.

# This file is only used by the Ant script.

# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.

# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.

source.absolute.dir = tmp-src
90 changes: 90 additions & 0 deletions pythonforandroid/bootstraps/webview/build/blacklist.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# prevent user to include invalid extensions
*.apk
*.pxd

# eggs
*.egg-info

# unit test
unittest/*

# python config
config/makesetup

# unused kivy files (platform specific)
kivy/input/providers/wm_*
kivy/input/providers/mactouch*
kivy/input/providers/probesysfs*
kivy/input/providers/mtdev*
kivy/input/providers/hidinput*
kivy/core/camera/camera_videocapture*
kivy/core/spelling/*osx*
kivy/core/video/video_pyglet*
kivy/tools
kivy/tests/*
kivy/*/*.h
kivy/*/*.pxi

# unused encodings
lib-dynload/*codec*
encodings/cp*.pyo
encodings/tis*
encodings/shift*
encodings/bz2*
encodings/iso*
encodings/undefined*
encodings/johab*
encodings/p*
encodings/m*
encodings/euc*
encodings/k*
encodings/unicode_internal*
encodings/quo*
encodings/gb*
encodings/big5*
encodings/hp*
encodings/hz*

# unused python modules
bsddb/*
wsgiref/*
hotshot/*
pydoc_data/*
tty.pyo
anydbm.pyo
nturl2path.pyo
LICENCE.txt
macurl2path.pyo
dummy_threading.pyo
audiodev.pyo
antigravity.pyo
dumbdbm.pyo
sndhdr.pyo
__phello__.foo.pyo
sunaudio.pyo
os2emxpath.pyo
multiprocessing/dummy*

# unused binaries python modules
lib-dynload/termios.so
lib-dynload/_lsprof.so
lib-dynload/*audioop.so
lib-dynload/mmap.so
lib-dynload/_hotshot.so
lib-dynload/_heapq.so
lib-dynload/_json.so
lib-dynload/grp.so
lib-dynload/resource.so
lib-dynload/pyexpat.so
lib-dynload/_ctypes_test.so
lib-dynload/_testcapi.so

# odd files
plat-linux3/regen

#>sqlite3
# conditionnal include depending if some recipes are included or not.
sqlite3/*
lib-dynload/_sqlite3.so
#<sqlite3

21 changes: 21 additions & 0 deletions pythonforandroid/bootstraps/webview/build/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked in Version Control Systems, as it is
# integral to the build system of your project.

# This file is only used by the Ant script.

# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.

# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.

key.store=${env.P4A_RELEASE_KEYSTORE}
key.alias=${env.P4A_RELEASE_KEYALIAS}
key.store.password=${env.P4A_RELEASE_KEYSTORE_PASSWD}
key.alias.password=${env.P4A_RELEASE_KEYALIAS_PASSWD}
Loading