Skip to content

Commit 0d491b9

Browse files
committed
Merge branch 'KeyWeeUsr-sdl2_launcher'
2 parents 8fdedc9 + 7e91e81 commit 0d491b9

File tree

17 files changed

+496
-30
lines changed

17 files changed

+496
-30
lines changed

doc/source/launcher.rst

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,23 @@ python-for-android.
2020
Building
2121
--------
2222

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

2927
.. highlight:: none
3028

3129
::
3230

33-
p4a clean_dists
34-
p4a clean_builds
31+
p4a clean_download_cache requirements
32+
p4a clean_dists && p4a clean_builds
3533
p4a apk --requirements=requirements \
3634
--permission PERMISSION \
3735
--package=the.package.name \
3836
--name="App name" \
3937
--version=x.y.z \
4038
--android_api XY \
41-
--bootstrap=pygame \
39+
--bootstrap=pygame or sdl2 \
4240
--launcher \
4341
--minsdk 13
4442

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

81+
To differentiate between apps in ``/sdcard/kivy`` you can include an icon
82+
named ``icon.png`` to the folder. The icon should be a square.
83+
8384
Release on the market
8485
---------------------
8586

@@ -91,10 +92,14 @@ Source code
9192
-----------
9293

9394
.. |renpy| replace:: pygame org.renpy.android
95+
.. |kivy| replace:: sdl2 org.kivy.android
9496

9597
.. _renpy:
9698
https://github.com/kivy/python-for-android/tree/master/\
9799
pythonforandroid/bootstraps/pygame/build/src/org/renpy/android
100+
.. _sdl2:
101+
https://github.com/kivy/python-for-android/tree/master/\
102+
pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android
98103

99104
If you feel confident, feel free to improve the launcher. You can find the
100-
source code at |renpy|_.
105+
source code at |renpy|_ or at |kivy|_.

pythonforandroid/bootstraps/sdl2/build/build.py

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
if PYTHON is not None:
5151
BLACKLIST_PATTERNS.append('*.py')
5252

53-
WHITELIST_PATTERNS = []
53+
WHITELIST_PATTERNS = ['pyconfig.h', ]
5454

5555
python_files = []
5656

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

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

233235
# Delete the old assets.
234236
if exists('assets/public.mp3'):
@@ -248,8 +250,13 @@ def make_package(args):
248250
tar_dirs.append('private')
249251
if exists('crystax_python'):
250252
tar_dirs.append('crystax_python')
253+
251254
if args.private:
252255
make_tar('assets/private.mp3', tar_dirs, args.ignore_path)
256+
elif args.launcher:
257+
# clean 'None's as a result of main.py path absence
258+
tar_dirs = [tdir for tdir in tar_dirs if tdir]
259+
make_tar('assets/private.mp3', tar_dirs, args.ignore_path)
253260
# else:
254261
# make_tar('assets/private.mp3', ['private'])
255262

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

269276

270-
# Prepare some variables for templating process
277+
# folder name for launcher
278+
url_scheme = 'kivy'
271279

272-
default_icon = 'templates/kivy-icon.png'
280+
# Prepare some variables for templating process
281+
if args.launcher:
282+
default_icon = 'templates/launcher-icon.png'
283+
default_presplash = 'templates/launcher-presplash.jpg'
284+
else:
285+
default_icon = 'templates/kivy-icon.png'
286+
default_presplash = 'templates/kivy-presplash.jpg'
273287
shutil.copy(args.icon or default_icon, 'res/drawable/icon.png')
274288

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

@@ -312,9 +325,10 @@ def make_package(args):
312325
args.extra_source_dirs = []
313326

314327
service = False
315-
service_main = join(realpath(args.private), 'service', 'main.py')
316-
if exists(service_main) or exists(service_main + 'o'):
317-
service = True
328+
if args.private:
329+
service_main = join(realpath(args.private), 'service', 'main.py')
330+
if exists(service_main) or exists(service_main + 'o'):
331+
service = True
318332

319333
service_names = []
320334
for sid, spec in enumerate(args.services):
@@ -344,6 +358,7 @@ def make_package(args):
344358
args=args,
345359
service=service,
346360
service_names=service_names,
361+
url_scheme=url_scheme,
347362
)
348363

349364
render(
@@ -355,7 +370,9 @@ def make_package(args):
355370
render(
356371
'strings.tmpl.xml',
357372
'res/values/strings.xml',
358-
args=args)
373+
args=args,
374+
url_scheme=url_scheme,
375+
)
359376

360377
render(
361378
'custom_rules.tmpl.xml',
@@ -391,8 +408,9 @@ def parse_args(args=None):
391408
''')
392409

393410
ap.add_argument('--private', dest='private',
394-
help='the dir of user files',
395-
required=True)
411+
help='the dir of user files')
412+
# , required=True) for launcher, crashes in make_package
413+
# if not mentioned (and the check is there anyway)
396414
ap.add_argument('--package', dest='package',
397415
help=('The name of the java package the project will be'
398416
' packaged under.'),
@@ -419,6 +437,9 @@ def parse_args(args=None):
419437
'android_screenOrientation at '
420438
'https://developer.android.com/guide/topics/manifest/'
421439
'activity-element.html'))
440+
ap.add_argument('--launcher', dest='launcher', action='store_true',
441+
help=('Provide this argument to build a multi-app '
442+
'launcher, rather than a single app.'))
422443
ap.add_argument('--icon', dest='icon',
423444
help='A png file to use as the icon for the application.')
424445
ap.add_argument('--permission', dest='permissions', action='append',
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout
3+
xmlns:android="http://schemas.android.com/apk/res/android"
4+
android:orientation="horizontal"
5+
android:gravity="center"
6+
>
7+
8+
<ImageView
9+
android:id="@+id/icon"
10+
android:layout_width="64sp"
11+
android:layout_height="64sp"
12+
android:scaleType="fitCenter"
13+
android:padding="2sp"
14+
/>
15+
16+
<LinearLayout
17+
android:orientation="vertical"
18+
android:layout_width="fill_parent"
19+
android:layout_height="wrap_content"
20+
>
21+
22+
<TextView
23+
android:layout_width="wrap_content"
24+
android:layout_height="wrap_content"
25+
android:id="@+id/title"
26+
android:textSize="18sp"
27+
android:textColor="#fff"
28+
android:singleLine="true"
29+
/>
30+
31+
<TextView
32+
android:layout_width="wrap_content"
33+
android:layout_height="wrap_content"
34+
android:singleLine="true"
35+
android:id="@+id/author"
36+
/>
37+
38+
</LinearLayout>
39+
</LinearLayout>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<LinearLayout
4+
xmlns:android="http://schemas.android.com/apk/res/android"
5+
android:orientation="vertical"
6+
>
7+
8+
<TextView
9+
android:text="Please choose a project:"
10+
android:layout_width="fill_parent"
11+
android:layout_height="wrap_content"
12+
android:padding="4sp"
13+
/>
14+
15+
<ListView
16+
android:id="@+id/projectList"
17+
android:layout_width="fill_parent"
18+
android:layout_height="fill_parent"
19+
/>
20+
21+
22+
</LinearLayout>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<LinearLayout
4+
xmlns:android="http://schemas.android.com/apk/res/android"
5+
android:orientation="vertical"
6+
>
7+
8+
<TextView
9+
android:id="@+id/emptyText"
10+
android:layout_width="fill_parent"
11+
android:layout_height="wrap_content"
12+
android:padding="4sp"
13+
/>
14+
15+
</LinearLayout>

pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonActivity.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import android.graphics.PixelFormat;
2424
import android.view.SurfaceHolder;
2525
import android.content.Context;
26+
import android.content.pm.ActivityInfo;
2627
import android.content.pm.PackageManager;
2728
import android.content.pm.ApplicationInfo;
2829
import android.content.Intent;
@@ -35,6 +36,7 @@
3536
import org.libsdl.app.SDLActivity;
3637

3738
import org.kivy.android.PythonUtil;
39+
import org.kivy.android.launcher.Project;
3840

3941
import org.renpy.android.ResourceManager;
4042
import org.renpy.android.AssetExtract;
@@ -72,14 +74,48 @@ protected void onCreate(Bundle savedInstanceState) {
7274
this.mActivity = this;
7375
this.showLoadingScreen();
7476

75-
77+
// Figure out the directory where the game is. If the game was
78+
// given to us via an intent, then we use the scheme-specific
79+
// part of that intent to determine the file to launch. We
80+
// also use the android.txt file to determine the orientation.
81+
//
82+
// Otherwise, we use the public data, if we have it, or the
83+
// private data if we do not.
7684
String app_root_dir = getAppRoot();
85+
if (getIntent() != null && getIntent().getAction() != null &&
86+
getIntent().getAction().equals("org.kivy.LAUNCH")) {
87+
File path = new File(getIntent().getData().getSchemeSpecificPart());
88+
89+
Project p = Project.scanDirectory(path);
90+
SDLActivity.nativeSetEnv("ANDROID_ENTRYPOINT", p.dir + "/main.py");
91+
SDLActivity.nativeSetEnv("ANDROID_ARGUMENT", p.dir);
92+
SDLActivity.nativeSetEnv("ANDROID_APP_PATH", p.dir);
93+
94+
if (p != null) {
95+
if (p.landscape) {
96+
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
97+
} else {
98+
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
99+
}
100+
}
101+
102+
// Let old apps know they started.
103+
try {
104+
FileWriter f = new FileWriter(new File(path, ".launch"));
105+
f.write("started");
106+
f.close();
107+
} catch (IOException e) {
108+
// pass
109+
}
110+
} else {
111+
SDLActivity.nativeSetEnv("ANDROID_ENTRYPOINT", "main.pyo");
112+
SDLActivity.nativeSetEnv("ANDROID_ARGUMENT", app_root_dir);
113+
SDLActivity.nativeSetEnv("ANDROID_APP_PATH", app_root_dir);
114+
}
115+
77116
String mFilesDirectory = mActivity.getFilesDir().getAbsolutePath();
78117
Log.v(TAG, "Setting env vars for start.c and Python to use");
79118
SDLActivity.nativeSetEnv("ANDROID_PRIVATE", mFilesDirectory);
80-
SDLActivity.nativeSetEnv("ANDROID_ARGUMENT", app_root_dir);
81-
SDLActivity.nativeSetEnv("ANDROID_APP_PATH", app_root_dir);
82-
SDLActivity.nativeSetEnv("ANDROID_ENTRYPOINT", "main.pyo");
83119
SDLActivity.nativeSetEnv("PYTHONHOME", app_root_dir);
84120
SDLActivity.nativeSetEnv("PYTHONPATH", app_root_dir + ":" + app_root_dir + "/lib");
85121
SDLActivity.nativeSetEnv("PYTHONOPTIMIZE", "2");

0 commit comments

Comments
 (0)