From 930b00494aad0d31842b6939550f0ef228a259be Mon Sep 17 00:00:00 2001 From: malverick Date: Fri, 24 Feb 2017 00:08:44 +0530 Subject: [PATCH 1/4] Initial commit --- README.rst | 21 +++++----- examples/light/main.py | 71 ++++++++++++++++++++++++++++++++ plyer/__init__.py | 11 +++-- plyer/facades/__init__.py | 11 ++--- plyer/facades/light.py | 36 ++++++++++++++++ plyer/platforms/android/light.py | 60 +++++++++++++++++++++++++++ 6 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 examples/light/main.py create mode 100644 plyer/facades/light.py create mode 100644 plyer/platforms/android/light.py diff --git a/README.rst b/README.rst index 3970e93d6..94aa9b8e4 100755 --- a/README.rst +++ b/README.rst @@ -21,22 +21,23 @@ Supported APIs Platform Android iOS Windows OS X Linux ================================== ======= === ======= ==== ===== Accelerometer X X X X +Audio recording X +Battery X X X X X Call X X Camera (taking picture) X X -GPS X X -Notifications X X X X -Text to speech X X X X X -Email (open mail client) X X X X X -Vibrator X X -Sms (send messages) X X Compass X X -Unique ID X X X X X +Email (open mail client) X X X X X +Flash X X +GPS X X Gyroscope X X -Battery X X X X X +Light X Native file chooser X X X +Notifications X X X X Orientation X -Audio recording X -Flash X X +Sms (send messages) X X +Text to speech X X X X X +Unique ID X X X X X +Vibrator X X Wifi X X X ================================== ======= === ======= ==== ===== diff --git a/examples/light/main.py b/examples/light/main.py new file mode 100644 index 000000000..c91b5283a --- /dev/null +++ b/examples/light/main.py @@ -0,0 +1,71 @@ +from kivy.app import App +from kivy.clock import Clock +from kivy.lang import Builder +from kivy.properties import NumericProperty +from kivy.properties import ObjectProperty +from kivy.uix.boxlayout import BoxLayout + + +Builder.load_string(''' +#:import light plyer.light +: + light: light + orientation: 'vertical' + padding: '50dp' + spacing: '50dp' + + BoxLayout: + orientation: 'horizontal' + size_hint_y: 0.3 + Button: + id: button_enable + text: 'Enable' + disabled: False + on_release: + root.enable() + button_disable.disabled = not button_disable.disabled + button_enable.disabled = not button_enable.disabled + Button: + id: button_disable + text: 'Disable' + disabled: True + on_release: + root.disable() + button_disable.disabled = not button_disable.disabled + button_enable.disabled = not button_enable.disabled + + Label: + text: 'Current illumination:' + str(root.illumination) + ' lx.' + + +''') + + +class LightInterface(BoxLayout): + '''Root Widget.''' + + light = ObjectProperty() + illumination = NumericProperty() + + def enable(self): + self.light.enable() + Clock.schedule_interval(self.get_illumination, 1 / 20.) + + def disable(self): + self.light.disable() + Clock.unschedule(self.get_illumination) + + def get_illumination(self, dt): + self.illumination = self.light.illumination or self.illumination + + +class LightApp(App): + + def build(self): + return LightInterface() + + def on_pause(self): + return True + +if __name__ == '__main__': + LightApp().run() diff --git a/plyer/__init__.py b/plyer/__init__.py index 3dc9b77e0..3baad29e2 100644 --- a/plyer/__init__.py +++ b/plyer/__init__.py @@ -5,8 +5,8 @@ ''' __all__ = ('accelerometer', 'audio', 'battery', 'call', 'camera', 'compass', - 'email', 'filechooser', 'gps', 'gyroscope', 'irblaster', - 'orientation', 'notification', 'sms', 'tts', 'uniqueid', 'vibrator', + 'email', 'filechooser', 'gps', 'gyroscope', 'irblaster', 'light', + 'notification', 'orientation', 'sms', 'tts', 'uniqueid', 'vibrator', 'wifi') __version__ = '1.2.5dev' @@ -48,12 +48,15 @@ #: IrBlaster proxy to :class:`plyer.facades.IrBlaster` irblaster = Proxy('irblaster', facades.IrBlaster) -#: Orientation proxy to :class:`plyer.facades.Orientation` -orientation = Proxy('orientation', facades.Orientation) +#: Light proxy to :class:`plyer.facades.Light` +light = Proxy('light', facades.Light) #: Notification proxy to :class:`plyer.facades.Notification` notification = Proxy('notification', facades.Notification) +#: Orientation proxy to :class:`plyer.facades.Orientation` +orientation = Proxy('orientation', facades.Orientation) + #: Sms proxy to :class:`plyer.facades.Sms` sms = Proxy('sms', facades.Sms) diff --git a/plyer/facades/__init__.py b/plyer/facades/__init__.py index a726c1687..a3bd6a57a 100644 --- a/plyer/facades/__init__.py +++ b/plyer/facades/__init__.py @@ -7,9 +7,9 @@ ''' __all__ = ('Accelerometer', 'Audio', 'Battery', 'Call', 'Camera', 'Compass', - 'Email', 'FileChooser', 'GPS', 'Gyroscope', 'IrBlaster', - 'Orientation', 'Notification', 'Sms', 'TTS', 'UniqueID', 'Vibrator', - 'Wifi', 'Flash') + 'Email', 'FileChooser', 'Flash', 'GPS', 'Gyroscope', 'IrBlaster', + 'Light', 'Notification', 'Orientation', 'Sms', 'TTS', 'UniqueID', + 'Vibrator', 'Wifi') from plyer.facades.accelerometer import Accelerometer from plyer.facades.audio import Audio @@ -19,14 +19,15 @@ from plyer.facades.compass import Compass from plyer.facades.email import Email from plyer.facades.filechooser import FileChooser +from plyer.facades.flash import Flash from plyer.facades.gps import GPS from plyer.facades.gyroscope import Gyroscope from plyer.facades.irblaster import IrBlaster -from plyer.facades.orientation import Orientation +from plyer.facades.light import Light from plyer.facades.notification import Notification +from plyer.facades.orientation import Orientation from plyer.facades.sms import Sms from plyer.facades.tts import TTS from plyer.facades.uniqueid import UniqueID from plyer.facades.vibrator import Vibrator -from plyer.facades.flash import Flash from plyer.facades.wifi import Wifi diff --git a/plyer/facades/light.py b/plyer/facades/light.py new file mode 100644 index 000000000..b5d8a3c83 --- /dev/null +++ b/plyer/facades/light.py @@ -0,0 +1,36 @@ +class Light(object): + '''Light facade. + + Light sensor measures the ambient light level(illumination) in lx. + Common uses include controlling screen brightness. + + With method `enable` you can turn on the sensor and + `disable` method stops the sensor. + + Use property `illumination` to get current illumination in lx. + + ''' + + @property + def illumination(self): + '''Current illumination in lx.''' + return self._get_illumination() + + def enable(self): + '''Enable light sensor.''' + self._enable() + + def disable(self): + '''Disable light sensor.''' + self._disable() + + #private + + def _get_illumination(self, **kwargs): + raise NotImplementedError() + + def _enable(self, **kwargs): + raise NotImplementedError() + + def _disable(self, **kwargs): + raise NotImplementedError() \ No newline at end of file diff --git a/plyer/platforms/android/light.py b/plyer/platforms/android/light.py new file mode 100644 index 000000000..9fcf8a528 --- /dev/null +++ b/plyer/platforms/android/light.py @@ -0,0 +1,60 @@ +from jnius import autoclass +from jnius import cast +from jnius import java_method +from jniud import PythonJavaClass + +from plyer.facades import Light +from plyer.platforms.android import activity + +Context = autoclass('android.content.Context') +Sensor = autoclass('android.hardware.Sensor') +SensorManager = autoclass('android.hardware.SensorManager') + + +class LightSensorListener(PythonJavaClass): + __javainterfaces__ = ['android/hardware/SensorEventListener'] + + def __init__(self): + super(LightSensorListener, self).__init__() + service = activity.getSystemService(Context.SENSOR_SERVICE) + self.SensorManager = cast('android.hardware.SensorManager', service) + self.sensor = self.SensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) + self.value = None + + def enable(self): + self.SensorManager.registerListener(self, self.sensor, + SensorManager.SENSOR_DELAY_NORMAL) + + def disable(self): + self.SensorManager.unregisterListener(self, self.sensor) + + @java_method('(Landroid/hardware/SensorEvent;)V') + def onSensorChanged(self, event): + self.value = event.values[0] + + @java_method('(Landroid/hardware/Sensor;I)V') + def onAccuracyChanged(self, sensor, accuracy): + pass + +class AndroidLight(Light): + + listener = None + + def _get_illumination(self): + if self.listener and self.listener.value: + light = self.listener.value + return light + + def _enable(self): + if not self.listener: + self.listener = LightSensorListener() + self.listener.enable() + + def _disable(self): + if self.listener: + self.listener.disable() + delattr(self, 'listener') + + +def instance(): + return AndroidLight() From 3a8a49df06b4bb9b7cc1a94009b31929ec97c1ad Mon Sep 17 00:00:00 2001 From: malverick Date: Fri, 24 Feb 2017 00:52:37 +0530 Subject: [PATCH 2/4] Fix typo --- plyer/platforms/android/light.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plyer/platforms/android/light.py b/plyer/platforms/android/light.py index 9fcf8a528..988cc5ae6 100644 --- a/plyer/platforms/android/light.py +++ b/plyer/platforms/android/light.py @@ -1,7 +1,7 @@ from jnius import autoclass from jnius import cast from jnius import java_method -from jniud import PythonJavaClass +from jnius import PythonJavaClass from plyer.facades import Light from plyer.platforms.android import activity From 3934a9829d3011792e45f629d3b28036258531e9 Mon Sep 17 00:00:00 2001 From: malverick Date: Fri, 24 Feb 2017 00:54:38 +0530 Subject: [PATCH 3/4] Add buildozer.spec --- examples/light/buildozer.spec | 233 ++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 examples/light/buildozer.spec diff --git a/examples/light/buildozer.spec b/examples/light/buildozer.spec new file mode 100644 index 000000000..286f7d0f7 --- /dev/null +++ b/examples/light/buildozer.spec @@ -0,0 +1,233 @@ +[app] + +# (str) Title of your application +title = Plyer Light Example + +# (str) Package name +package.name = plyerlight + +# (str) Package domain (needed for android/ios packaging) +package.domain = org.test + +# (str) Source code where the main.py live +source.dir = . + +# (list) Source files to include (let empty to include all the files) +source.include_exts = py,png,jpg,kv,atlas + +# (list) List of inclusions using pattern matching +#source.include_patterns = assets/*,images/*.png + +# (list) Source files to exclude (let empty to not exclude anything) +#source.exclude_exts = spec + +# (list) List of directory to exclude (let empty to not exclude anything) +#source.exclude_dirs = tests, bin + +# (list) List of exclusions using pattern matching +#source.exclude_patterns = license,images/*/*.jpg + +# (str) Application versioning (method 1) +version = 0.1 + +# (str) Application versioning (method 2) +# version.regex = __version__ = ['"](.*)['"] +# version.filename = %(source.dir)s/main.py + +# (list) Application requirements +# comma seperated e.g. requirements = sqlite3,kivy +requirements = kivy,plyer + +# (str) Custom source folders for requirements +# Sets custom source for any requirements with recipes +# requirements.source.kivy = ../../kivy + +# (list) Garden requirements +#garden_requirements = + +# (str) Presplash of the application +#presplash.filename = %(source.dir)s/data/presplash.png + +# (str) Icon of the application +#icon.filename = %(source.dir)s/data/icon.png + +# (str) Supported orientation (one of landscape, portrait or all) +orientation = portrait + +# (list) List of service to declare +#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY + +# +# OSX Specific +# + +# +# author = © Copyright Info + +# +# Android specific +# + +# (bool) Indicate if the application should be fullscreen or not +fullscreen = 0 + +# (list) Permissions +#android.permissions = INTERNET + +# (int) Android API to use +#android.api = 19 + +# (int) Minimum API required +#android.minapi = 9 + +# (int) Android SDK version to use +#android.sdk = 20 + +# (str) Android NDK version to use +#android.ndk = 9c + +# (bool) Use --private data storage (True) or --dir public storage (False) +#android.private_storage = True + +# (str) Android NDK directory (if empty, it will be automatically downloaded.) +#android.ndk_path = + +# (str) Android SDK directory (if empty, it will be automatically downloaded.) +#android.sdk_path = + +# (str) ANT directory (if empty, it will be automatically downloaded.) +#android.ant_path = + +# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github) +#android.p4a_dir = + +# (str) The directory in which python-for-android should look for your own build recipes (if any) +#p4a.local_recipes = + +# (list) python-for-android whitelist +#android.p4a_whitelist = + +# (bool) If True, then skip trying to update the Android sdk +# This can be useful to avoid excess Internet downloads or save time +# when an update is due and you just want to test/build your package +# android.skip_update = False + +# (str) Bootstrap to use for android builds (android_new only) +# android.bootstrap = sdl2 + +# (str) Android entry point, default is ok for Kivy-based app +#android.entrypoint = org.renpy.android.PythonActivity + +# (list) List of Java .jar files to add to the libs so that pyjnius can access +# their classes. Don't add jars that you do not need, since extra jars can slow +# down the build process. Allows wildcards matching, for example: +# OUYA-ODK/libs/*.jar +#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar + +# (list) List of Java files to add to the android project (can be java or a +# directory containing the files) +#android.add_src = + +# (str) python-for-android branch to use, if not master, useful to try +# not yet merged features. +#android.branch = master + +# (str) OUYA Console category. Should be one of GAME or APP +# If you leave this blank, OUYA support will not be enabled +#android.ouya.category = GAME + +# (str) Filename of OUYA Console icon. It must be a 732x412 png image. +#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png + +# (str) XML file to include as an intent filters in tag +#android.manifest.intent_filters = + +# (list) Android additionnal libraries to copy into libs/armeabi +#android.add_libs_armeabi = libs/android/*.so +#android.add_libs_armeabi_v7a = libs/android-v7/*.so +#android.add_libs_x86 = libs/android-x86/*.so +#android.add_libs_mips = libs/android-mips/*.so + +# (bool) Indicate whether the screen should stay on +# Don't forget to add the WAKE_LOCK permission if you set this to True +#android.wakelock = False + +# (list) Android application meta-data to set (key=value format) +#android.meta_data = + +# (list) Android library project to add (will be added in the +# project.properties automatically.) +#android.library_references = + +# (str) Android logcat filters to use +#android.logcat_filters = *:S python:D + +# (bool) Copy library instead of making a libpymodules.so +#android.copy_libs = 1 + +# +# iOS specific +# + +# (str) Path to a custom kivy-ios folder +#ios.kivy_ios_dir = ../kivy-ios + +# (str) Name of the certificate to use for signing the debug version +# Get a list of available identities: buildozer ios list_identities +#ios.codesign.debug = "iPhone Developer: ()" + +# (str) Name of the certificate to use for signing the release version +#ios.codesign.release = %(ios.codesign.debug)s + + +[buildozer] + +# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output)) +log_level = 2 + +# (int) Display warning if buildozer is run as root (0 = False, 1 = True) +warn_on_root = 1 + +# (str) Path to build artifact storage, absolute or relative to spec file +# build_dir = ./.buildozer + +# (str) Path to build output (i.e. .apk, .ipa) storage +# bin_dir = ./bin + +# ----------------------------------------------------------------------------- +# List as sections +# +# You can define all the "list" as [section:key]. +# Each line will be considered as a option to the list. +# Let's take [app] / source.exclude_patterns. +# Instead of doing: +# +#[app] +#source.exclude_patterns = license,data/audio/*.wav,data/images/original/* +# +# This can be translated into: +# +#[app:source.exclude_patterns] +#license +#data/audio/*.wav +#data/images/original/* +# + + +# ----------------------------------------------------------------------------- +# Profiles +# +# You can extend section / key with a profile +# For example, you want to deploy a demo version of your application without +# HD content. You could first change the title to add "(demo)" in the name +# and extend the excluded directories to remove the HD content. +# +#[app@demo] +#title = My Application (demo) +# +#[app:source.exclude_patterns@demo] +#images/hd/* +# +# Then, invoke the command line with the "demo" profile: +# +#buildozer --profile demo android debug From 55cd7d97044815647c9666c2c06099dd3475d301 Mon Sep 17 00:00:00 2001 From: malverick Date: Fri, 24 Feb 2017 00:56:49 +0530 Subject: [PATCH 4/4] Pep8 fixes --- examples/light/main.py | 86 ++++++++++++++++---------------- plyer/facades/light.py | 48 +++++++++--------- plyer/platforms/android/light.py | 65 ++++++++++++------------ 3 files changed, 100 insertions(+), 99 deletions(-) diff --git a/examples/light/main.py b/examples/light/main.py index c91b5283a..39034bcb2 100644 --- a/examples/light/main.py +++ b/examples/light/main.py @@ -9,63 +9,63 @@ Builder.load_string(''' #:import light plyer.light : - light: light - orientation: 'vertical' - padding: '50dp' - spacing: '50dp' - - BoxLayout: - orientation: 'horizontal' - size_hint_y: 0.3 - Button: - id: button_enable - text: 'Enable' - disabled: False - on_release: - root.enable() - button_disable.disabled = not button_disable.disabled - button_enable.disabled = not button_enable.disabled - Button: - id: button_disable - text: 'Disable' - disabled: True - on_release: - root.disable() - button_disable.disabled = not button_disable.disabled - button_enable.disabled = not button_enable.disabled - - Label: - text: 'Current illumination:' + str(root.illumination) + ' lx.' + light: light + orientation: 'vertical' + padding: '50dp' + spacing: '50dp' + + BoxLayout: + orientation: 'horizontal' + size_hint_y: 0.3 + Button: + id: button_enable + text: 'Enable' + disabled: False + on_release: + root.enable() + button_disable.disabled = not button_disable.disabled + button_enable.disabled = not button_enable.disabled + Button: + id: button_disable + text: 'Disable' + disabled: True + on_release: + root.disable() + button_disable.disabled = not button_disable.disabled + button_enable.disabled = not button_enable.disabled + + Label: + text: 'Current illumination:' + str(root.illumination) + ' lx.' ''') class LightInterface(BoxLayout): - '''Root Widget.''' + '''Root Widget.''' - light = ObjectProperty() - illumination = NumericProperty() + light = ObjectProperty() + illumination = NumericProperty() - def enable(self): - self.light.enable() - Clock.schedule_interval(self.get_illumination, 1 / 20.) + def enable(self): + self.light.enable() + Clock.schedule_interval(self.get_illumination, 1 / 20.) - def disable(self): - self.light.disable() - Clock.unschedule(self.get_illumination) + def disable(self): + self.light.disable() + Clock.unschedule(self.get_illumination) - def get_illumination(self, dt): - self.illumination = self.light.illumination or self.illumination + def get_illumination(self, dt): + self.illumination = self.light.illumination or self.illumination class LightApp(App): - def build(self): - return LightInterface() + def build(self): + return LightInterface() - def on_pause(self): - return True + def on_pause(self): + return True if __name__ == '__main__': - LightApp().run() + LightApp().run() diff --git a/plyer/facades/light.py b/plyer/facades/light.py index b5d8a3c83..72614f097 100644 --- a/plyer/facades/light.py +++ b/plyer/facades/light.py @@ -1,36 +1,36 @@ class Light(object): - '''Light facade. + '''Light facade. - Light sensor measures the ambient light level(illumination) in lx. - Common uses include controlling screen brightness. + Light sensor measures the ambient light level(illumination) in lx. + Common uses include controlling screen brightness. - With method `enable` you can turn on the sensor and - `disable` method stops the sensor. + With method `enable` you can turn on the sensor and + `disable` method stops the sensor. - Use property `illumination` to get current illumination in lx. + Use property `illumination` to get current illumination in lx. - ''' + ''' - @property - def illumination(self): - '''Current illumination in lx.''' - return self._get_illumination() + @property + def illumination(self): + '''Current illumination in lx.''' + return self._get_illumination() - def enable(self): - '''Enable light sensor.''' - self._enable() + def enable(self): + '''Enable light sensor.''' + self._enable() - def disable(self): - '''Disable light sensor.''' - self._disable() + def disable(self): + '''Disable light sensor.''' + self._disable() - #private + #private - def _get_illumination(self, **kwargs): - raise NotImplementedError() + def _get_illumination(self, **kwargs): + raise NotImplementedError() - def _enable(self, **kwargs): - raise NotImplementedError() + def _enable(self, **kwargs): + raise NotImplementedError() - def _disable(self, **kwargs): - raise NotImplementedError() \ No newline at end of file + def _disable(self, **kwargs): + raise NotImplementedError() diff --git a/plyer/platforms/android/light.py b/plyer/platforms/android/light.py index 988cc5ae6..4971c2e38 100644 --- a/plyer/platforms/android/light.py +++ b/plyer/platforms/android/light.py @@ -12,49 +12,50 @@ class LightSensorListener(PythonJavaClass): - __javainterfaces__ = ['android/hardware/SensorEventListener'] + __javainterfaces__ = ['android/hardware/SensorEventListener'] - def __init__(self): - super(LightSensorListener, self).__init__() - service = activity.getSystemService(Context.SENSOR_SERVICE) - self.SensorManager = cast('android.hardware.SensorManager', service) - self.sensor = self.SensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) - self.value = None + def __init__(self): + super(LightSensorListener, self).__init__() + service = activity.getSystemService(Context.SENSOR_SERVICE) + self.SensorManager = cast('android.hardware.SensorManager', service) + self.sensor = self.SensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) + self.value = None - def enable(self): - self.SensorManager.registerListener(self, self.sensor, - SensorManager.SENSOR_DELAY_NORMAL) + def enable(self): + self.SensorManager.registerListener(self, self.sensor, + SensorManager.SENSOR_DELAY_NORMAL) - def disable(self): - self.SensorManager.unregisterListener(self, self.sensor) + def disable(self): + self.SensorManager.unregisterListener(self, self.sensor) - @java_method('(Landroid/hardware/SensorEvent;)V') - def onSensorChanged(self, event): - self.value = event.values[0] + @java_method('(Landroid/hardware/SensorEvent;)V') + def onSensorChanged(self, event): + self.value = event.values[0] + + @java_method('(Landroid/hardware/Sensor;I)V') + def onAccuracyChanged(self, sensor, accuracy): + pass - @java_method('(Landroid/hardware/Sensor;I)V') - def onAccuracyChanged(self, sensor, accuracy): - pass class AndroidLight(Light): - listener = None + listener = None - def _get_illumination(self): - if self.listener and self.listener.value: - light = self.listener.value - return light + def _get_illumination(self): + if self.listener and self.listener.value: + light = self.listener.value + return light - def _enable(self): - if not self.listener: - self.listener = LightSensorListener() - self.listener.enable() + def _enable(self): + if not self.listener: + self.listener = LightSensorListener() + self.listener.enable() - def _disable(self): - if self.listener: - self.listener.disable() - delattr(self, 'listener') + def _disable(self): + if self.listener: + self.listener.disable() + delattr(self, 'listener') def instance(): - return AndroidLight() + return AndroidLight()