Skip to content
Fabian edited this page Dec 10, 2025 · 8 revisions

Contains how to's

How to Create Broadcast Listener Kivy

Register Listener

# buildozer.spec
android.add_src = src
p4a.hook = p4a/hook.py
# p4a/hook.py
from pathlib import Path
from pythonforandroid.toolchain import ToolchainCL

def after_apk_build(toolchain: ToolchainCL):
    manifest_file = Path(toolchain._dist.dist_dir) / "src" / "main" / "AndroidManifest.xml"
    old_manifest = manifest_file.read_text(encoding="utf-8")

    # Your custom receiver XML
    receiver_xml = '''
    <receiver android:name="org.laner.lan_ft.Action1"
              android:enabled="true"
              android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    '''

    # Insert before the closing </application>
    new_manifest = old_manifest.replace('</application>', f'{receiver_xml}\n</application>')

    manifest_file.write_text(new_manifest, encoding="utf-8")

    if old_manifest != new_manifest:
        print("Receiver added successfully")
    else:
        print("Failed to add receiver")

Talk to listener from py file

def test101():
    from jnius import autoclass, cast
    from android import python_act

    # Get current activity and context
    mActivity = autoclass("org.kivy.android.PythonActivity").mActivity
    context = mActivity.getApplicationContext()

    # Autoclass necessary Java classes
    RingtoneManager = autoclass("android.media.RingtoneManager")
    Uri = autoclass("android.net.Uri")
    AudioAttributesBuilder = autoclass("android.media.AudioAttributes$Builder")
    AudioAttributes = autoclass("android.media.AudioAttributes")
    AndroidString = autoclass("java.lang.String")
    NotificationManager = autoclass("android.app.NotificationManager")
    NotificationChannel = autoclass("android.app.NotificationChannel")
    NotificationCompat = autoclass("androidx.core.app.NotificationCompat")
    NotificationCompatBuilder = autoclass("androidx.core.app.NotificationCompat$Builder")
    NotificationManagerCompat = autoclass("androidx.core.app.NotificationManagerCompat")
    NotificationCompatActionBuilder = autoclass("androidx.core.app.NotificationCompat$Action$Builder")

    func_from = getattr(NotificationManagerCompat, "from")
    Intent = autoclass("android.content.Intent")
    PendingIntent = autoclass("android.app.PendingIntent")

    # Autoclass your own Java class
    action1 = autoclass("org.laner.lan_ft.Action1")

    # Variables
    channel_id = "channel_id"
    notification_id = 101
    id = 1  # action id

    # === CREATE CHANNEL ===
    sound = cast(Uri, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
    att = AudioAttributesBuilder()
    att.setUsage(AudioAttributes.USAGE_NOTIFICATION)
    att.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
    att = cast(AudioAttributes, att.build())

    name = cast("java.lang.CharSequence", AndroidString("Channel Name"))
    description = AndroidString("Channel Description")
    importance = NotificationManager.IMPORTANCE_HIGH

    channel = NotificationChannel(channel_id, name, importance)
    channel.setDescription(description)
    channel.enableLights(True)
    channel.enableVibration(True)
    channel.setSound(sound, att)

    notificationManager = context.getSystemService(NotificationManager)
    notificationManager.createNotificationChannel(channel)

    # === CREATE NOTIFICATION ===
    builder = NotificationCompatBuilder(context, channel_id)
    builder.setSmallIcon(context.getApplicationInfo().icon)
    builder.setContentTitle(cast("java.lang.CharSequence", AndroidString("Notification Title")))
    builder.setContentText(cast("java.lang.CharSequence", AndroidString("Notification Text")))
    builder.setSound(sound)
    builder.setPriority(NotificationCompat.PRIORITY_HIGH)
    builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

    # Intent for action button
    intent = Intent(context, action1)
    pendingintent = PendingIntent.getBroadcast(
        context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE
    )
    title = cast("java.lang.CharSequence", AndroidString("Action 1"))
		
    action1_button = NotificationCompatActionBuilder(
        id, title, pendingintent
    ).build()
    builder.addAction(action1_button)

    # Send the notification
    compatmanager = func_from(context)
    compatmanager.notify(notification_id, builder.build())

Broadcast Listener

// src/Action1.java

package org.laner.lan_ft;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
import android.util.Log;

public class Action1 extends BroadcastReceiver {

    private static final String TAG = "Action1";

    @Override
    public void onReceive(Context context, Intent intent) {
        // Show a short popup on the screen
        Toast.makeText(context, "Action1 triggered!", Toast.LENGTH_SHORT).show();

        // Log a message to Logcat
        Log.d(TAG, "BroadcastReceiver received an intent!");
    }
}

Resource: p4a hook and broadcast listener

Clone this wiki locally