Skip to content

Commit d01413a

Browse files
committed
update android package for sdl2 bootstrap
1 parent 5ed46a7 commit d01413a

File tree

8 files changed

+186
-109
lines changed

8 files changed

+186
-109
lines changed
Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
21
from pythonforandroid.recipe import CythonRecipe, IncludedFilesBehaviour
3-
import sh
4-
from os.path import exists, join
2+
from pythonforandroid.util import current_directory
3+
from pythonforandroid.patching import will_build
4+
from pythonforandroid import logger
5+
6+
from os.path import join
57

68

79
class AndroidRecipe(IncludedFilesBehaviour, CythonRecipe):
@@ -11,8 +13,63 @@ class AndroidRecipe(IncludedFilesBehaviour, CythonRecipe):
1113

1214
src_filename = 'src'
1315

14-
depends = ['pygame']
15-
conflicts = ['sdl2']
16+
depends = [('pygame', 'sdl2'), ('python2', 'python3')]
17+
18+
config_env = {}
19+
20+
def get_recipe_env(self, arch):
21+
env = super(AndroidRecipe, self).get_recipe_env(arch)
22+
env.update(self.config_env)
23+
return env
24+
25+
def prebuild_arch(self, arch):
26+
super(AndroidRecipe, self).prebuild_arch(arch)
27+
28+
tpxi = 'DEF {} = {}\n'
29+
th = '#define {} {}\n'
30+
tpy = '{} = {}\n'
31+
32+
bootstrap_name = self.ctx.bootstrap.name
33+
is_sdl2 = bootstrap_name in ('sdl2', 'sdl2python3')
34+
is_pygame = bootstrap_name in ('pygame',)
35+
36+
if is_sdl2:
37+
bootstrap = 'sdl2'
38+
java_ns = 'org.kivy.android'
39+
jni_ns = 'org/kivy/android'
40+
elif is_pygame:
41+
bootstrap = 'pygame'
42+
java_ns = 'org.renpy.android'
43+
jni_ns = 'org/renpy/android'
44+
else:
45+
logger.error('unsupported bootstrap for android recipe: {}'.format(bootstrap_name))
46+
exit(1)
47+
48+
config = {
49+
'BOOTSTRAP': bootstrap,
50+
'IS_SDL2': int(is_sdl2),
51+
'IS_PYGAME': int(is_pygame),
52+
'PY2': int(will_build('python2')(self)),
53+
'JAVA_NAMESPACE': java_ns,
54+
'JNI_NAMESPACE': jni_ns,
55+
}
56+
57+
with current_directory(self.get_build_dir(arch.arch)):
58+
with open(join('android', 'config.pxi'), 'w') as fpxi:
59+
with open(join('android', 'config.h'), 'w') as fh:
60+
with open(join('android', 'config.py'), 'w') as fpy:
61+
for key, value in config.items():
62+
fpxi.write(tpxi.format(key, repr(value)))
63+
fpy.write(tpy.format(key, repr(value)))
64+
fh.write(th.format(key, value if isinstance(value, int)
65+
else '"{}"'.format(value)))
66+
self.config_env[key] = str(value)
67+
68+
if is_sdl2:
69+
fh.write('JNIEnv *SDL_AndroidGetJNIEnv(void);\n')
70+
fh.write('#define SDL_ANDROID_GetJNIEnv SDL_AndroidGetJNIEnv\n')
71+
elif is_pygame:
72+
fh.write('JNIEnv *SDL_ANDROID_GetJNIEnv(void);\n')
1673

1774

1875
recipe = AndroidRecipe()

pythonforandroid/recipes/android/src/android/_android.pyx

Lines changed: 75 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
# Android-specific python services.
22

3-
cdef extern int SDL_ANDROID_CheckPause()
4-
cdef extern void SDL_ANDROID_WaitForResume() nogil
5-
cdef extern void SDL_ANDROID_MapKey(int scancode, int keysym)
6-
7-
def check_pause():
8-
return SDL_ANDROID_CheckPause()
9-
10-
def wait_for_resume():
11-
android_accelerometer_enable(False)
12-
SDL_ANDROID_WaitForResume()
13-
android_accelerometer_enable(accelerometer_enabled)
14-
15-
def map_key(scancode, keysym):
16-
SDL_ANDROID_MapKey(scancode, keysym)
3+
include "config.pxi"
4+
5+
IF BOOTSTRAP == 'pygame':
6+
cdef extern int SDL_ANDROID_CheckPause()
7+
cdef extern void SDL_ANDROID_WaitForResume() nogil
8+
cdef extern void SDL_ANDROID_MapKey(int scancode, int keysym)
9+
10+
def check_pause():
11+
return SDL_ANDROID_CheckPause()
12+
13+
def wait_for_resume():
14+
android_accelerometer_enable(False)
15+
SDL_ANDROID_WaitForResume()
16+
android_accelerometer_enable(accelerometer_enabled)
17+
18+
def map_key(scancode, keysym):
19+
SDL_ANDROID_MapKey(scancode, keysym)
1720

1821
# Android keycodes.
1922
KEYCODE_UNKNOWN = 0
@@ -109,12 +112,6 @@ KEYCODE_MEDIA_REWIND = 89
109112
KEYCODE_MEDIA_FAST_FORWARD = 90
110113
KEYCODE_MUTE = 91
111114

112-
# Activate input - required to receive input events.
113-
cdef extern void android_activate_input()
114-
115-
def init():
116-
android_activate_input()
117-
118115
# Vibration support.
119116
cdef extern void android_vibrate(double)
120117

@@ -178,7 +175,7 @@ api_version = autoclass('android.os.Build$VERSION').SDK_INT
178175
version_codes = autoclass('android.os.Build$VERSION_CODES')
179176

180177

181-
python_act = autoclass('org.renpy.android.PythonActivity')
178+
python_act = autoclass(JAVA_NAMESPACE + '.PythonActivity')
182179
Rect = autoclass('android.graphics.Rect')
183180
mActivity = python_act.mActivity
184181
if mActivity:
@@ -194,7 +191,10 @@ if mActivity:
194191
self.height = mActivity.getWindowManager().getDefaultDisplay().getHeight() - (rctx.bottom - rctx.top)
195192

196193
ll = LayoutListener()
197-
python_act.mView.getViewTreeObserver().addOnGlobalLayoutListener(ll)
194+
IF BOOTSTRAP == 'sdl2':
195+
python_act.getLayout().getViewTreeObserver().addOnGlobalLayoutListener(ll)
196+
ELSE:
197+
python_act.mView.getViewTreeObserver().addOnGlobalLayoutListener(ll)
198198

199199
def get_keyboard_height():
200200
return ll.height
@@ -276,52 +276,59 @@ def get_buildinfo():
276276
binfo.VERSION_RELEASE = BUILD_VERSION_RELEASE
277277
return binfo
278278

279-
# Action send
280-
cdef extern void android_action_send(char*, char*, char*, char*, char*)
281-
def action_send(mimetype, filename=None, subject=None, text=None,
282-
chooser_title=None):
283-
cdef char *j_mimetype = <bytes>mimetype
284-
cdef char *j_filename = NULL
285-
cdef char *j_subject = NULL
286-
cdef char *j_text = NULL
287-
cdef char *j_chooser_title = NULL
288-
if filename is not None:
289-
j_filename = <bytes>filename
290-
if subject is not None:
291-
j_subject = <bytes>subject
292-
if text is not None:
293-
j_text = <bytes>text
294-
if chooser_title is not None:
295-
j_chooser_title = <bytes>chooser_title
296-
android_action_send(j_mimetype, j_filename, j_subject, j_text,
297-
j_chooser_title)
298-
299-
cdef extern int android_checkstop()
300-
cdef extern void android_ackstop()
301-
302-
def check_stop():
303-
return android_checkstop()
304-
305-
def ack_stop():
306-
android_ackstop()
307-
308-
# -------------------------------------------------------------------
309-
# URL Opening.
310-
cdef extern void android_open_url(char *url)
311-
def open_url(url):
312-
android_open_url(url)
313-
314-
# Web browser support.
315-
class AndroidBrowser(object):
316-
def open(self, url, new=0, autoraise=True):
317-
open_url(url)
318-
def open_new(self, url):
319-
open_url(url)
320-
def open_new_tab(self, url):
321-
open_url(url)
322-
323-
import webbrowser
324-
webbrowser.register('android', AndroidBrowser, None, -1)
279+
IF IS_PYGAME:
280+
# Activate input - required to receive input events.
281+
cdef extern void android_activate_input()
282+
283+
def init():
284+
android_activate_input()
285+
286+
# Action send
287+
cdef extern void android_action_send(char*, char*, char*, char*, char*)
288+
def action_send(mimetype, filename=None, subject=None, text=None,
289+
chooser_title=None):
290+
cdef char *j_mimetype = <bytes>mimetype
291+
cdef char *j_filename = NULL
292+
cdef char *j_subject = NULL
293+
cdef char *j_text = NULL
294+
cdef char *j_chooser_title = NULL
295+
if filename is not None:
296+
j_filename = <bytes>filename
297+
if subject is not None:
298+
j_subject = <bytes>subject
299+
if text is not None:
300+
j_text = <bytes>text
301+
if chooser_title is not None:
302+
j_chooser_title = <bytes>chooser_title
303+
android_action_send(j_mimetype, j_filename, j_subject, j_text,
304+
j_chooser_title)
305+
306+
cdef extern int android_checkstop()
307+
cdef extern void android_ackstop()
308+
309+
def check_stop():
310+
return android_checkstop()
311+
312+
def ack_stop():
313+
android_ackstop()
314+
315+
# -------------------------------------------------------------------
316+
# URL Opening.
317+
cdef extern void android_open_url(char *url)
318+
def open_url(url):
319+
android_open_url(url)
320+
321+
# Web browser support.
322+
class AndroidBrowser(object):
323+
def open(self, url, new=0, autoraise=True):
324+
open_url(url)
325+
def open_new(self, url):
326+
open_url(url)
327+
def open_new_tab(self, url):
328+
open_url(url)
329+
330+
import webbrowser
331+
webbrowser.register('android', AndroidBrowser, None, -1)
325332

326333
cdef extern void android_start_service(char *, char *, char *)
327334
def start_service(title=None, description=None, arg=None):

pythonforandroid/recipes/android/src/android/_android_billing_jni.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <string.h>
55
#include <stdlib.h>
66

7-
JNIEnv *SDL_ANDROID_GetJNIEnv(void);
7+
#include "config.h"
88

99
#define aassert(x) { if (!x) { __android_log_print(ANDROID_LOG_ERROR, "android_jni", "Assertion failed. %s:%d", __FILE__, __LINE__); abort(); }}
1010
#define PUSH_FRAME { (*env)->PushLocalFrame(env, 16); }
@@ -18,7 +18,7 @@ void android_billing_service_start() {
1818
if (env == NULL) {
1919
env = SDL_ANDROID_GetJNIEnv();
2020
aassert(env);
21-
cls = (*env)->FindClass(env, "org/renpy/android/PythonActivity");
21+
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
2222
aassert(cls);
2323
mid = (*env)->GetStaticMethodID(env, cls, "billingServiceStart", "()V");
2424
aassert(mid);
@@ -37,7 +37,7 @@ void android_billing_service_stop() {
3737
if (env == NULL) {
3838
env = SDL_ANDROID_GetJNIEnv();
3939
aassert(env);
40-
cls = (*env)->FindClass(env, "org/renpy/android/PythonActivity");
40+
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
4141
aassert(cls);
4242
mid = (*env)->GetStaticMethodID(env, cls, "billingServiceStop", "()V");
4343
aassert(mid);
@@ -56,7 +56,7 @@ void android_billing_buy(char *sku) {
5656
if (env == NULL) {
5757
env = SDL_ANDROID_GetJNIEnv();
5858
aassert(env);
59-
cls = (*env)->FindClass(env, "org/renpy/android/PythonActivity");
59+
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
6060
aassert(cls);
6161
mid = (*env)->GetStaticMethodID(env, cls, "billingBuy", "(Ljava/lang/String;)V");
6262
aassert(mid);
@@ -81,7 +81,7 @@ char *android_billing_get_purchased_items() {
8181
if (env == NULL) {
8282
env = SDL_ANDROID_GetJNIEnv();
8383
aassert(env);
84-
cls = (*env)->FindClass(env, "org/renpy/android/PythonActivity");
84+
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
8585
aassert(cls);
8686
mid = (*env)->GetStaticMethodID(env, cls, "billingGetPurchasedItems", "()Ljava/lang/String;");
8787
aassert(mid);
@@ -104,7 +104,7 @@ char *android_billing_get_pending_message() {
104104
if (env == NULL) {
105105
env = SDL_ANDROID_GetJNIEnv();
106106
aassert(env);
107-
cls = (*env)->FindClass(env, "org/renpy/android/PythonActivity");
107+
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
108108
aassert(cls);
109109
mid = (*env)->GetStaticMethodID(env, cls, "billingGetPendingMessage", "()Ljava/lang/String;");
110110
aassert(mid);

pythonforandroid/recipes/android/src/android/_android_jni.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <string.h>
55
#include <stdlib.h>
66

7-
JNIEnv *SDL_ANDROID_GetJNIEnv(void);
7+
#include "config.h"
88

99
#define aassert(x) { if (!x) { __android_log_print(ANDROID_LOG_ERROR, "android_jni", "Assertion failed. %s:%d", __FILE__, __LINE__); abort(); }}
1010
#define PUSH_FRAME { (*env)->PushLocalFrame(env, 16); }
@@ -201,6 +201,7 @@ void android_get_buildinfo() {
201201
}
202202
}
203203

204+
#if IS_PYGAME
204205
void android_activate_input(void) {
205206
static JNIEnv *env = NULL;
206207
static jclass *cls = NULL;
@@ -310,6 +311,7 @@ void android_open_url(char *url) {
310311

311312
POP_FRAME;
312313
}
314+
#endif // IS_PYGAME
313315

314316
void android_start_service(char *title, char *description, char *arg) {
315317
static JNIEnv *env = NULL;
@@ -319,7 +321,7 @@ void android_start_service(char *title, char *description, char *arg) {
319321
if (env == NULL) {
320322
env = SDL_ANDROID_GetJNIEnv();
321323
aassert(env);
322-
cls = (*env)->FindClass(env, "org/renpy/android/PythonActivity");
324+
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
323325
aassert(cls);
324326
mid = (*env)->GetStaticMethodID(env, cls, "start_service",
325327
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
@@ -346,7 +348,7 @@ void android_stop_service() {
346348

347349
if (env == NULL) {
348350
env = SDL_ANDROID_GetJNIEnv();
349-
cls = (*env)->FindClass(env, "org/renpy/android/PythonActivity");
351+
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
350352
aassert(cls);
351353
mid = (*env)->GetStaticMethodID(env, cls, "stop_service", "()V");
352354
aassert(mid);

pythonforandroid/recipes/android/src/android/activity.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from jnius import PythonJavaClass, java_method, autoclass, cast
2+
from android.config import JAVA_NAMESPACE, JNI_NAMESPACE
23

3-
_activity = autoclass('org.renpy.android.PythonActivity').mActivity
4+
_activity = autoclass(JAVA_NAMESPACE + '.PythonActivity').mActivity
45

56
_callbacks = {
67
'on_new_intent': [],
78
'on_activity_result': [] }
89

910
class NewIntentListener(PythonJavaClass):
10-
__javainterfaces__ = ['org/renpy/android/PythonActivity$NewIntentListener']
11+
__javainterfaces__ = [JNI_NAMESPACE + '/PythonActivity$NewIntentListener']
1112
__javacontext__ = 'app'
1213

1314
def __init__(self, callback, **kwargs):
@@ -20,7 +21,7 @@ def onNewIntent(self, intent):
2021

2122

2223
class ActivityResultListener(PythonJavaClass):
23-
__javainterfaces__ = ['org/renpy/android/PythonActivity$ActivityResultListener']
24+
__javainterfaces__ = [JNI_NAMESPACE + '/PythonActivity$ActivityResultListener']
2425
__javacontext__ = 'app'
2526

2627
def __init__(self, callback):

0 commit comments

Comments
 (0)