8000 add android_broadcast module · cydeep/python-for-android@075a465 · GitHub
[go: up one dir, main page]

Skip to content

Commit 075a465

Browse files
committed
add android_broadcast module
1 parent 55d291e commit 075a465

File tree

4 files changed

+181
-0
lines changed
  • docs/source
  • < 8000 div class="PRIVATE_VisuallyHidden prc-TreeView-TreeViewVisuallyHidden-4-mPv" aria-hidden="true" id=":R3lddabH1:">
    recipes/android/src
  • src/src/org/renpy/android
  • 4 files changed

    +181
    -0
    lines changed

    docs/source/android.rst

    Lines changed: 79 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -348,6 +348,84 @@ Example without PyJNIus
    348348
    print android.get_dpi()
    349349

    350350

    351+
    Bridges
    352+
    -------
    353+
    354+
    Some part of the Android API is not accessible from PyJNIus. For example, if
    355+
    you want to receive some broadcast, you need to implement a `BroadcastReceiver
    356+
    <http://developer.android.com/reference/android/content/BroadcastReceiver.html>`_.
    357+
    PyJNIus allows you to implement dynamically classes from Java interfaces, but
    358+
    unfortunately, the `BroadcastReceiver` is an abstract class.
    359+
    360+
    So we started to create bridges for this case.
    361+
    362+
    android_broadcast
    363+
    ~~~~~~~~~~~~~~~~~
    364+
    365+
    .. module:: android_broadcast
    366+
    367+
    .. class:: BroadcastReceiver
    368+
    369+
    Implementation of the android `BroadcastReceiver
    370+
    <http://developer.android.com/reference/android/content/BroadcastReceiver.html>`_.
    371+
    You can specify the callback that will receive the broadcast event, and
    372+
    actions or categories filters.
    373+
    374+
    .. warning::
    375+
    376+
    The callback will be called in another thread than the main thread. Be
    377+
    careful to not access to OpenGL or something like that.
    378+
    379+
    .. method:: __init__(callback, actions=None, categories=None)
    380+
    381+
    :param callback: function or method that will receive the event. Will
    382+
    receive the context and intent as argument.
    383+
    :param actions: list of strings that represent an action.
    384+
    :param categories: list of strings that represent a category.
    385+
    386+
    For actions and categories, the string must be in lower case, without the prefix::
    387+
    388+
    # In java: Intent.ACTION_HEADSET_PLUG
    389+
    # In python: 'headset_plug'
    390+
    391+
    .. method:: start()
    392+
    393+
    Register the receiver with all the actions and categories, and start
    394+
    handling events.
    395+
    396+
    .. method:: stop()
    397+
    398+
    Unregister the receiver with all the actions and categories, and stop
    399+
    handling events.
    400+
    401+
    Example::
    402+
    403+
    class TestApp(App):
    404+
    405+
    def build(self):
    406+
    self.br = BroadcastReceiver(
    407+
    self.on_broadcast, actions=['headset_plug'])
    408+
    self.br.start()
    409+
    # ...
    410+
    411+
    def on_broadcast(self, context, intent):
    412+
    extras = intent.getExtras()
    413+
    headset_state = bool(extras.get('state'))
    414+
    if headset_state:
    415+
    print 'The headset is plugged'
    416+
    else:
    417+
    print 'The headset is unplugged'
    418+
    419+
    # don't forget to stop and restart the receiver when the app is going
    420+
    # to pause / resume mode
    421+
    422+
    def on_pause(self):
    423+
    self.br.stop()
    424+
    return True
    425+
    426+
    def on_resume(self):
    427+
    self.br.start()
    428+
    351429

    352430
    Old Version
    353431
    -----------
    @@ -434,3 +512,4 @@ It has several differences from the pygame mixer:
    434512
    The android_mixer module hasn't been tested much, and so bugs may be
    435513
    present.
    436514

    515+
    Lines changed: 75 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,75 @@
    1+
    # -------------------------------------------------------------------
    2+
    # Broadcast receiver bridge
    3+
    4+
    from jnius import autoclass, PythonJavaClass, java_method
    5+
    6+
    class BroadcastReceiver(object):
    7+
    8+
    class Callback(PythonJavaClass):
    9+
    __javainterfaces__ = ['org/renpy/android/GenericBroadcastReceiverCallback']
    10+
    __javacontext__ = 'app'
    11+
    12+
    def __init__(self, callback, *args, **kwargs):
    13+
    self.callback = callback
    14+
    PythonJavaClass.__init__(self, *args, **kwargs)
    15+
    16+
    @java_method('(Landroid/content/Context;Landroid/content/Intent;)V')
    17+
    def onReceive(self, context, intent):
    18+
    self.callback(context, intent)
    19+
    20+
    def __init__(self, callback, actions=None, categories=None):
    21+
    super(BroadcastReceiver, self).__init__()
    22+
    self.callback = callback
    23+
    24+
    if not actions and not categories:
    25+
    raise Exception('You need to define at least actions or categories')
    26+
    27+
    # resolve actions/categories first
    28+
    Intent = autoclass('android.content.Intent')
    29+
    resolved_actions = []
    30+
    if actions:
    31+
    for x in actions:
    32+
    name = 'ACTION_{}'.format(x.upper())
    33+
    if not hasattr(Intent, name):
    34+
    raise Exception('The intent {} doesnt exist'.format(name))
    35+
    resolved_actions += [getattr(Intent, name)]
    36+
    37+
    resolved_categories = []
    38+
    if categories:
    39+
    for x in categories:
    40+
    name = 'CATEGORY_{}'.format(x.upper())
    41+
    if not hasattr(Intent, name):
    42+
    raise Exception('The intent {} doesnt exist'.format(name))
    43+
    resolved_categories += [getattr(Intent, name)]
    44+
    45+
    # resolve android API
    46+
    PythonActivity = autoclass('org.renpy.android.PythonActivity')
    47+
    GenericBroadcastReceiver = autoclass('org.renpy.android.GenericBroadcastReceiver')
    48+
    IntentFilter = autoclass('android.content.IntentFilter')
    49+
    HandlerThread = autoclass('android.os.HandlerThread')
    50+
    51+
    # create a thread for handling events from the receiver
    52+
    self.handlerthread = HandlerThread('handlerthread')
    53+
    54+
    # create a listener
    55+
    self.context = PythonActivity.mActivity
    56+
    self.listener = BroadcastReceiver.Callback(self.callback)
    57+
    self.receiver = GenericBroadcastReceiver(self.listener)
    58+
    self.receiver_filter = IntentFilter()
    59+
    for x in resolved_actions:
    60+
    self.receiver_filter.addAction(x)
    61+
    for x in resolved_categories:
    62+
    self.receiver_filter.addCategory(x)
    63+
    64+
    def start(self):
    65+
    Handler = autoclass('android.os.Handler')
    66+
    self.handlerthread.start()
    67+
    self.handler = Handler(self.handlerthread.getLooper())
    68+
    self.context.registerReceiver(self.receiver, self.receiver_filter, None,
    69+
    self.handler)
    70+
    71+
    def stop(self):
    72+
    self.context.unregisterReceiver(self.receiver)
    73+
    self.handlerthread.quit()
    74+
    75+
    Lines changed: 19 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,19 @@
    1+
    package org.renpy.android;
    2+
    3+
    import android.content.BroadcastReceiver;
    4+
    import android.content.Intent;
    5+
    import android.content.Context;
    6+
    7+
    public class GenericBroadcastReceiver extends BroadcastReceiver {
    8+
    9+
    GenericBroadcastReceiverCallback listener;
    10+
    11+
    public GenericBroadcastReceiver(GenericBroadcastReceiverCallback listener) {
    12+
    super();
    13+
    this.listener = listener;
    14+
    }
    15+
    16+
    public void onReceive(Context context, Intent intent) {
    17+
    this.listener.onReceive(context, intent);
    18+
    }
    19+
    }
    Lines changed: 8 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,8 @@
    1+
    package org.renpy.android;
    2+
    3+
    import android.content.Intent;
    4+
    import android.content.Context;
    5+
    6+
    public interface GenericBroadcastReceiverCallback {
    7+
    void onReceive(Context context, Intent intent);
    8+
    };

    0 commit comments

    Comments
     (0)
    0