Skip to content
Open
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
12 changes: 11 additions & 1 deletion doc/source/apis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -342,18 +342,28 @@ or categories filters.
The callback will be called in another thread than the main thread. In
that thread, be careful not to access OpenGL or something like that.

.. method:: __init__(callback, actions=None, categories=None)
.. method:: __init__(callback, actions=None, categories=None, exported=False)

:param callback: function or method that will receive the event. Will
receive the context and intent as argument.
:param actions: list of strings that represent an action.
:param categories: list of strings that represent a category.
:param exported: if `True`, other applications are allowed to send
broadcasts to this receiver. Defaults to `False`.

For actions and categories, the string must be in lower case, without the prefix::

# In java: Intent.ACTION_HEADSET_PLUG
# In python: 'headset_plug'

.. note::

Since Android 14 (API 34), receivers must be registered with
``RECEIVER_EXPORTED`` or ``RECEIVER_NOT_EXPORTED``. The default
(``exported=False``) uses ``RECEIVER_NOT_EXPORTED``, so only your
own application and the system can send broadcasts to this
receiver.

.. method:: start()

Register the receiver with all the actions and categories, and start
Expand Down
20 changes: 17 additions & 3 deletions pythonforandroid/recipes/android/src/android/broadcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ def __init__(self, callback, *args, **kwargs):
def onReceive(self, context, intent):
self.callback(context, intent)

def __init__(self, callback, actions=None, categories=None):
def __init__(self, callback, actions=None, categories=None, exported=False):
super().__init__()
self.callback = callback
self._is_registered = False
self.exported = exported

if not actions and not categories:
raise Exception('You need to define at least actions or categories')
Expand Down Expand Up @@ -77,10 +78,23 @@ def start(self):

Handler = autoclass('android.os.Handler')
self.handler = Handler(self.handlerthread.getLooper())
self.context.registerReceiver(
self.receiver, self.receiver_filter, None, self.handler)
self._register_receiver()
self._is_registered = True

def _register_receiver(self):
if autoclass('android.os.Build$VERSION').SDK_INT >= 33:
# API 34+ requires RECEIVER_EXPORTED / RECEIVER_NOT_EXPORTED
Context = autoclass('android.content.Context')
if self.exported:
flags = Context.RECEIVER_EXPORTED
else:
flags = Context.RECEIVER_NOT_EXPORTED
self.context.registerReceiver(
self.receiver, self.receiver_filter, None, self.handler, flags)
else:
self.context.registerReceiver(
self.receiver, self.receiver_filter, None, self.handler)

def stop(self):
try:
self.context.unregisterReceiver(self.receiver)
Expand Down
Loading