Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android library #2092

Merged
merged 3 commits into from
Apr 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions pythonforandroid/bdistapk.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ def argv_contains(t):
return False


class BdistAPK(Command):
description = 'Create an APK with python-for-android'
class Bdist(Command):

user_options = []
package_type = None

def initialize_options(self):
for option in self.user_options:
setattr(self, option[0].strip('=').replace('-', '_'), None)

option_dict = self.distribution.get_option_dict('apk')
option_dict = self.distribution.get_option_dict(self.package_type)

# This is a hack, we probably aren't supposed to loop through
# the option_dict so early because distutils does exactly the
Expand All @@ -34,7 +34,7 @@ def initialize_options(self):

def finalize_options(self):

setup_options = self.distribution.get_option_dict('apk')
setup_options = self.distribution.get_option_dict(self.package_type)
for (option, (source, value)) in setup_options.items():
if source == 'command line':
continue
Expand Down Expand Up @@ -75,7 +75,7 @@ def run(self):
self.prepare_build_dir()

from pythonforandroid.entrypoints import main
sys.argv[1] = 'apk'
sys.argv[1] = self.package_type
main()

def prepare_build_dir(self):
Expand Down Expand Up @@ -127,6 +127,22 @@ def prepare_build_dir(self):
)


class BdistAPK(Bdist):
"""
distutil command handler for 'apk'
"""
description = 'Create an APK with python-for-android'
package_type = 'apk'


class BdistAAR(Bdist):
"""
distutil command handler for 'aar'
"""
description = 'Create an AAR with python-for-android'
package_type = 'aar'


def _set_user_options():
# This seems like a silly way to do things, but not sure if there's a
# better way to pass arbitrary options onwards to p4a
Expand Down
41 changes: 25 additions & 16 deletions pythonforandroid/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from pythonforandroid.recipe import Recipe


def copy_files(src_root, dest_root, override=True):
def copy_files(src_root, dest_root, override=True, symlink=False):
for root, dirnames, filenames in walk(src_root):
for filename in filenames:
subdir = normpath(root.replace(src_root, ""))
Expand All @@ -29,7 +29,10 @@ def copy_files(src_root, dest_root, override=True):
if override and os.path.exists(dest_file):
os.unlink(dest_file)
if not os.path.exists(dest_file):
shutil.copy(src_file, dest_file)
if symlink:
os.symlink(src_file, dest_file)
else:
shutil.copy(src_file, dest_file)
else:
os.makedirs(dest_file)

Expand Down Expand Up @@ -109,7 +112,7 @@ def check_recipe_choices(self):
and optional dependencies are being used,
and returns a list of these.'''
recipes = []
built_recipes = self.ctx.recipe_build_order
built_recipes = self.ctx.recipe_build_order or []
for recipe in self.recipe_depends:
if isinstance(recipe, (tuple, list)):
for alternative in recipe:
Expand Down Expand Up @@ -137,21 +140,27 @@ def name(self):
modname = self.__class__.__module__
return modname.split(".", 2)[-1]

def get_bootstrap_dirs(self):
"""get all bootstrap directories, following the MRO path"""

# get all bootstrap names along the __mro__, cutting off Bootstrap and object
zworkb marked this conversation as resolved.
Show resolved Hide resolved
classes = self.__class__.__mro__[:-2]
bootstrap_names = [cls.name for cls in classes] + ['common']
bootstrap_dirs = [
join(self.ctx.root_dir, 'bootstraps', bootstrap_name)
for bootstrap_name in reversed(bootstrap_names)
]
return bootstrap_dirs

def prepare_build_dir(self):
'''Ensure that a build dir exists for the recipe. This same single
dir will be used for building all different archs.'''
"""Ensure that a build dir exists for the recipe. This same single
dir will be used for building all different archs."""
bootstrap_dirs = self.get_bootstrap_dirs()
# now do a cumulative copy of all bootstrap dirs
self.build_dir = self.get_build_dir()
self.common_dir = self.get_common_dir()
copy_files(join(self.bootstrap_dir, 'build'), self.build_dir)
copy_files(join(self.common_dir, 'build'), self.build_dir,
override=False)
if self.ctx.symlink_java_src:
info('Symlinking java src instead of copying')
shprint(sh.rm, '-r', join(self.build_dir, 'src'))
shprint(sh.mkdir, join(self.build_dir, 'src'))
for dirn in listdir(join(self.bootstrap_dir, 'build', 'src')):
shprint(sh.ln, '-s', join(self.bootstrap_dir, 'build', 'src', dirn),
zworkb marked this conversation as resolved.
Show resolved Hide resolved
join(self.build_dir, 'src'))
for bootstrap_dir in bootstrap_dirs:
copy_files(join(bootstrap_dir, 'build'), self.build_dir, symlink=self.ctx.symlink_bootstrap_files)

with current_directory(self.build_dir):
with open('project.properties', 'w') as fileh:
fileh.write('target=android-{}'.format(self.ctx.android_api))
Expand Down
3 changes: 2 additions & 1 deletion pythonforandroid/bootstraps/common/build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def compile_dir(dfn, optimize_python=True):
def make_package(args):
# If no launcher is specified, require a main.py/main.pyo:
if (get_bootstrap_name() != "sdl" or args.launcher is None) and \
get_bootstrap_name() != "webview":
get_bootstrap_name() not in ["webview", "service_library"]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This look like it should be a setting on the bootstrap.

# (webview doesn't need an entrypoint, apparently)
if args.private is None or (
not exists(join(realpath(args.private), 'main.py')) and
Expand Down Expand Up @@ -479,6 +479,7 @@ def make_package(args):
android_api=android_api,
build_tools_version=build_tools_version,
debug_build="debug" in args.build_mode,
is_library=(get_bootstrap_name() == 'service_library'),
)

# ant build templates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ protected static ArrayList<String> getLibraries(File libsDir) {
libsList.add("python3.5m");
libsList.add("python3.6m");
libsList.add("python3.7m");
libsList.add("python3.8m");
libsList.add("main");
return libsList;
}
Expand All @@ -59,7 +60,7 @@ public static void loadLibraries(File filesDir, File libsDir) {
// load, and it has failed, give a more
// general error
Log.v(TAG, "Library loading error: " + e.getMessage());
if (lib.startsWith("python3.7") && !foundPython) {
if (lib.startsWith("python3.8") && !foundPython) {
throw new java.lang.RuntimeException("Could not load any libpythonXXX.so");
} else if (lib.startsWith("python")) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ allprojects {
}
}

{% if is_library %}
apply plugin: 'com.android.library'
{% else %}
apply plugin: 'com.android.application'
{% endif %}

android {
compileSdkVersion {{ android_api }}
Expand Down
9 changes: 9 additions & 0 deletions pythonforandroid/bootstraps/service_library/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from pythonforandroid.bootstraps.service_only import ServiceOnlyBootstrap


class ServiceLibraryBootstrap(ServiceOnlyBootstrap):

name = 'service_library'


bootstrap = ServiceLibraryBootstrap()
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

#define BOOTSTRAP_NAME_LIBRARY
#define BOOTSTRAP_USES_NO_SDL_HEADERS

const char bootstrap_name[] = "service_library";

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.kivy.android;

import android.app.Activity;

// Required by PythonService class
public class PythonActivity extends Activity {

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// This string is autogenerated by ChangeAppSettings.sh, do not change
// spaces amount
package org.renpy.android;

import java.io.*;

import android.content.Context;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;

import java.util.zip.GZIPInputStream;

import android.content.res.AssetManager;

import org.kamranzafar.jtar.*;

public class AssetExtract {

private AssetManager mAssetManager = null;
private Context ctx = null;

public AssetExtract(Context context) {
ctx = context;
mAssetManager = ctx.getAssets();
}

public boolean extractTar(String asset, String target) {

byte buf[] = new byte[1024 * 1024];

InputStream assetStream = null;
TarInputStream tis = null;

try {
assetStream = mAssetManager.open(asset, AssetManager.ACCESS_STREAMING);
tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(assetStream, 8192)), 8192));
} catch (IOException e) {
Log.e("python", "opening up extract tar", e);
return false;
}

while (true) {
TarEntry entry = null;

try {
entry = tis.getNextEntry();
} catch ( java.io.IOException e ) {
Log.e("python", "extracting tar", e);
return false;
}

if ( entry == null ) {
break;
}

Log.v("python", "extracting " + entry.getName());

if (entry.isDirectory()) {

try {
new File(target +"/" + entry.getName()).mkdirs();
} catch ( SecurityException e ) { };

continue;
}

OutputStream out = null;
String path = target + "/" + entry.getName();

try {
out = new BufferedOutputStream(new FileOutputStream(path), 8192);
} catch ( FileNotFoundException e ) {
} catch ( SecurityException e ) { };

if ( out == null ) {
Log.e("python", "could not open " + path);
return false;
}

try {
while (true) {
int len = tis.read(buf);

if (len == -1) {
break;
}

out.write(buf, 0, len);
}

out.flush();
out.close();
} catch ( java.io.IOException e ) {
Log.e("python", "extracting zip", e);
return false;
}
}

try {
tis.close();
assetStream.close();
} catch (IOException e) {
// pass
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="{{ args.package }}"
android:versionCode="{{ args.numeric_version }}"
android:versionName="{{ args.version }}">

<!-- Android 2.3.3 -->
<uses-sdk android:minSdkVersion="{{ args.min_sdk_version }}" android:targetSdkVersion="{{ android_api }}" />

<application>
{% for name in service_names %}
<service android:name="{{ args.package }}.Service{{ name|capitalize }}"
android:process=":service_{{ name }}"
android:exported="true" />
{% endfor %}
</application>

</manifest>
Loading