Skip to content

Commit

Permalink
Merge pull request kivy#1 from kivy/master
Browse files Browse the repository at this point in the history
Update from origin master
  • Loading branch information
opacam committed Mar 6, 2016
2 parents a2e7e65 + 3f0bcc7 commit 9a30281
Show file tree
Hide file tree
Showing 36 changed files with 695 additions and 103 deletions.
9 changes: 2 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,26 +70,21 @@ linked above.

Relating to all bootstraps:
- Some recipes/components aren't stripped properly of doc etc.
- Some command line options of distribute.sh
- Biglink is essential (the p4a disable option isn't implemented)
- Downloaded file md5 and headers aren't checked

Relating to SDL2 only:
- Downloaded file md5 and headers aren't checked
- Android services are not implemented at all
- App loading screen
- Public dir installation
- Keyboard height getter
- Billing support
- Kivy Launcher build (can now be implemented as a bootstrap...maybe?)
- Several build options for build.py
- Probably some other stuff

Here are some specific things relating to changes in p4a itself since
the reference commit that the revamp is based on:

# Current status

The tool works, testing is welcomed.
python-for-android is fully ready for use. We are working towards a versioned release.

# Development notes

Expand Down
49 changes: 34 additions & 15 deletions pythonforandroid/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,22 +135,24 @@ def get_bootstrap_from_recipes(cls, recipes, ctx):
for name in cls.list_bootstraps()]
acceptable_bootstraps = []
for bs in bootstraps:
ok = True
if not bs.can_be_chosen_automatically:
ok = False
for recipe in bs.recipe_depends:
recipe = Recipe.get_recipe(recipe, ctx)
if any([conflict in recipes for conflict in recipe.conflicts]):
ok = False
break
for recipe in recipes:
recipe = Recipe.get_recipe(recipe, ctx)
if any([conflict in bs.recipe_depends
for conflict in recipe.conflicts]):
ok = False
break
if ok:
acceptable_bootstraps.append(bs)
continue
possible_dependency_lists = expand_dependencies(bs.recipe_depends)
for possible_dependencies in possible_dependency_lists:
ok = True
for recipe in possible_dependencies:
recipe = Recipe.get_recipe(recipe, ctx)
if any([conflict in recipes for conflict in recipe.conflicts]):
ok = False
break
for recipe in recipes:
recipe = Recipe.get_recipe(recipe, ctx)
if any([conflict in possible_dependencies
for conflict in recipe.conflicts]):
ok = False
break
if ok:
acceptable_bootstraps.append(bs)
info('Found {} acceptable bootstraps: {}'.format(
len(acceptable_bootstraps),
[bs.name for bs in acceptable_bootstraps]))
Expand Down Expand Up @@ -264,3 +266,20 @@ def fry_eggs(self, sitepackages):
if files:
shprint(sh.mv, '-t', sitepackages, *files)
shprint(sh.rm, '-rf', d)


def expand_dependencies(recipes):
recipe_lists = [[]]
for recipe in recipes:
if isinstance(recipe, (tuple, list)):
new_recipe_lists = []
for alternative in recipe:
for old_list in recipe_lists:
new_list = [i for i in old_list]
new_list.append(alternative)
new_recipe_lists.append(new_list)
recipe_lists = new_recipe_lists
else:
for old_list in recipe_lists:
old_list.append(recipe)
return recipe_lists
6 changes: 3 additions & 3 deletions pythonforandroid/bootstraps/sdl2/build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,8 @@ def make_package(args):
entrypoint = spec[1]
options = spec[2:]

foreground = False
if 'foreground' in options:
foreground = True
foreground = 'foreground' in options
sticky = 'sticky' in options

service_names.append(name)
render(
Expand All @@ -323,6 +322,7 @@ def make_package(args):
entrypoint=entrypoint,
args=args,
foreground=foreground,
sticky=sticky,
service_id=sid + 1,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,23 @@ public class PythonService extends Service implements Runnable {
private String serviceEntrypoint;
// Argument to pass to Python code,
private String pythonServiceArgument;
public static Service mService = null;
public static PythonService mService = null;
private Intent startIntent = null;

private boolean autoRestartService = false;

public void setAutoRestartService(boolean restart) {
autoRestartService = restart;
}

public boolean canDisplayNotification() {
return true;
}

public int startType() {
return START_NOT_STICKY;
}

@Override
public IBinder onBind(Intent arg0) {
return null;
Expand All @@ -52,6 +63,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}

startIntent = intent;
Bundle extras = intent.getExtras();
androidPrivate = extras.getString("androidPrivate");
androidArgument = extras.getString("androidArgument");
Expand All @@ -64,31 +76,35 @@ public int onStartCommand(Intent intent, int flags, int startId) {
pythonThread = new Thread(this);
pythonThread.start();

doStartForeground(extras);
if (canDisplayNotification()) {
doStartForeground(extras);
}

return START_NOT_STICKY;
return startType();
}

protected void doStartForeground(Bundle extras) {
if (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);
}
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);
}

@Override
public void onDestroy() {
super.onDestroy();
pythonThread = null;
if (autoRestartService && startIntent != null) {
Log.v("python service", "service restart requested");
startService(startIntent);
}
Process.killProcess(Process.myPid());
}

Expand All @@ -101,6 +117,7 @@ public void run(){
serviceEntrypoint, pythonName,
pythonHome, pythonPath,
pythonServiceArgument);
stopSelf();
}

// Native part
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,29 @@ protected static String[] getLibraries() {
"SDL2_image",
"SDL2_mixer",
"SDL2_ttf",
"python2.7",
"python3.5m",
"main"
};
}

public static void loadLibraries(File filesDir) {

String filesDirPath = filesDir.getAbsolutePath();
boolean skippedPython = false;

for (String lib : getLibraries()) {
System.loadLibrary(lib);
try {
System.loadLibrary(lib);
} catch(UnsatisfiedLinkError e) {
if (lib.startsWith("python") && !skippedPython) {
skippedPython = true;
continue;
}
throw e;
}
}

try {
System.loadLibrary("python2.7");
} catch(UnsatisfiedLinkError e) {
Log.v(TAG, "Failed to load libpython2.7");
}

try {
System.loadLibrary("python3.5m");
} catch(UnsatisfiedLinkError e) {
Log.v(TAG, "Failed to load libpython3.5m");
}

try {
System.load(filesDirPath + "/lib/python2.7/lib-dynload/_io.so");
System.load(filesDirPath + "/lib/python2.7/lib-dynload/unicodedata.so");
Expand Down
14 changes: 14 additions & 0 deletions pythonforandroid/bootstraps/sdl2/build/templates/Service.tmpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@


public class Service{{ name|capitalize }} extends PythonService {
{% if sticky %}
@Override
public int startType() {
return START_STICKY;
}
{% endif %}

{% if not foreground %}
@Override
public boolean canDisplayNotification() {
return false;
}
{% endif %}

@Override
protected void doStartForeground(Bundle extras) {
Context context = getApplicationContext();
Expand Down
11 changes: 10 additions & 1 deletion pythonforandroid/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,13 @@ def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
android_api = int(android_api)
self.android_api = android_api

if self.android_api >= 21 and self.archs[0].arch == 'armeabi':
error('Asked to build for armeabi architecture with API '
'{}, but API 21 or greater does not support armeabi'.format(
self.android_api))
error('You probably want to build with --arch=armeabi-v7a instead')
exit(1)

android = sh.Command(join(sdk_dir, 'tools', 'android'))
targets = android('list').stdout.decode('utf-8').split('\n')
apis = [s for s in targets if re.match(r'^ *API level: ', s)]
Expand Down Expand Up @@ -330,7 +337,9 @@ def prepare_build_environment(self, user_sdk_dir, user_ndk_dir,
if cython:
self.cython = cython
break
self.cython = 'cython'
else:
error('No cython binary found. Exiting.')
exit(1)
if not self.cython:
ok = False
warning("Missing requirement: cython is not installed")
Expand Down
7 changes: 5 additions & 2 deletions pythonforandroid/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ def _add(self, graph, dependent, dependency):

def conflicts(self, conflict):
graphs = self.graphs
initial_num = len(graphs)
for i in range(len(graphs)):
graph = graphs[len(graphs) - 1 - i]
graph = graphs[initial_num - 1 - i]
if conflict in graph:
graphs.pop(len(graphs) - 1 - i)
graphs.pop(initial_num - 1 - i)
return len(graphs) == 0

def remove_remaining_conflicts(self, ctx):
Expand Down Expand Up @@ -227,6 +228,8 @@ def get_recipe_order_and_bootstrap(ctx, names, bs=None):
recipe_loaded.append(name)
graph.remove_remaining_conflicts(ctx)
build_order = list(graph.find_order(0))
build_order, python_modules, bs = get_recipe_order_and_bootstrap(
ctx, build_order + python_modules, bs)
return build_order, python_modules, bs

# Do a final check that the new bs doesn't pull in any conflicts
8 changes: 5 additions & 3 deletions pythonforandroid/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
stdout = codecs.getwriter('utf8')(stdout)
stderr = codecs.getwriter('utf8')(stderr)

if six.PY2:
unistr = unicode
else:
unistr = str

# monkey patch to show full output
sh.ErrorReturnCode.truncate_cap = 999999

Expand Down Expand Up @@ -216,6 +221,3 @@ def printtail(out, name, forecolor, tail_n=0,
raise

return output


from pythonforandroid.util import unistr
9 changes: 6 additions & 3 deletions pythonforandroid/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,9 +580,12 @@ def has_libs(self, arch, *libs):

@classmethod
def recipe_dirs(cls, ctx):
return [ctx.local_recipes,
join(ctx.storage_dir, 'recipes'),
join(ctx.root_dir, "recipes")]
recipe_dirs = []
if ctx.local_recipes is not None:
recipe_dirs.append(ctx.local_recipes)
recipe_dirs.extend([join(ctx.storage_dir, 'recipes'),
join(ctx.root_dir, "recipes")])
return recipe_dirs

@classmethod
def list_recipes(cls, ctx):
Expand Down
Loading

0 comments on commit 9a30281

Please sign in to comment.