Skip to content

Commit

Permalink
Merge pull request #52 from mhsmith/chaquopy
Browse files Browse the repository at this point in the history
Migrate Briefcase support to use Chaquopy
  • Loading branch information
freakboy3742 authored Sep 27, 2022
2 parents 00fece0 + 3bba6ec commit e1727ce
Show file tree
Hide file tree
Showing 12 changed files with 620 additions and 408 deletions.
72 changes: 25 additions & 47 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,16 @@ However, if you *do* want use this template directly...
your app). The remainder of these instructions will assume a `name` of
``my-project``, and a formal name of ``My Project``.

3. `Obtain a Python support package for Android`_, and extract it into
the ``My Project`` directory generated by the template. This will create
``app/libs`` and ``app/src/main/assets`` folders containing a self contained
Python install.

4. Add your code to the template, into the
``My Project/app/src/main/assets/python/app`` directory. At the very minimum,
you need to have an
``My Project/app/src/main/assets/python/app/<app name>/__main__.py`` file
that instantiates an instance of ``org.beeware.android.IPythonApp``, and
then invokes ``org.beeware.android.MainActivity.setPythonApp()``, providing
the ``IPythonApp`` instance.

If your code has any dependencies, they should be installed into the
``My Project/app/src/main/assets/python/app_packages`` directory.
3. Add your code to the template, into the ``My Project/app/src/main/python``
directory. At the very minimum, you need to have an ``<app
name>/__main__.py`` file that invokes
``org.beeware.android.MainActivity.setPythonApp()``, providing an
``IPythonApp`` instance. This provides the hooks into the Android application
lifecycle (``onCreate``, ``onResume`` and so on); it's up to you what your
code does with those lifecycle hooks.

If your code has any dependencies, they should be listed in the file
``My Project/app/requirements.txt``.

If you've done this correctly, a project with a formal name of ``My Project``,
with an app name of ``my-project`` should have a directory structure that
Expand All @@ -53,14 +48,10 @@ looks something like::
app/
src/
main/
assets/
python/
app/
my_project/
__init__.py
__main__.py (declares IPythonApp)
app_packages/
...
python/
my_project/
__init__.py
__main__.py (declares IPythonApp)
cpp/
...
java/
Expand All @@ -70,48 +61,35 @@ looks something like::
AndroidManifest.xml
build.gradle
proguard-rules.pro
requirements.txt
briefcase.toml
build.gradle
gradle.properties
gradlew
gradlew.bat
settings.gradle

You're now ready to run build and run your project! Set

$ ./gradlew installDebug
You're now ready to build and run your project! Either open the ``My Project``
directory in Android Studio, or `use the command line tools
<https://developer.android.com/studio/build/building-cmdline>`__.

Next steps
----------

Of course, running Python code isn't very interesting by itself - you'll be
able to output to the console, and see that output in Gradle, but if you tap the
able to output to the console, and see that output in the Logcat, but if you tap the
app icon on your phone, you won't see anything - because there isn't a visible
console on an Android.

To do something interesting, you'll need to work with the native Android system
libraries to draw widgets and respond to screen taps. The `Rubicon`_ Java
libraries to draw widgets and respond to screen taps. The `Chaquopy`_ Java
bridging library can be used to interface with the Android system libraries.

Alternatively, you could use a cross-platform widget toolkit that supports
Android (such as `Toga`_) to provide a GUI for your application.

Regardless of whether you use Toga, or you write an application natively, the
template project will run the `__main__` module associated with the app name
that you provided when you generated the tempalte. That Python code must
define an instance of ``org.beeware.android.IPythonApp``, and invoke
``org.beeware.android.MainActivity.setPythonApp()`` to set that instance as the
active Python app. This app will coordinate provides the hooks into the
Android application lifecycle (``onCreate``, ``onResume`` and so on); it's
up to you what your code does with those lifecycle hooks. If ``setPythonApp``
is not set, an error will be logged, and the Python interpreter will be shut
down.

If you have any external library dependencies (like Toga, or anything other
third-party library), you should install the library code into the
``app_packages`` directory. This directory is the same as a ``site_packages``
directory on a desktop Python install.
Android (such as `Toga`_) to provide a GUI for your application. Toga
automatically handles creating the ``IPythonApp`` instance and responding to the
app's lifecycle hooks.

.. _cookiecutter: https://github.com/cookiecutter/cookiecutter
.. _Obtain a Python support package for Android: https://github.com/beeware/Python-Android-support
.. _Rubicon: https://github.com/beeware/rubicon-java
.. _Chaquopy: https://chaquo.com/chaquopy/
.. _Toga: https://beeware.org/project/projects/libraries/toga
48 changes: 25 additions & 23 deletions {{ cookiecutter.safe_formal_name }}/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
apply plugin: 'com.android.application'
apply plugin: 'com.chaquo.python'

android {
compileSdkVersion 32
defaultConfig {
applicationId "{{ cookiecutter.package_name }}.{{ cookiecutter.module_name }}"

// JNI crashes may happen on older versions:
// https://github.com/beeware/rubicon-java/issues/74
minSdkVersion 26

targetSdkVersion 32
versionCode {{ cookiecutter.version_code }}
versionName "{{ cookiecutter.version }}"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

// Briefcase currently requires API level 24 for the `pidof` command, and the `--pid`
// argument to `adb logcat`. This supports over 90% of active devices
// (https://github.com/beeware/rubicon-java/issues/74).
minSdkVersion 24
targetSdkVersion 33

python {
version "{{ cookiecutter.python_version|py_tag }}"
pip {
install "-r", "requirements.txt"
}
}
externalNativeBuild {
cmake {
cppFlags "-std=c++14"
}
}
ndk {
// Chaquopy also supports x86, but it's not very useful anymore, so we'll
// disable it to speed up the build. For armeabi-v7a, see
// https://github.com/chaquo/chaquopy/issues/709.
abiFilters "arm64-v8a", "armeabi-v7a", "x86_64"
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
Expand All @@ -36,19 +51,10 @@ android {
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
aaptOptions {
// Use default ignore rule *except* allow directories starting with _,
// so that pyc files in __pycache__ directories flow through into apps.
// https://android.googlesource.com/platform/frameworks/base/+/b41af58f49d371cedf041443d20a1893f7f6c840/tools/aapt/AaptAssets.cpp#60
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
}
packagingOptions {
jniLibs {
// MainActivity requires libpython to be extracted as a separate file.
useLegacyPackaging true
python.srcDirs = [
"src/main/python", // App code
"src/main/python-briefcase", // Template code
]
}
}
}
Expand All @@ -60,9 +66,5 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation files('libs/rubicon.jar')
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
}
repositories {
mavenCentral()
}
2 changes: 2 additions & 0 deletions {{ cookiecutter.safe_formal_name }}/app/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# If your app needs any 3rd party packages, list them here as shown at
# https://pip.pypa.io/en/stable/reference/requirements-file-format/

This file was deleted.

This file was deleted.

Loading

0 comments on commit e1727ce

Please sign in to comment.