Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 14 additions & 9 deletions doc/source/launcher.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,23 @@ python-for-android.
Building
--------

The Kivy Launcher is built using python-for-android, and is currently
only supported by the pygame bootstrap (there is no SDL2 launcher
yet). To get the most recent versions of packages you need to clean
them first, so that the packager won't grab an old package instead of
fresh one.
The Kivy Launcher is built using python-for-android. To get the most recent
versions of packages you need to clean them first, so that the packager won't
grab an old (cached) package instead of fresh one.

.. highlight:: none

::

p4a clean_dists
p4a clean_builds
p4a clean_download_cache requirements
p4a clean_dists && p4a clean_builds
p4a apk --requirements=requirements \
--permission PERMISSION \
--package=the.package.name \
--name="App name" \
--version=x.y.z \
--android_api XY \
--bootstrap=pygame \
--bootstrap=pygame or sdl2 \
--launcher \
--minsdk 13

Expand Down Expand Up @@ -80,6 +78,9 @@ to change other settings.
After you set your `android.txt` file, you can now run the launcher
and start any available app from the list.

To differentiate between apps in ``/sdcard/kivy`` you can include an icon
named ``icon.png`` to the folder. The icon should be a square.

Release on the market
---------------------

Expand All @@ -91,10 +92,14 @@ Source code
-----------

.. |renpy| replace:: pygame org.renpy.android
.. |kivy| replace:: sdl2 org.kivy.android

.. _renpy:
https://github.com/kivy/python-for-android/tree/master/\
pythonforandroid/bootstraps/pygame/build/src/org/renpy/android
.. _sdl2:
https://github.com/kivy/python-for-android/tree/master/\
pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android

If you feel confident, feel free to improve the launcher. You can find the
source code at |renpy|_.
source code at |renpy|_ or at |kivy|_.
49 changes: 35 additions & 14 deletions pythonforandroid/bootstraps/sdl2/build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
if PYTHON is not None:
BLACKLIST_PATTERNS.append('*.py')

WHITELIST_PATTERNS = []
WHITELIST_PATTERNS = ['pyconfig.h', ]

python_files = []

Expand Down Expand Up @@ -222,13 +222,15 @@ def make_package(args):
# print('Your PATH must include android tools.')
# sys.exit(-1)

if not (exists(join(realpath(args.private), 'main.py')) or
exists(join(realpath(args.private), 'main.pyo'))):
print('''BUILD FAILURE: No main.py(o) found in your app directory. This
# Ignore warning if the launcher is in args
if not args.launcher:
if not (exists(join(realpath(args.private), 'main.py')) or
exists(join(realpath(args.private), 'main.pyo'))):
print('''BUILD FAILURE: No main.py(o) found in your app directory. This
file must exist to act as the entry point for you app. If your app is
started by a file with a different name, rename it to main.py or add a
main.py that loads it.''')
exit(1)
exit(1)

# Delete the old assets.
if exists('assets/public.mp3'):
Expand All @@ -248,8 +250,13 @@ def make_package(args):
tar_dirs.append('private')
if exists('crystax_python'):
tar_dirs.append('crystax_python')

if args.private:
make_tar('assets/private.mp3', tar_dirs, args.ignore_path)
elif args.launcher:
# clean 'None's as a result of main.py path absence
tar_dirs = [tdir for tdir in tar_dirs if tdir]
make_tar('assets/private.mp3', tar_dirs, args.ignore_path)
# else:
# make_tar('assets/private.mp3', ['private'])

Expand All @@ -267,12 +274,18 @@ def make_package(args):
# sys.exit(-1)


# Prepare some variables for templating process
# folder name for launcher
url_scheme = 'kivy'

default_icon = 'templates/kivy-icon.png'
# Prepare some variables for templating process
if args.launcher:
default_icon = 'templates/launcher-icon.png'
default_presplash = 'templates/launcher-presplash.jpg'
else:
default_icon = 'templates/kivy-icon.png'
default_presplash = 'templates/kivy-presplash.jpg'
shutil.copy(args.icon or default_icon, 'res/drawable/icon.png')

default_presplash = 'templates/kivy-presplash.jpg'
shutil.copy(args.presplash or default_presplash,
'res/drawable/presplash.jpg')

Expand Down Expand Up @@ -312,9 +325,10 @@ def make_package(args):
args.extra_source_dirs = []

service = False
service_main = join(realpath(args.private), 'service', 'main.py')
if exists(service_main) or exists(service_main + 'o'):
service = True
if args.private:
service_main = join(realpath(args.private), 'service', 'main.py')
if exists(service_main) or exists(service_main + 'o'):
service = True

service_names = []
for sid, spec in enumerate(args.services):
Expand Down Expand Up @@ -344,6 +358,7 @@ def make_package(args):
args=args,
service=service,
service_names=service_names,
url_scheme=url_scheme,
)

render(
Expand All @@ -355,7 +370,9 @@ def make_package(args):
render(
'strings.tmpl.xml',
'res/values/strings.xml',
args=args)
args=args,
url_scheme=url_scheme,
)

render(
'custom_rules.tmpl.xml',
Expand Down Expand Up @@ -391,8 +408,9 @@ def parse_args(args=None):
''')

ap.add_argument('--private', dest='private',
help='the dir of user files',
required=True)
help='the dir of user files')
# , required=True) for launcher, crashes in make_package
# if not mentioned (and the check is there anyway)
ap.add_argument('--package', dest='package',
help=('The name of the java package the project will be'
' packaged under.'),
Expand All @@ -414,6 +432,9 @@ def parse_args(args=None):
help=('The orientation that the game will display in. '
'Usually one of "landscape", "portrait" or '
'"sensor"'))
ap.add_argument('--launcher', dest='launcher', action='store_true',
help=('Provide this argument to build a multi-app '
'launcher, rather than a single app.'))
ap.add_argument('--icon', dest='icon',
help='A png file to use as the icon for the application.')
ap.add_argument('--permission', dest='permissions', action='append',
Expand Down
39 changes: 39 additions & 0 deletions pythonforandroid/bootstraps/sdl2/build/res/layout/chooser_item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="center"
>

<ImageView
android:id="@+id/icon"
android:layout_width="64sp"
android:layout_height="64sp"
android:scaleType="fitCenter"
android:padding="2sp"
/>

<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/title"
android:textSize="18sp"
android:textColor="#fff"
android:singleLine="true"
/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:id="@+id/author"
/>

</LinearLayout>
</LinearLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
>

<TextView
android:text="Please choose a project:"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4sp"
/>

<ListView
android:id="@+id/projectList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>


</LinearLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
>

<TextView
android:id="@+id/emptyText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4sp"
/>

</LinearLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.kivy.android;

import java.io.UnsupportedEncodingException;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;

import android.util.Log;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;


/**
* This represents a project we've scanned for.
*/
public class Project {

String dir = null;
String title = null;
String author = null;
Bitmap icon = null;
boolean landscape = false;

static String decode(String s) {
try {
return new String(s.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
return s;
}
}

/**
* Scans directory for a android.txt file. If it finds one,
* and it looks valid enough, then it creates a new Project,
* and returns that. Otherwise, returns null.
*/
public static Project scanDirectory(File dir) {

// We might have a link file.
if (dir.getAbsolutePath().endsWith(".link")) {
try {

// Scan the android.txt file.
File propfile = new File(dir, "android.txt");
FileInputStream in = new FileInputStream(propfile);
Properties p = new Properties();
p.load(in);
in.close();

String directory = p.getProperty("directory", null);

if (directory == null) {
return null;
}

dir = new File(directory);

} catch (Exception e) {
Log.i("Project", "Couldn't open link file " + dir, e);
}
}

// Make sure we're dealing with a directory.
if (! dir.isDirectory()) {
return null;
}

try {

// Scan the android.txt file.
File propfile = new File(dir, "android.txt");
FileInputStream in = new FileInputStream(propfile);
Properties p = new Properties();
p.load(in);
in.close();

// Get the various properties.
String title = decode(p.getProperty("title", "Untitled"));
String author = decode(p.getProperty("author", ""));
boolean landscape = p.getProperty("orientation", "portrait").equals("landscape");

// Create the project object.
Project rv = new Project();
rv.title = title;
rv.author = author;
rv.icon = BitmapFactory.decodeFile(new File(dir, "icon.png").getAbsolutePath());
rv.landscape = landscape;
rv.dir = dir.getAbsolutePath();

return rv;

} catch (Exception e) {
Log.i("Project", "Couldn't open android.txt", e);
}

return null;

}
}
Loading