Skip to content

Call Android APIs with pyjnius

pyjnius bridges Python and Java, so your app can call the Android framework and any Java library you have added. The Android build of pyjnius is a prebuilt wheel on the mobile wheel index, so you compile nothing.

Before you begin

  • Configure your Android app, including the mobile wheel index in extra_index_urls.
  • You don't need to add pyjnius to your dependencies. Kivy itself uses it on Android, so kivyforge lock -p android adds it to every Android lock, in the range kivyforge supports (>=1.7.0, so new pyjnius releases work as they come out). Your desktop dependencies stay unchanged.

    To choose the version yourself, declare it. kivyforge then uses your requirement instead. The build fails if the locked pyjnius is older than 1.7, or if its Android wheel does not match the Java glue kivyforge generates:

    [project]
    dependencies = [
        "kivy==2.3.1",
        "pyjnius==1.8.0; sys_platform == 'android'",
    ]
    

    The marker keeps it out of desktop installs, where pyjnius would need a Java runtime. If a marker leaves Android out (for example sys_platform == 'win32'), kivyforge adds its own requirement as well, so an Android lock always has pyjnius.

    Pin any other dependency, including Kivy, the same way. See Pin a package version.

  • Declare any permission the API you call requires, under [tool.kivy.android.permissions].

Call an Android framework class

autoclass returns a Java class that you use like a Python class. This code reads the device model and Android version:

from jnius import autoclass

Build = autoclass("android.os.Build")
VERSION = autoclass("android.os.Build$VERSION")

print(Build.MODEL, Build.MANUFACTURER)
print("Android", VERSION.RELEASE, "API", VERSION.SDK_INT)

The pyjnius-deviceinfo example does the same. To reach the running activity, use autoclass("org.kivy.android.PythonActivity").mActivity.

Call a Java library you added

After you add a Java library, reach its classes the same way. This code, from the qr-maven example, encodes a QR code with ZXing:

from jnius import autoclass

QRCodeWriter = autoclass("com.google.zxing.qrcode.QRCodeWriter")
BarcodeFormat = autoclass("com.google.zxing.BarcodeFormat")

matrix = QRCodeWriter().encode("hello", BarcodeFormat.QR_CODE, 512, 512)

Implement a Java interface in Python

pyjnius can make a Python object implement a Java interface, so Java code can call back into Python. Subclass PythonJavaClass and mark methods with @java_method:

from jnius import PythonJavaClass, autoclass, java_method


class Task(PythonJavaClass):
    __javainterfaces__ = ["java/lang/Runnable"]
    __javacontext__ = "app"

    @java_method("()V")
    def run(self):
        print("called from Java")


FutureTask = autoclass("java.util.concurrent.FutureTask")
task = Task()
future = FutureTask(task, None)
future.run()  # Java calls Task.run()

Keep a Python reference to the object for as long as Java might call it.

Verify

Run the app on a device or emulator and confirm that the values appear in the log that kivyforge run prints. To check the pyjnius bridge itself, including a Java-to-Python callback, run the smoke test:

kivyforge run -p android --smoke

What's next