8000 Merge branch 'sdl2_launcher' of https://github.com/KeyWeeUsr/python-f… · CoolCloud/python-for-android@ac8b68d · GitHub
[go: up one dir, main page]

Skip to content

Commit ac8b68d

Browse files
committed
Merge branch 'sdl2_launcher' of https://github.com/KeyWeeUsr/python-for-android into KeyWeeUsr-sdl2_launcher
2 parents 8fdedc9 + 2004698 commit ac8b68d

File tree

17 files changed

+496
-31
lines changed

17 files changed

+496
-31
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>
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package org.kivy.android;
2+
3+
import java.io.UnsupportedEncodingException;
4+
import java.io.File;
5+
import java.io.FileInputStream;
6+
import java.util.Properties;
7+
8+
import android.util.Log;
9+
import android.graphics.Bitmap;
10+
import android.graphics.BitmapFactory;
11+
12+
13+
/**
14+
* This represents a project we've scanned for.
15+
*/
16+
public class Project {
17+
18+
String dir = null;
19+
String title = null;
20+
String author = null;
21+
Bitmap icon = null;
22+
boolean landscape = false;
23+
24+
static String decode(String s) {
25+
try {
26+
return new String(s.getBytes("ISO-8859-1"), "UTF-8");
27+
} catch (UnsupportedEncodingException e) {
28+
return s;
29+
}
30+
}
31+
32+
/**
33+
* Scans directory for a android.txt file. If it finds one,
34+
* and it looks valid enough, then it creates a new Project,
35+
* and returns that. Otherwise, returns null.
36+
*/
37+
public static Project scanDirectory(File dir) {
38+
39+
// We might have a link file.
40+
if (dir.getAbsolutePath().endsWith(".link")) {
41+
try {
42+
43+
// Scan the android.txt file.
44+
File propfile = new File(dir, "android.txt");
45+
FileInputStream in = new FileInputStream(propfile);
46+
Properties p = new Properties();
47+
p.load(in);
48+
in.close();
49+
50+
String directory = p.getProperty("directory", null);
51+
52+
if (directory == null) {
53+
return null;
54+
}
55+
56+
dir = new File(directory);
57+
58+
} catch (Exception e) {
59+
Log.i("Project", "Couldn't open link file " + dir, e);
60+
}
61+
}
62+
63+
// Make sure we're dealing with a directory.
64+
if (! dir.isDirectory()) {
65+
return null;
66+
}
67+
68+
try {
69+
70+
// Scan the android.txt file.
71+
File propfile = new File(dir, "android.txt");
72+
FileInputStream in = new FileInputStream(propfile);
73+
Properties p = new Properties();
74+
p.load(in);
75+
in.close();
76+
77+
// Get the various properties.
78+
String title = decode(p.getProperty("title", "Untitled"));
79+
String author = decode(p.getProperty("author", ""));
80+
boolean landscape = p.getProperty("orientation", "portrait").equals("landscape");
81+
82+
// Create the project object.
83+
Project rv = new Project();
84+
rv.title = title;
85+
rv.author = author;
86+
rv.icon = BitmapFactory.decodeFile(new File(dir, "icon.png").getAbsolutePath());
87+
rv.landscape = landscape;
88+
rv.dir = dir.getAbsolutePath();
89+
90+
return rv;
91+
92+
} catch (Exception e) {
93+
Log.i("Project", "Couldn't open android.txt", e);
94+
}
95+
96+
return null;
97+
98+
}
99+
}

0 commit comments

Comments
 (0)
0