diff --git a/pythonforandroid/bootstraps/sdl2/build/build.py b/pythonforandroid/bootstraps/sdl2/build/build.py index 0262bf5138..3a6ff45199 100755 --- a/pythonforandroid/bootstraps/sdl2/build/build.py +++ b/pythonforandroid/bootstraps/sdl2/build/build.py @@ -3,6 +3,7 @@ from __future__ import print_function from os.path import dirname, join, isfile, realpath, relpath, split, exists +from os import makedirs import os import tarfile import time @@ -59,6 +60,10 @@ def render(template, dest, **kwargs): keyword arguments as template parameters. ''' + dest_dir = dirname(dest) + if dest_dir and not exists(dest_dir): + makedirs(dest_dir) + template = environment.get_template(template) text = template.render(**kwargs) @@ -95,7 +100,7 @@ def listfiles(d): if isfile(fn): yield fn else: - subdirlist.append(os.path.join(basedir, item)) + subdirlist.append(join(basedir, item)) for subdir in subdirlist: for fn in listfiles(subdir): yield fn @@ -112,7 +117,7 @@ def make_python_zip(): print('No compiled python is present to zip, skipping.') print('this should only be the case if you are using the CrystaX python') return - + global python_files d = realpath(join('private', 'lib', 'python2.7')) @@ -214,10 +219,10 @@ def make_package(args): # sys.exit(-1) # Delete the old assets. - if os.path.exists('assets/public.mp3'): + if exists('assets/public.mp3'): os.unlink('assets/public.mp3') - if os.path.exists('assets/private.mp3'): + if exists('assets/private.mp3'): os.unlink('assets/private.mp3') # In order to speedup import and initial depack, @@ -262,7 +267,7 @@ def make_package(args): # If extra Java jars were requested, copy them into the libs directory if args.add_jar: for jarname in args.add_jar: - if not os.path.exists(jarname): + if not exists(jarname): print('Requested jar does not exist: {}'.format(jarname)) sys.exit(-1) shutil.copy(jarname, 'libs') @@ -283,14 +288,27 @@ def make_package(args): service = False service_main = join(realpath(args.private), 'service', 'main.py') - if os.path.exists(service_main) or os.path.exists(service_main + 'o'): + if exists(service_main) or exists(service_main + 'o'): service = True + service_names = [] + for entrypoint in args.services: + name, entrypoint = entrypoint.split(":", 1) + service_names.append(name) + render( + 'Service.tmpl.java', + 'src/{}/Service{}.java'.format(args.package.replace(".", "/"), name.capitalize()), + name=name, + entrypoint=entrypoint, + args=args + ) + render( 'AndroidManifest.tmpl.xml', 'AndroidManifest.xml', args=args, service=service, + service_names=service_names, ) render( @@ -390,6 +408,8 @@ def parse_args(args=None): 'directory')) ap.add_argument('--with-billing', dest='billing_pubkey', help='If set, the billing service will be added (not implemented)') + ap.add_argument('--service', dest='services', action='append', + help='Declare a new service entrypoint: NAME:PATH_TO_PY') if args is None: args = sys.argv[1:] diff --git a/pythonforandroid/bootstraps/sdl2/build/jni/src/start.c b/pythonforandroid/bootstraps/sdl2/build/jni/src/start.c index 19db3f58c4..7b40cb73be 100644 --- a/pythonforandroid/bootstraps/sdl2/build/jni/src/start.c +++ b/pythonforandroid/bootstraps/sdl2/build/jni/src/start.c @@ -2,7 +2,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" #ifndef Py_PYTHON_H - #error Python headers needed to compile C extensions, please install development version of Python. +#error Python headers needed to compile C extensions, please install development version of Python. #else #include @@ -12,83 +12,42 @@ #include #include #include - #include #include "SDL.h" - -/* #include */ - #include "android/log.h" - -/* #include "jniwrapperstuff.h" */ - - -/* AND: I don't know why this include is needed! */ #include "SDL_opengles2.h" -#define LOG(x) __android_log_write(ANDROID_LOG_INFO, "python", (x)) +#define ENTRYPOINT_MAXLEN 128 +#define LOG(n, x) __android_log_write(ANDROID_LOG_INFO, (n), (x)) +#define LOGP(x) LOG("python", (x)) static PyObject *androidembed_log(PyObject *self, PyObject *args) { - char *logstr = NULL; - if (!PyArg_ParseTuple(args, "s", &logstr)) { - return NULL; - } - LOG(logstr); - Py_RETURN_NONE; + char *logstr = NULL; + if (!PyArg_ParseTuple(args, "s", &logstr)) { + return NULL; + } + LOG(getenv("PYTHON_NAME"), logstr); + Py_RETURN_NONE; } static PyMethodDef AndroidEmbedMethods[] = { - {"log", androidembed_log, METH_VARARGS, - "Log on android platform"}, - {NULL, NULL, 0, NULL} -}; - + {"log", androidembed_log, METH_VARARGS, "Log on android platform"}, + {NULL, NULL, 0, NULL}}; #if PY_MAJOR_VERSION >= 3 - static struct PyModuleDef androidembed = - { - PyModuleDef_HEAD_INIT, - "androidembed", - "", - -1, - AndroidEmbedMethods - }; - - PyMODINIT_FUNC initandroidembed(void) { - return PyModule_Create(&androidembed); - /* (void) Py_InitModule("androidembed", AndroidEmbedMethods); */ - } +static struct PyModuleDef androidembed = {PyModuleDef_HEAD_INIT, "androidembed", + "", -1, AndroidEmbedMethods}; + +PyMODINIT_FUNC initandroidembed(void) { + return PyModule_Create(&androidembed); +} #else - PyMODINIT_FUNC initandroidembed(void) { - (void) Py_InitModule("androidembed", AndroidEmbedMethods); - } +PyMODINIT_FUNC initandroidembed(void) { + (void)Py_InitModule("androidembed", AndroidEmbedMethods); +} #endif -/* int dir_exists(char* filename) */ -/* /\* Function from http://stackoverflow.com/questions/12510874/how-can-i-check-if-a-directory-exists-on-linux-in-c# *\/ */ -/* { */ -/* if (0 != access(filename, F_OK)) { */ -/* if (ENOENT == errno) { */ -/* return 0; */ -/* } */ -/* if (ENOTDIR == errno) { */ -/* return 0; */ -/* } */ -/* return 1; */ -/* } */ -/* } */ - -/* int dir_exists(char* filename) { */ -/* DIR *dip; */ -/* if (dip = opendir(filename)) { */ -/* closedir(filename); */ -/* return 1; */ -/* } */ -/* return 0; */ -/* } */ - - int dir_exists(char *filename) { struct stat st; if (stat(filename, &st) == 0) { @@ -98,252 +57,263 @@ int dir_exists(char *filename) { return 0; } - -int file_exists(const char * filename) -{ - FILE *file; - if (file = fopen(filename, "r")) { - fclose(file); - return 1; - } - return 0; +int file_exists(const char *filename) { + FILE *file; + if (file = fopen(filename, "r")) { + fclose(file); + return 1; + } + return 0; } /* int main(int argc, char **argv) { */ int main(int argc, char *argv[]) { - char *env_argument = NULL; - int ret = 0; - FILE *fd; - - /* AND: Several filepaths are hardcoded here, these must be made - configurable */ - /* AND: P4A uses env vars...not sure what's best */ - LOG("Initialize Python for Android"); - /* env_argument = "/data/data/org.kivy.android/files"; */ - env_argument = getenv("ANDROID_ARGUMENT"); - setenv("ANDROID_APP_PATH", env_argument, 1); - - /* setenv("ANDROID_ARGUMENT", env_argument, 1); */ - /* setenv("ANDROID_PRIVATE", env_argument, 1); */ - /* setenv("ANDROID_APP_PATH", env_argument, 1); */ - /* setenv("PYTHONHOME", env_argument, 1); */ - /* setenv("PYTHONPATH", "/data/data/org.kivy.android/files:/data/data/org.kivy.android/files/lib", 1); */ - - /* LOG("AND: Set env vars"); */ - /* LOG(argv[0]); */ - /* LOG("AND: That was argv 0"); */ - //setenv("PYTHONVERBOSE", "2", 1); - - LOG("Changing directory to the one provided by ANDROID_ARGUMENT"); - LOG(env_argument); - chdir(env_argument); - - Py_SetProgramName(L"android_python"); + char *env_argument = NULL; + char *env_entrypoint = NULL; + char *env_logname = NULL; + char entrypoint[ENTRYPOINT_MAXLEN]; + int ret = 0; + FILE *fd; + + /* AND: Several filepaths are hardcoded here, these must be made + configurable */ + /* AND: P4A uses env vars...not sure what's best */ + LOGP("Initialize Python for Android"); + env_argument = getenv("ANDROID_ARGUMENT"); + setenv("ANDROID_APP_PATH", env_argument, 1); + env_entrypoint = getenv("ANDROID_ENTRYPOINT"); + env_logname = getenv("PYTHON_NAME"); + + if (env_logname == NULL) { + env_logname = "python"; + setenv("PYTHON_NAME", "python", 1); + } + + LOGP("Changing directory to the one provided by ANDROID_ARGUMENT"); + LOGP(env_argument); + chdir(env_argument); + + Py_SetProgramName(L"android_python"); #if PY_MAJOR_VERSION >= 3 - /* our logging module for android - */ - PyImport_AppendInittab("androidembed", initandroidembed); + /* our logging module for android + */ + PyImport_AppendInittab("androidembed", initandroidembed); #endif - - LOG("Preparing to initialize python"); - - if (dir_exists("crystax_python/")) { - LOG("crystax_python exists"); - char paths[256]; - snprintf(paths, 256, "%s/crystax_python/stdlib.zip:%s/crystax_python/modules", env_argument, env_argument); - /* snprintf(paths, 256, "%s/stdlib.zip:%s/modules", env_argument, env_argument); */ - LOG("calculated paths to be..."); - LOG(paths); - + + LOGP("Preparing to initialize python"); + + if (dir_exists("crystax_python/")) { + LOGP("crystax_python exists"); + char paths[256]; + snprintf(paths, 256, + "%s/crystax_python/stdlib.zip:%s/crystax_python/modules", + env_argument, env_argument); + /* snprintf(paths, 256, "%s/stdlib.zip:%s/modules", env_argument, + * env_argument); */ + LOGP("calculated paths to be..."); + LOGP(paths); + #if PY_MAJOR_VERSION >= 3 - wchar_t* wchar_paths = Py_DecodeLocale(paths, NULL); - Py_SetPath(wchar_paths); + wchar_t *wchar_paths = Py_DecodeLocale(paths, NULL); + Py_SetPath(wchar_paths); #else - char* wchar_paths = paths; - LOG("Can't Py_SetPath in python2, so crystax python2 doesn't work yet"); - exit(1); + char *wchar_paths = paths; + LOGP("Can't Py_SetPath in python2, so crystax python2 doesn't work yet"); + exit(1); #endif - - LOG("set wchar paths..."); - } else { LOG("crystax_python does not exist");} - Py_Initialize(); - + LOGP("set wchar paths..."); + } else { + LOGP("crystax_python does not exist"); + } + + Py_Initialize(); + #if PY_MAJOR_VERSION < 3 - PySys_SetArgv(argc, argv); + PySys_SetArgv(argc, argv); #endif - - LOG("Initialized python"); - /* ensure threads will work. - */ - LOG("AND: Init threads"); - PyEval_InitThreads(); - + LOGP("Initialized python"); + + /* ensure threads will work. + */ + LOGP("AND: Init threads"); + PyEval_InitThreads(); #if PY_MAJOR_VERSION < 3 - initandroidembed(); + initandroidembed(); #endif - PyRun_SimpleString("import androidembed\nandroidembed.log('testing python print redirection')"); - - /* inject our bootstrap code to redirect python stdin/stdout - * replace sys.path with our path - */ - PyRun_SimpleString("import sys, posix\n"); - if (dir_exists("lib")) { - /* If we built our own python, set up the paths correctly */ - LOG("Setting up python from ANDROID_PRIVATE"); - PyRun_SimpleString( - "private = posix.environ['ANDROID_PRIVATE']\n" \ - "argument = posix.environ['ANDROID_ARGUMENT']\n" \ - "sys.path[:] = [ \n" \ - " private + '/lib/python27.zip', \n" \ - " private + '/lib/python2.7/', \n" \ - " private + '/lib/python2.7/lib-dynload/', \n" \ - " private + '/lib/python2.7/site-packages/', \n" \ - " argument ]\n"); - } - - if (dir_exists("crystax_python")) { - char add_site_packages_dir[256]; - snprintf(add_site_packages_dir, 256, "sys.path.append('%s/crystax_python/site-packages')", - env_argument); - - PyRun_SimpleString( - "import sys\n" \ - "sys.argv = ['notaninterpreterreally']\n" \ - "from os.path import realpath, join, dirname"); - PyRun_SimpleString(add_site_packages_dir); - /* "sys.path.append(join(dirname(realpath(__file__)), 'site-packages'))") */ - PyRun_SimpleString("sys.path = ['.'] + sys.path"); - } - - PyRun_SimpleString( - "class LogFile(object):\n" \ - " def __init__(self):\n" \ - " self.buffer = ''\n" \ - " def write(self, s):\n" \ - " s = self.buffer + s\n" \ - " lines = s.split(\"\\n\")\n" \ - " for l in lines[:-1]:\n" \ - " androidembed.log(l)\n" \ - " self.buffer = lines[-1]\n" \ - " def flush(self):\n" \ - " return\n" \ - "sys.stdout = sys.stderr = LogFile()\n" \ - "print('Android path', sys.path)\n" \ - "import os\n" \ - "print('os.environ is', os.environ)\n" \ - "print('Android kivy bootstrap done. __name__ is', __name__)"); + PyRun_SimpleString("import androidembed\nandroidembed.log('testing python " + "print redirection')"); + + /* inject our bootstrap code to redirect python stdin/stdout + * replace sys.path with our path + */ + PyRun_SimpleString("import sys, posix\n"); + if (dir_exists("lib")) { + /* If we built our own python, set up the paths correctly */ + LOGP("Setting up python from ANDROID_PRIVATE"); + PyRun_SimpleString("private = posix.environ['ANDROID_PRIVATE']\n" + "argument = posix.environ['ANDROID_ARGUMENT']\n" + "sys.path[:] = [ \n" + " private + '/lib/python27.zip', \n" + " private + '/lib/python2.7/', \n" + " private + '/lib/python2.7/lib-dynload/', \n" + " private + '/lib/python2.7/site-packages/', \n" + " argument ]\n"); + } + + if (dir_exists("crystax_python")) { + char add_site_packages_dir[256]; + snprintf(add_site_packages_dir, 256, + "sys.path.append('%s/crystax_python/site-packages')", + env_argument); + + PyRun_SimpleString("import sys\n" + "sys.argv = ['notaninterpreterreally']\n" + "from os.path import realpath, join, dirname"); + PyRun_SimpleString(add_site_packages_dir); + /* "sys.path.append(join(dirname(realpath(__file__)), 'site-packages'))") */ + PyRun_SimpleString("sys.path = ['.'] + sys.path"); + } + + PyRun_SimpleString( + "class LogFile(object):\n" + " def __init__(self):\n" + " self.buffer = ''\n" + " def write(self, s):\n" + " s = self.buffer + s\n" + " lines = s.split(\"\\n\")\n" + " for l in lines[:-1]:\n" + " androidembed.log(l)\n" + " self.buffer = lines[-1]\n" + " def flush(self):\n" + " return\n" + "sys.stdout = sys.stderr = LogFile()\n" + "print('Android path', sys.path)\n" + "import os\n" + "print('os.environ is', os.environ)\n" + "print('Android kivy bootstrap done. __name__ is', __name__)"); #if PY_MAJOR_VERSION < 3 - PyRun_SimpleString("import site; print site.getsitepackages()\n"); + PyRun_SimpleString("import site; print site.getsitepackages()\n"); #endif - /* PyRun_SimpleString( */ - /* "import sys, posix\n" \ */ - /* "private = posix.environ['ANDROID_PRIVATE']\n" \ */ - /* "argument = posix.environ['ANDROID_ARGUMENT']\n" \ */ - /* "sys.path[:] = [ \n" \ */ - /* " private + '/lib/python27.zip', \n" \ */ - /* " private + '/lib/python2.7/', \n" \ */ - /* " private + '/lib/python2.7/lib-dynload/', \n" \ */ - /* " private + '/lib/python2.7/site-packages/', \n" \ */ - /* " argument ]\n" \ */ - /* "import androidembed\n" \ */ - /* "class LogFile(object):\n" \ */ - /* " def __init__(self):\n" \ */ - /* " self.buffer = ''\n" \ */ - /* " def write(self, s):\n" \ */ - /* " s = self.buffer + s\n" \ */ - /* " lines = s.split(\"\\n\")\n" \ */ - /* " for l in lines[:-1]:\n" \ */ - /* " androidembed.log(l)\n" \ */ - /* " self.buffer = lines[-1]\n" \ */ - /* " def flush(self):\n" \ */ - /* " return\n" \ */ - /* "sys.stdout = sys.stderr = LogFile()\n" \ */ - /* "import site; print site.getsitepackages()\n"\ */ - /* "print 'Android path', sys.path\n" \ */ - /* "print 'Android kivy bootstrap done. __name__ is', __name__"); */ - - LOG("AND: Ran string"); - - /* run it ! - */ - LOG("Run user program, change dir and execute main.py"); - - /* search the initial main.py - */ - char *main_py = "main.pyo"; - if ( file_exists(main_py) == 0 ) { - if ( file_exists("main.py") ) - main_py = "main.py"; - else - main_py = NULL; - } - - if ( main_py == NULL ) { - LOG("No main.pyo / main.py found."); - return -1; - } - - fd = fopen(main_py, "r"); - if ( fd == NULL ) { - LOG("Open the main.py(o) failed"); - return -1; - } + LOGP("AND: Ran string"); - /* run python ! - */ - ret = PyRun_SimpleFile(fd, main_py); + /* run it ! + */ + LOGP("Run user program, change dir and execute entrypoint"); - if (PyErr_Occurred() != NULL) { - ret = 1; - PyErr_Print(); /* This exits with the right code if SystemExit. */ - PyObject *f = PySys_GetObject("stdout"); - if (PyFile_WriteString("\n", f)) /* python2 used Py_FlushLine, but this no longer exists */ - PyErr_Clear(); + /* Get the entrypoint, search the .pyo then .py + */ + char *dot = strrchr(env_entrypoint, '.'); + if (dot <= 0) { + LOGP("Invalid entrypoint, abort."); + return -1; + } + if (strlen(env_entrypoint) > ENTRYPOINT_MAXLEN - 2) { + LOGP("Entrypoint path is too long, try increasing ENTRYPOINT_MAXLEN."); + return -1; + } + if (!strcmp(dot, ".pyo")) { + if (!file_exists(env_entrypoint)) { + /* fallback on .py */ + strcpy(entrypoint, env_entrypoint); + entrypoint[strlen(env_entrypoint) - 1] = '\0'; + LOGP(entrypoint); + if (!file_exists(entrypoint)) { + LOGP("Entrypoint not found (.pyo, fallback on .py), abort"); + return -1; + } + } else { + strcpy(entrypoint, env_entrypoint); } + } else if (!strcmp(dot, ".py")) { + /* if .py is passed, check the pyo version first */ + strcpy(entrypoint, env_entrypoint); + entrypoint[strlen(env_entrypoint) + 1] = '\0'; + entrypoint[strlen(env_entrypoint)] = 'o'; + if (!file_exists(entrypoint)) { + /* fallback on pure python version */ + if (!file_exists(env_entrypoint)) { + LOGP("Entrypoint not found (.py), abort."); + return -1; + } + strcpy(entrypoint, env_entrypoint); + } + } else { + LOGP("Entrypoint have an invalid extension (must be .py or .pyo), abort."); + return -1; + } + // LOGP("Entrypoint is:"); + // LOGP(entrypoint); + fd = fopen(entrypoint, "r"); + if (fd == NULL) { + LOGP("Open the entrypoint failed"); + LOGP(entrypoint); + return -1; + } + + /* run python ! + */ + ret = PyRun_SimpleFile(fd, entrypoint); + + if (PyErr_Occurred() != NULL) { + ret = 1; + PyErr_Print(); /* This exits with the right code if SystemExit. */ + PyObject *f = PySys_GetObject("stdout"); + if (PyFile_WriteString( + "\n", f)) /* python2 used Py_FlushLine, but this no longer exists */ + PyErr_Clear(); + } - /* close everything - */ - Py_Finalize(); - fclose(fd); + /* close everything + */ + Py_Finalize(); + fclose(fd); - LOG("Python for android ended."); - return ret; + LOGP("Python for android ended."); + return ret; } -JNIEXPORT void JNICALL Java_org_kivy_android_PythonService_nativeStart ( JNIEnv* env, jobject thiz, - jstring j_android_private, - jstring j_android_argument, - jstring j_python_home, - jstring j_python_path, - jstring j_arg ) -{ - jboolean iscopy; - const char *android_private = (*env)->GetStringUTFChars(env, j_android_private, &iscopy); - const char *android_argument = (*env)->GetStringUTFChars(env, j_android_argument, &iscopy); - const char *python_home = (*env)->GetStringUTFChars(env, j_python_home, &iscopy); - const char *python_path = (*env)->GetStringUTFChars(env, j_python_path, &iscopy); - const char *arg = (*env)->GetStringUTFChars(env, j_arg, &iscopy); - - setenv("ANDROID_PRIVATE", android_private, 1); - setenv("ANDROID_ARGUMENT", android_argument, 1); - setenv("PYTHONOPTIMIZE", "2", 1); - setenv("PYTHONHOME", python_home, 1); - setenv("PYTHONPATH", python_path, 1); - setenv("PYTHON_SERVICE_ARGUMENT", arg, 1); - - char *argv[] = { "service" }; - /* ANDROID_ARGUMENT points to service subdir, - * so main() will run main.py from this dir - */ - main(1, argv); +JNIEXPORT void JNICALL Java_org_kivy_android_PythonService_nativeStart( + JNIEnv *env, jobject thiz, jstring j_android_private, + jstring j_android_argument, jstring j_service_entrypoint, + jstring j_python_name, jstring j_python_home, jstring j_python_path, + jstring j_arg) { + jboolean iscopy; + const char *android_private = + (*env)->GetStringUTFChars(env, j_android_private, &iscopy); + const char *android_argument = + (*env)->GetStringUTFChars(env, j_android_argument, &iscopy); + const char *service_entrypoint = + (*env)->GetStringUTFChars(env, j_service_entrypoint, &iscopy); + const char *python_name = + (*env)->GetStringUTFChars(env, j_python_name, &iscopy); + const char *python_home = + (*env)->GetStringUTFChars(env, j_python_home, &iscopy); + const char *python_path = + (*env)->GetStringUTFChars(env, j_python_path, &iscopy); + const char *arg = (*env)->GetStringUTFChars(env, j_arg, &iscopy); + + setenv("ANDROID_PRIVATE", android_private, 1); + setenv("ANDROID_ARGUMENT", android_argument, 1); + setenv("ANDROID_ENTRYPOINT", service_entrypoint, 1); + setenv("PYTHONOPTIMIZE", "2", 1); + setenv("PYTHON_NAME", python_name, 1); + setenv("PYTHONHOME", python_home, 1); + setenv("PYTHONPATH", python_path, 1); + setenv("PYTHON_SERVICE_ARGUMENT", arg, 1); + + char *argv[] = {"."}; + /* ANDROID_ARGUMENT points to service subdir, + * so main() will run main.py from this dir + */ + main(1, argv); } #endif diff --git a/pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonActivity.java index f4a5e31d84..d879e2cd71 100644 --- a/pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonActivity.java @@ -69,12 +69,10 @@ protected void onCreate(Bundle savedInstanceState) { SDLActivity.nativeSetEnv("ANDROID_PRIVATE", mFilesDirectory); SDLActivity.nativeSetEnv("ANDROID_ARGUMENT", mFilesDirectory); SDLActivity.nativeSetEnv("ANDROID_APP_PATH", mFilesDirectory); + SDLActivity.nativeSetEnv("ANDROID_ENTRYPOINT", "main.pyo"); SDLActivity.nativeSetEnv("PYTHONHOME", mFilesDirectory); SDLActivity.nativeSetEnv("PYTHONPATH", mFilesDirectory + ":" + mFilesDirectory + "/lib"); - - // nativeSetEnv("ANDROID_ARGUMENT", getFilesDir()); - try { Log.v(TAG, "Access to our meta-data..."); this.mMetaData = this.mActivity.getPackageManager().getApplicationInfo( @@ -271,7 +269,8 @@ public static void start_service(String serviceTitle, String serviceDescription, String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String filesDirectory = argument; serviceIntent.putExtra("androidPrivate", argument); - serviceIntent.putExtra("androidArgument", filesDirectory); + serviceIntent.putExtra("androidArgument", argument); + serviceIntent.putExtra("serviceEntrypoint", "service/main.pyo"); serviceIntent.putExtra("pythonHome", argument); serviceIntent.putExtra("pythonPath", argument + ":" + filesDirectory + "/lib"); serviceIntent.putExtra("serviceTitle", serviceTitle); diff --git a/pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonService.java b/pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonService.java index 3539c5e108..252c7ab650 100644 --- a/pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonService.java +++ b/pythonforandroid/bootstraps/sdl2/build/src/org/kivy/android/PythonService.java @@ -23,12 +23,18 @@ public class PythonService extends Service implements Runnable { // Python environment variables private String androidPrivate; private String androidArgument; + private String pythonName; private String pythonHome; private String pythonPath; + private String serviceEntrypoint; // Argument to pass to Python code, private String pythonServiceArgument; public static Service mService = null; + public boolean canDisplayNotification() { + return true; + } + @Override public IBinder onBind(Intent arg0) { return null; @@ -37,7 +43,6 @@ public IBinder onBind(Intent arg0) { @Override public void onCreate() { super.onCreate(); - //Hardware.context = this; } @Override @@ -49,26 +54,30 @@ public int onStartCommand(Intent intent, int flags, int startId) { Bundle extras = intent.getExtras(); androidPrivate = extras.getString("androidPrivate"); - // service code is located in service subdir - androidArgument = extras.getString("androidArgument") + "/service"; + androidArgument = extras.getString("androidArgument"); + serviceEntrypoint = extras.getString("serviceEntrypoint"); + pythonName = extras.getString("pythonName"); pythonHome = extras.getString("pythonHome"); pythonPath = extras.getString("pythonPath"); pythonServiceArgument = extras.getString("pythonServiceArgument"); - String serviceTitle = extras.getString("serviceTitle"); - String serviceDescription = extras.getString("serviceDescription"); pythonThread = new Thread(this); pythonThread.start(); - Context context = getApplicationContext(); - Notification notification = new Notification(context.getApplicationInfo().icon, - serviceTitle, - System.currentTimeMillis()); - Intent contextIntent = new Intent(context, PythonActivity.class); - PendingIntent pIntent = PendingIntent.getActivity(context, 0, contextIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - notification.setLatestEventInfo(context, serviceTitle, serviceDescription, pIntent); - startForeground(1, notification); + if (this.canDisplayNotification()) { + String serviceTitle = extras.getString("serviceTitle"); + String serviceDescription = extras.getString("serviceDescription"); + + Context context = getApplicationContext(); + Notification notification = new Notification(context.getApplicationInfo().icon, + serviceTitle, + System.currentTimeMillis()); + Intent contextIntent = new Intent(context, PythonActivity.class); + PendingIntent pIntent = PendingIntent.getActivity(context, 0, contextIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + notification.setLatestEventInfo(context, serviceTitle, serviceDescription, pIntent); + startForeground(1, notification); + } return START_NOT_STICKY; } @@ -83,15 +92,18 @@ public void onDestroy() { @Override public void run(){ PythonUtil.loadLibraries(getFilesDir()); - this.mService = this; - nativeStart(androidPrivate, androidArgument, pythonHome, pythonPath, - pythonServiceArgument); + nativeStart( + androidPrivate, androidArgument, + serviceEntrypoint, pythonName, + pythonHome, pythonPath, + pythonServiceArgument); } // Native part - public static native void nativeStart(String androidPrivate, String androidArgument, + public static native void nativeStart( + String androidPrivate, String androidArgument, + String serviceEntrypoint, String pythonName, String pythonHome, String pythonPath, String pythonServiceArgument); - } diff --git a/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml index 8e8047db35..55db1baae4 100644 --- a/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml @@ -37,11 +37,11 @@ {% if args.wakelock %} {% endif %} - + {% if args.billing_pubkey %} {% endif %} - +