mirror of
				https://github.com/liberatedsystems/openCom-Companion.git
				synced 2025-07-08 05:07:21 +02:00 
			
		
		
		
	Included local plyer
This commit is contained in:
		
							parent
							
								
									25f0d52260
								
							
						
					
					
						commit
						f23855fb68
					
				
							
								
								
									
										124
									
								
								sbapp/plyer/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								sbapp/plyer/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,124 @@ | ||||
| ''' | ||||
| Plyer | ||||
| ===== | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| __all__ = ( | ||||
|     'accelerometer', 'audio', 'barometer', 'battery', 'bluetooth', | ||||
|     'brightness', 'call', 'camera', 'compass', 'cpu', 'email', 'filechooser', | ||||
|     'flash', 'gps', 'gravity', 'gyroscope', 'humidity', 'irblaster', | ||||
|     'keystore', 'light', 'notification', 'orientation', 'processors', | ||||
|     'proximity', 'screenshot', 'sms', 'spatialorientation', 'storagepath', | ||||
|     'stt', 'temperature', 'tts', 'uniqueid', 'vibrator', 'wifi', 'devicename' | ||||
| ) | ||||
| 
 | ||||
| __version__ = '2.1.0.dev0' | ||||
| 
 | ||||
| 
 | ||||
| from plyer import facades | ||||
| from plyer.utils import Proxy | ||||
| 
 | ||||
| #: Accelerometer proxy to :class:`plyer.facades.Accelerometer` | ||||
| accelerometer = Proxy('accelerometer', facades.Accelerometer) | ||||
| 
 | ||||
| #: Keyring proxy to :class::`plyer.facades.Keystore` | ||||
| keystore = Proxy('keystore', facades.Keystore) | ||||
| 
 | ||||
| #: Audio proxy to :class:`plyer.facades.Audio` | ||||
| audio = Proxy('audio', facades.Audio) | ||||
| 
 | ||||
| #: Barometer proxy to :class:`plyer.facades.Barometer` | ||||
| barometer = Proxy('barometer', facades.Barometer) | ||||
| 
 | ||||
| #: Battery proxy to :class:`plyer.facades.Battery` | ||||
| battery = Proxy('battery', facades.Battery) | ||||
| 
 | ||||
| #: Call proxy to  :class `plyer.facades.Call` | ||||
| call = Proxy('call', facades.Call) | ||||
| 
 | ||||
| #: Compass proxy to :class:`plyer.facades.Compass` | ||||
| compass = Proxy('compass', facades.Compass) | ||||
| 
 | ||||
| #: Camera proxy to :class:`plyer.facades.Camera` | ||||
| camera = Proxy('camera', facades.Camera) | ||||
| 
 | ||||
| #: Email proxy to :class:`plyer.facades.Email` | ||||
| email = Proxy('email', facades.Email) | ||||
| 
 | ||||
| #: FileChooser proxy to :class:`plyer.facades.FileChooser` | ||||
| filechooser = Proxy('filechooser', facades.FileChooser) | ||||
| 
 | ||||
| #: GPS proxy to :class:`plyer.facades.GPS` | ||||
| gps = Proxy('gps', facades.GPS) | ||||
| 
 | ||||
| #: Gravity proxy to :class:`plyer.facades.Gravity` | ||||
| gravity = Proxy('gravity', facades.Gravity) | ||||
| 
 | ||||
| #: Gyroscope proxy to :class:`plyer.facades.Gyroscope` | ||||
| gyroscope = Proxy('gyroscope', facades.Gyroscope) | ||||
| 
 | ||||
| #: IrBlaster proxy to :class:`plyer.facades.IrBlaster` | ||||
| irblaster = Proxy('irblaster', facades.IrBlaster) | ||||
| 
 | ||||
| #: Light proxy to :class:`plyer.facades.Light` | ||||
| light = Proxy('light', facades.Light) | ||||
| 
 | ||||
| #: Orientation proxy to :class:`plyer.facades.Orientation` | ||||
| orientation = Proxy('orientation', facades.Orientation) | ||||
| 
 | ||||
| #: Notification proxy to :class:`plyer.facades.Notification` | ||||
| notification = Proxy('notification', facades.Notification) | ||||
| 
 | ||||
| #: Proximity proxy to :class:`plyer.facades.Proximity` | ||||
| proximity = Proxy('proximity', facades.Proximity) | ||||
| 
 | ||||
| #: Sms proxy to :class:`plyer.facades.Sms` | ||||
| sms = Proxy('sms', facades.Sms) | ||||
| 
 | ||||
| #: Speech proxy to :class:`plyer.facades.STT` | ||||
| stt = Proxy('stt', facades.STT) | ||||
| 
 | ||||
| #: TTS proxy to :class:`plyer.facades.TTS` | ||||
| tts = Proxy('tts', facades.TTS) | ||||
| 
 | ||||
| #: UniqueID proxy to :class:`plyer.facades.UniqueID` | ||||
| uniqueid = Proxy('uniqueid', facades.UniqueID) | ||||
| 
 | ||||
| #: Vibrator proxy to :class:`plyer.facades.Vibrator` | ||||
| vibrator = Proxy('vibrator', facades.Vibrator) | ||||
| 
 | ||||
| #: Flash proxy to :class:`plyer.facades.Flash` | ||||
| flash = Proxy('flash', facades.Flash) | ||||
| 
 | ||||
| #: Wifi proxy to :class:`plyer.facades.Wifi` | ||||
| wifi = Proxy('wifi', facades.Wifi) | ||||
| 
 | ||||
| #: Temperature proxy to :class:`plyer.facades.Temperature` | ||||
| temperature = Proxy('temperature', facades.Temperature) | ||||
| 
 | ||||
| #: Humidity proxy to :class:`plyer.facades.Humidity` | ||||
| humidity = Proxy('humidity', facades.Humidity) | ||||
| #: SpatialOrientation proxy to :class:`plyer.facades.SpatialOrientation` | ||||
| spatialorientation = Proxy('spatialorientation', facades.SpatialOrientation) | ||||
| 
 | ||||
| #: Brightness proxy to :class:`plyer.facades.Brightness` | ||||
| brightness = Proxy('brightness', facades.Brightness) | ||||
| 
 | ||||
| #: StoragePath proxy to :class:`plyer.facades.StoragePath` | ||||
| storagepath = Proxy('storagepath', facades.StoragePath) | ||||
| 
 | ||||
| #: Bluetooth proxy to :class:`plyer.facades.Bluetooth` | ||||
| bluetooth = Proxy('bluetooth', facades.Bluetooth) | ||||
| 
 | ||||
| #: Processors proxy to :class:`plyer.facades.Processors` | ||||
| processors = Proxy('processors', facades.Processors) | ||||
| 
 | ||||
| #: Processors proxy to :class:`plyer.facades.CPU` | ||||
| cpu = Proxy('cpu', facades.CPU) | ||||
| 
 | ||||
| #: Screenshot proxy to :class:`plyer.facades.Screenshot` | ||||
| screenshot = Proxy('screenshot', facades.Screenshot) | ||||
| 
 | ||||
| #: devicename proxy to :class:`plyer.facades.DeviceName` | ||||
| devicename = Proxy('devicename', facades.DeviceName) | ||||
							
								
								
									
										51
									
								
								sbapp/plyer/facades/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								sbapp/plyer/facades/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| ''' | ||||
| Facades | ||||
| ======= | ||||
| 
 | ||||
| Interface of all the features available. | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| __all__ = ('Accelerometer', 'Audio', 'Barometer', 'Battery', 'Call', 'Camera', | ||||
|            'Compass', 'Email', 'FileChooser', 'GPS', 'Gravity', 'Gyroscope', | ||||
|            'IrBlaster', 'Light', 'Orientation', 'Notification', 'Proximity', | ||||
|            'Sms', 'TTS', 'UniqueID', 'Vibrator', 'Wifi', 'Flash', 'CPU', | ||||
|            'Temperature', 'Humidity', 'SpatialOrientation', 'Brightness', | ||||
|            'Processors', 'StoragePath', 'Keystore', 'Bluetooth', 'Screenshot', | ||||
|            'STT', 'DeviceName') | ||||
| 
 | ||||
| from plyer.facades.accelerometer import Accelerometer | ||||
| from plyer.facades.audio import Audio | ||||
| from plyer.facades.barometer import Barometer | ||||
| from plyer.facades.battery import Battery | ||||
| from plyer.facades.call import Call | ||||
| from plyer.facades.camera import Camera | ||||
| 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.gravity import Gravity | ||||
| from plyer.facades.gyroscope import Gyroscope | ||||
| from plyer.facades.irblaster import IrBlaster | ||||
| from plyer.facades.light import Light | ||||
| from plyer.facades.proximity import Proximity | ||||
| from plyer.facades.orientation import Orientation | ||||
| from plyer.facades.notification import Notification | ||||
| from plyer.facades.sms import Sms | ||||
| from plyer.facades.stt import STT | ||||
| from plyer.facades.tts import TTS | ||||
| from plyer.facades.uniqueid import UniqueID | ||||
| from plyer.facades.vibrator import Vibrator | ||||
| from plyer.facades.wifi import Wifi | ||||
| from plyer.facades.temperature import Temperature | ||||
| from plyer.facades.humidity import Humidity | ||||
| from plyer.facades.spatialorientation import SpatialOrientation | ||||
| from plyer.facades.brightness import Brightness | ||||
| from plyer.facades.keystore import Keystore | ||||
| from plyer.facades.storagepath import StoragePath | ||||
| from plyer.facades.bluetooth import Bluetooth | ||||
| from plyer.facades.processors import Processors | ||||
| from plyer.facades.cpu import CPU | ||||
| from plyer.facades.screenshot import Screenshot | ||||
| from plyer.facades.devicename import DeviceName | ||||
							
								
								
									
										75
									
								
								sbapp/plyer/facades/accelerometer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								sbapp/plyer/facades/accelerometer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| ''' | ||||
| Accelerometer | ||||
| ============ | ||||
| 
 | ||||
| The accelerometer is a motion sensor that detects the change (delta) in | ||||
| movement relative to the current device orientation, in three dimensions | ||||
| along the x, y, and z axis. | ||||
| 
 | ||||
| The :class:`Accelerometer` provides access to public methods to | ||||
| use accelerometer of your device. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To enable accelerometer:: | ||||
| 
 | ||||
|     >>> from plyer import accelerometer | ||||
|     >>> accelerometer.enable() | ||||
| 
 | ||||
| To disable accelerometer:: | ||||
| 
 | ||||
|     >>> accelerometer.disable() | ||||
| 
 | ||||
| To get the acceleration:: | ||||
| 
 | ||||
|     >>> accelerometer.acceleration | ||||
|     (-10.048464775085449, 6.825869083404541, 7.7260890007019043) | ||||
| 
 | ||||
| Supported Plaforms | ||||
| ------------------ | ||||
| Android, iOS, OS X, Linux | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Accelerometer: | ||||
|     ''' | ||||
|     Accelerometer facade. | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def acceleration(self): | ||||
|         ''' | ||||
|         Property that returns values of the current acceleration | ||||
|         sensors, as a (x, y, z) tuple. Returns (None, None, None) | ||||
|         if no data is currently available. | ||||
|         ''' | ||||
|         return self.get_acceleration() | ||||
| 
 | ||||
|     def enable(self): | ||||
|         ''' | ||||
|         Activate the accelerometer sensor. Throws an error if the | ||||
|         hardware is not available or not implemented on. | ||||
|         ''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         ''' | ||||
|         Disable the accelerometer sensor. | ||||
|         ''' | ||||
|         self._disable() | ||||
| 
 | ||||
|     def get_acceleration(self): | ||||
|         return self._get_acceleration() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_acceleration(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										103
									
								
								sbapp/plyer/facades/audio.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								sbapp/plyer/facades/audio.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| ''' | ||||
| Audio | ||||
| ===== | ||||
| 
 | ||||
| The :class:`Audio` is used for recording audio. | ||||
| 
 | ||||
| Default path for recording is set in platform implementation. | ||||
| 
 | ||||
| .. note:: | ||||
|         On Android the `RECORD_AUDIO`, `WAKE_LOCK` permissions are needed. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To get the file path:: | ||||
| 
 | ||||
|     >>> audio.file_path | ||||
|     '/sdcard/testrecorder.3gp' | ||||
| 
 | ||||
| To set the file path:: | ||||
| 
 | ||||
|     >>> import os | ||||
|     >>> current_list = os.listdir('.') | ||||
|     ['/sdcard/testrecorder.3gp', '/sdcard/testrecorder1.3gp', | ||||
|     '/sdcard/testrecorder2.3gp', '/sdcard/testrecorder3.3gp'] | ||||
|     >>> file_path = current_list[2] | ||||
|     >>> audio.file_path = file_path | ||||
| 
 | ||||
| To start recording:: | ||||
| 
 | ||||
|     >>> from plyer import audio | ||||
|     >>> audio.start() | ||||
| 
 | ||||
| To stop recording:: | ||||
| 
 | ||||
|     >>> audio.stop() | ||||
| 
 | ||||
| To play recording:: | ||||
| 
 | ||||
|     >>> audio.play() | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, Windows, macOS | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Audio: | ||||
|     ''' | ||||
|     Audio facade. | ||||
|     ''' | ||||
| 
 | ||||
|     state = 'ready' | ||||
|     _file_path = '' | ||||
| 
 | ||||
|     def __init__(self, file_path=None): | ||||
|         super().__init__() | ||||
|         self._file_path = file_path or self._file_path | ||||
| 
 | ||||
|     def start(self): | ||||
|         ''' | ||||
|         Start record. | ||||
|         ''' | ||||
|         self._start() | ||||
|         self.state = 'recording' | ||||
| 
 | ||||
|     def stop(self): | ||||
|         ''' | ||||
|         Stop record. | ||||
|         ''' | ||||
|         self._stop() | ||||
|         self.state = 'ready' | ||||
| 
 | ||||
|     def play(self): | ||||
|         ''' | ||||
|         Play current recording. | ||||
|         ''' | ||||
|         self._play() | ||||
|         self.state = 'playing' | ||||
| 
 | ||||
|     @property | ||||
|     def file_path(self): | ||||
|         return self._file_path | ||||
| 
 | ||||
|     @file_path.setter | ||||
|     def file_path(self, location): | ||||
|         ''' | ||||
|         Location of the recording. | ||||
|         ''' | ||||
|         assert isinstance(location, str), 'Location must be string or unicode' | ||||
|         self._file_path = location | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _start(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _stop(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _play(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										36
									
								
								sbapp/plyer/facades/barometer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								sbapp/plyer/facades/barometer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| class Barometer: | ||||
|     '''Barometer facade. | ||||
| 
 | ||||
|     Barometer sensor is used to measure the ambient air pressure in hPa. | ||||
| 
 | ||||
|     With method `enable` you can turn on pressure sensor and 'disable' | ||||
|     method stops the sensor. | ||||
| 
 | ||||
|     Use property `pressure` to get current air pressure in hPa. | ||||
| 
 | ||||
|     .. versionadded:: 1.2.5 | ||||
| 
 | ||||
|     Supported Platforms:: Android, iOS | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def pressure(self): | ||||
|         '''Current air pressure in hPa.''' | ||||
|         return self._get_pressure() | ||||
| 
 | ||||
|     def _get_pressure(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _enable(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def enable(self): | ||||
|         '''Enable barometer sensor.''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def _disable(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         '''Disable barometer sensor.''' | ||||
|         self._disable() | ||||
							
								
								
									
										54
									
								
								sbapp/plyer/facades/battery.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								sbapp/plyer/facades/battery.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| ''' | ||||
| Battery | ||||
| ======= | ||||
| 
 | ||||
| The :class:`Battery` provides information about the battery of your device. | ||||
| 
 | ||||
| .. note:: | ||||
|         On Android the `BATTERY_STATS` permission is needed. | ||||
| 
 | ||||
| Simple Example | ||||
| --------------- | ||||
| 
 | ||||
| To get battery status:: | ||||
| 
 | ||||
|     >>> from plyer import battery | ||||
|     >>> battery.status | ||||
|     {'percentage': 82.0, 'isCharging': False} | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS, Windows, OS X, Linux | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Battery: | ||||
|     ''' | ||||
|     Battery info facade. | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def status(self): | ||||
|         ''' | ||||
|         Property that contains a dict with the following fields: | ||||
|              * **isCharging** *(bool)*: Battery is charging | ||||
|              * **percentage** *(float)*: Battery charge remaining | ||||
| 
 | ||||
|             .. warning:: | ||||
|                 If any of the fields is not readable, it is set as | ||||
|                 None. | ||||
|         ''' | ||||
|         return self.get_state() | ||||
| 
 | ||||
|     def get_state(self): | ||||
|         ''' | ||||
|         Public method for filling battery.status via platform-specific | ||||
|         API in plyer.platforms. | ||||
|         ''' | ||||
|         return self._get_state() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _get_state(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										43
									
								
								sbapp/plyer/facades/bluetooth.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								sbapp/plyer/facades/bluetooth.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| '''Bluetooth facade. | ||||
| 
 | ||||
| Returns the following: | ||||
| 
 | ||||
| * Bluetooth info | ||||
| 
 | ||||
| Simple Example | ||||
| -------------- | ||||
| 
 | ||||
| To get the bluetooth status info:: | ||||
| todo: will be extended to get additional bluetooth info | ||||
| todo: will be extended to allow bluetooth connections etc. | ||||
| 
 | ||||
|     >>> from plyer import bluetooth | ||||
|     >>> bluetooth | ||||
|     'on' or 'off' | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, OS X | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Bluetooth: | ||||
|     ''' | ||||
|     Bluetooth facade. | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def info(self): | ||||
|         ''' | ||||
|         Property that returns the info (currently status) of the bluetooth. | ||||
|         ''' | ||||
|         return self.get_info() | ||||
| 
 | ||||
|     def get_info(self): | ||||
|         return self._get_info() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _get_info(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										58
									
								
								sbapp/plyer/facades/brightness.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										58
									
								
								sbapp/plyer/facades/brightness.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,58 @@ | ||||
| ''' | ||||
| Brightness | ||||
| ========== | ||||
| 
 | ||||
| This API helps you to control the brightness of your primary display screen. | ||||
| 
 | ||||
| The :class:`Brightness` provides access to public methods to control the | ||||
| brightness of screen. | ||||
| 
 | ||||
| NOTE:: For Android, make sure to add permission, WRITE_SETTINGS | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| To know the current brightness level of device:: | ||||
| 
 | ||||
|     >>> from plyer import brightness | ||||
|     >>> brightness.current_level() | ||||
| 
 | ||||
| To set the brightness level to half of maximum:: | ||||
| 
 | ||||
|     >>> from plyer import brightness | ||||
|     >>> brightness.set_level(50) | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS, Linux | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Brightness: | ||||
|     ''' | ||||
|     Brightness facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def current_level(self): | ||||
|         ''' | ||||
|         Know the current level of device's brightness. | ||||
|         ''' | ||||
|         return self._current_level() | ||||
| 
 | ||||
|     def set_level(self, level): | ||||
|         ''' | ||||
|         Adjust the brightness of the screen. | ||||
|         Minimum brightness level:: 1 | ||||
|         Maximum brightness level:: 100 | ||||
| 
 | ||||
|         :param level: New level of brightness between 1 and 100 | ||||
|         :type level: int | ||||
|         ''' | ||||
|         return self._set_level(level) | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _set_level(self, level): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _current_level(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										59
									
								
								sbapp/plyer/facades/call.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								sbapp/plyer/facades/call.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| ''' | ||||
| Call | ||||
| ==== | ||||
| 
 | ||||
| The :class:`Call` provides access to calling feature of your device. | ||||
| 
 | ||||
| .. note:: | ||||
|     - On Android your app needs the `CALL_PHONE` or `CALL_PRIVILEGED` | ||||
|     permission in order to make calls. | ||||
| 
 | ||||
|     - Dialing call feature in not supported yet in iOS devices. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To make call:: | ||||
| 
 | ||||
|     >>> from plyer import call | ||||
|     >>> tel = 9999222299 | ||||
|     >>> call.makecall(tel=tel) | ||||
| 
 | ||||
| To dial call:: | ||||
| 
 | ||||
|     >>> call.dialcall() | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Call: | ||||
|     ''' | ||||
|     Call facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def makecall(self, tel): | ||||
|         ''' | ||||
|         Make calls using your device. | ||||
| 
 | ||||
|         :param tel: The reciever | ||||
|         :type tel: number | ||||
|         ''' | ||||
|         self._makecall(tel=tel) | ||||
| 
 | ||||
|     def dialcall(self): | ||||
|         ''' | ||||
|         Opens dialing interface. | ||||
|         ''' | ||||
|         self._dialcall() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _makecall(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _dialcall(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										88
									
								
								sbapp/plyer/facades/camera.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								sbapp/plyer/facades/camera.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| ''' | ||||
| Camera | ||||
| ====== | ||||
| 
 | ||||
| The :class:`Camera` is to capture pictures and make videos. | ||||
| 
 | ||||
| .. note:: | ||||
|         - On Android the `CAMERA` , `WRITE_EXTERNAL_STORAGE`, | ||||
|           `READ_EXTERNAL_STORAGE` permissions are needed. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| Setup callback function. | ||||
| 
 | ||||
|     >>> from os.path import exists, join | ||||
|     >>> from plyer import camera | ||||
|     >>> def camera_callback(filepath): | ||||
|     >>>     if(exists(filepath)): | ||||
|     >>>         print "saved" | ||||
|     >>>     else: | ||||
|     >>>         print "unable to save." | ||||
|     >>> filepath = 'path/to/your/file' | ||||
|     >>> # e.g: filepath = join(App.get_running_app().user_data_dir, file_name) | ||||
| 
 | ||||
| To take picture:: | ||||
| 
 | ||||
|     >>> file_name = "test.jpg" | ||||
|     >>> camera.take_picture(filename=file_name, | ||||
|     >>>                     on_complete=camera_callback) | ||||
| 
 | ||||
| Ta take a video:: | ||||
| 
 | ||||
|     >>> file_name = "test.mp4" | ||||
|     >>> camera.take_video(filename=file_name, | ||||
|     >>>                   on_complete=camera_callback) | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Camera: | ||||
|     ''' | ||||
|     Camera facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def take_picture(self, filename, on_complete): | ||||
|         '''Ask the OS to capture a picture, and store it at filename. | ||||
| 
 | ||||
|         When the capture is done, on_complete will be called with the filename | ||||
|         as an argument. If the callback returns True, the filename will be | ||||
|         unlinked. | ||||
| 
 | ||||
|         :param filename: Name of the image file | ||||
|         :param on_complete: Callback that will be called when the operation is | ||||
|             done | ||||
| 
 | ||||
|         :type filename: str | ||||
|         :type on_complete: callable | ||||
|         ''' | ||||
|         self._take_picture(filename=filename, on_complete=on_complete) | ||||
| 
 | ||||
|     def take_video(self, filename, on_complete): | ||||
|         '''Ask the OS to capture a video, and store it at filename. | ||||
| 
 | ||||
|         When the capture is done, on_complete will be called with the filename | ||||
|         as an argument. If the callback returns True, the filename will be | ||||
|         unlinked. | ||||
| 
 | ||||
|         :param filename: Name of the video file | ||||
|         :param on_complete: Callback that will be called when the operation is | ||||
|             done | ||||
| 
 | ||||
|         :type filename: str | ||||
|         :type on_complete: callable | ||||
|         ''' | ||||
|         self._take_video(filename=filename, on_complete=on_complete) | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _take_picture(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _take_video(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										113
									
								
								sbapp/plyer/facades/compass.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								sbapp/plyer/facades/compass.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | ||||
| ''' | ||||
| Compass | ||||
| ======= | ||||
| 
 | ||||
| The :class:`Compass` provides access to public methods to use compass of your | ||||
| device. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To enable compass:: | ||||
| 
 | ||||
|     >>> from plyer import compass | ||||
|     >>> compass.enable() | ||||
| 
 | ||||
| To disable compass:: | ||||
| 
 | ||||
|     >>> compass.disable() | ||||
| 
 | ||||
| To get the field:: | ||||
| 
 | ||||
|     >>> compass.field() | ||||
|     (-23.721826553344727, -5.7114701271057129, -36.749668121337891) | ||||
| 
 | ||||
| To get the uncalibrated field along with iron bias estimation:: | ||||
| 
 | ||||
|     >>> compass.field_uncalib() | ||||
|     (a,b,c,x,y,z) | ||||
|     # a,b,c denote the Geomagnetic field strength | ||||
|     # (without hard iron calibration) along the three axes. | ||||
|     # x,y,z denote the Iron bias estimation along the three axes. | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Compass: | ||||
|     '''Compass facade. | ||||
| 
 | ||||
|     .. versionadded:: 1.2.0 | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def orientation(self): | ||||
|         ''' | ||||
|         WARNING:: This property is deprecated after API level 8. | ||||
|         Use `compass.field` instead. | ||||
| 
 | ||||
|         Property that returns values of the current compass | ||||
|         (magnetic field) sensors, as a (x, y, z) tuple. | ||||
|         Returns (None, None, None) if no data is currently available. | ||||
|         ''' | ||||
|         return self.get_orientation() | ||||
| 
 | ||||
|     @property | ||||
|     def field(self): | ||||
|         ''' | ||||
|         .. versionadded:: 1.3.1 | ||||
| 
 | ||||
|         Property that returns values of the current compass | ||||
|         (magnetic field) sensors, as a (x, y, z) tuple. | ||||
|         Returns (None, None, None) if no data is currently available. | ||||
|         ''' | ||||
|         return self.get_orientation() | ||||
| 
 | ||||
|     @property | ||||
|     def field_uncalib(self): | ||||
|         ''' | ||||
|         .. versionadded:: 1.3.1 | ||||
| 
 | ||||
|         Property that returns the current value of Uncalibrated Magnetic Field | ||||
|         (without hard iron calibration) along with the iron bias estimation | ||||
|         along the three axes. | ||||
|         ''' | ||||
|         return self.get_field_uncalib() | ||||
| 
 | ||||
|     def enable(self): | ||||
|         ''' | ||||
|         Activate the compass sensor. | ||||
|         ''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         ''' | ||||
|         Disable the compass sensor. | ||||
|         ''' | ||||
|         self._disable() | ||||
| 
 | ||||
|     def get_orientation(self): | ||||
|         return self._get_orientation() | ||||
| 
 | ||||
|     def get_field_uncalib(self): | ||||
|         ''' | ||||
|         .. versionadded:: 1.3.1 | ||||
|         ''' | ||||
|         return self._get_field_uncalib() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_field_uncalib(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										92
									
								
								sbapp/plyer/facades/cpu.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								sbapp/plyer/facades/cpu.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | ||||
| ''' | ||||
| CPU | ||||
| === | ||||
| 
 | ||||
| Simple Example | ||||
| --------------- | ||||
| 
 | ||||
| To get CPU count:: | ||||
|     >>> from plyer import cpu | ||||
|     >>> # 1 socket, 1 core per socket, 2 threads per core | ||||
|     >>> cpu.sockets   # 1 CPU socket (or slot) | ||||
|     1 | ||||
|     >>> cpu.physical  # 1 CPU socket * 1 core per socket | ||||
|     1 | ||||
|     >>> cpu.logical   # 1 CPU socket * 1 core per socket * 2 threads per core | ||||
|     2 | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| 
 | ||||
| MacOS | ||||
| Linux | ||||
| Windows | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class CPU: | ||||
|     ''' | ||||
|     Facade providing info about sockets, physical and logical | ||||
|     number of processors. | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def sockets(self): | ||||
|         ''' | ||||
|         Property that contains the count of CPU sockets. | ||||
|         ''' | ||||
|         return self._sockets() | ||||
| 
 | ||||
|     @property | ||||
|     def physical(self): | ||||
|         ''' | ||||
|         Property that contains the total number of physical cores | ||||
|         (max core count) in the system. | ||||
| 
 | ||||
|         .. note:: `sockets * cores per socket` | ||||
|         ''' | ||||
|         return self._physical() | ||||
| 
 | ||||
|     @property | ||||
|     def logical(self): | ||||
|         ''' | ||||
|         Property that contains the total number of logical cores | ||||
|         (max thread count) in the system. | ||||
| 
 | ||||
|         .. note:: `sockets * cores per socket * threads per core` | ||||
|         ''' | ||||
|         return self._logical() | ||||
| 
 | ||||
|     @property | ||||
|     def cache(self): | ||||
|         ''' | ||||
|         Property that contains the count of L1, L2, L3 caches in the system | ||||
|         as a dictionary `{'L1': int, 'L2': int, 'L3': int}`. | ||||
|         ''' | ||||
|         return self._cache() | ||||
| 
 | ||||
|     @property | ||||
|     def numa(self): | ||||
|         ''' | ||||
|         Property that contains the count of NUMA nodes in the system. | ||||
| 
 | ||||
|         .. note:: https://en.wikipedia.org/wiki/Non-uniform_memory_access | ||||
|         ''' | ||||
|         return self._numa() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _sockets(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _physical(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _logical(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _cache(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _numa(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										44
									
								
								sbapp/plyer/facades/devicename.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								sbapp/plyer/facades/devicename.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| '''DeviceName facade. | ||||
| 
 | ||||
| Returns the following depending on the platform: | ||||
| 
 | ||||
| * **Android**: Android Device name | ||||
| * **Linux**: Hostname of the machine | ||||
| * **OS X**: Hostname of the machine | ||||
| * **Windows**: Hostname of the machine | ||||
| 
 | ||||
| Simple Example | ||||
| -------------- | ||||
| 
 | ||||
| To get the Device Name:: | ||||
| 
 | ||||
|     >>> from plyer import devicename | ||||
|     >>> devicename.device_name | ||||
|     'Oneplus 3' | ||||
| 
 | ||||
| .. versionadded:: 2.1.0 | ||||
|     - first release | ||||
| 
 | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, Windows, OS X, Linux | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class DeviceName: | ||||
|     ''' | ||||
|     DeviceName facade. | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def device_name(self): | ||||
|         ''' | ||||
|         Property that returns the device name of the platform. | ||||
|         ''' | ||||
|         return self._get_device_name() | ||||
| 
 | ||||
|     # private | ||||
|     def _get_device_name(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										58
									
								
								sbapp/plyer/facades/email.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								sbapp/plyer/facades/email.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| ''' | ||||
| Email | ||||
| ===== | ||||
| 
 | ||||
| The :class:`Email` provides access to public methods to use email of your | ||||
| device. | ||||
| 
 | ||||
| .. note:: | ||||
|     On Android `INTERNET` permission is needed. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To send an e-mail:: | ||||
| 
 | ||||
|     >>> from plyer import email | ||||
|     >>> recipient = 'abc@gmail.com' | ||||
|     >>> subject = 'Hi' | ||||
|     >>> text = 'This is an example.' | ||||
|     >>> create_chooser = False | ||||
|     >>> email.send(recipient=recipient, subject=subject, text=text, | ||||
|                    create_chooser=create_chooser) | ||||
| 
 | ||||
|     >>> # opens email interface where user can change the content. | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS, Windows, OS X, Linux | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Email: | ||||
|     ''' | ||||
|     Email facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def send(self, recipient=None, subject=None, text=None, | ||||
|              create_chooser=None): | ||||
|         ''' | ||||
|         Open an email client message send window, prepopulated with the | ||||
|         given arguments. | ||||
| 
 | ||||
|         :param recipient: Recipient of the message (str) | ||||
|         :param subject: Subject of the message (str) | ||||
|         :param text: Main body of the message (str) | ||||
|         :param create_chooser: Whether to display a program chooser to | ||||
|                                handle the message (bool) | ||||
| 
 | ||||
|         .. note:: create_chooser is only supported on Android | ||||
|         ''' | ||||
|         self._send(recipient=recipient, subject=subject, text=text, | ||||
|                    create_chooser=create_chooser) | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _send(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										74
									
								
								sbapp/plyer/facades/filechooser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								sbapp/plyer/facades/filechooser.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | ||||
| ''' | ||||
| Native filechooser dialog facade. | ||||
| ================================= | ||||
| 
 | ||||
| open_file, save_file and choose_dir accept a number of arguments | ||||
| listed below. They return either a list of paths (normally | ||||
| absolute), or None if no file was selected or the operation was | ||||
| canceled and no result is available. | ||||
| 
 | ||||
| Arguments: | ||||
|     * **path** *(string or None)*: a path that will be selected | ||||
|         by default, or None | ||||
|     * **multiple** *(bool)*: True if you want the dialog to | ||||
|         allow multiple file selection. (Note: Windows doesn't | ||||
|         support multiple directory selection) | ||||
|     * **filters** *(iterable)*: either a list of wildcard patterns | ||||
|         or of sequences that contain the name of the filter and any | ||||
|         number of wildcards that will be grouped under that name | ||||
|         (e.g. [["Music", "*mp3", "*ogg", "*aac"], "*jpg", "*py"]) | ||||
|     * **preview** *(bool)*: True if you want the file chooser to | ||||
|         show a preview of the selected file, if supported by the | ||||
|         back-end. | ||||
|     * **title** *(string or None)*: The title of the file chooser | ||||
|         window, or None for the default title. | ||||
|     * **icon** *(string or None)*: Path to the icon of the file | ||||
|         chooser window (where supported), or None for the back-end's | ||||
|         default. | ||||
|     * **show_hidden** *(bool)*: Force showing hidden files (currently | ||||
|         supported only on Windows) | ||||
|     * **on_selection** *(func)*: Callback for fetching the selection. | ||||
| 
 | ||||
| Important: these methods will return only after user interaction. | ||||
| Use threads or you will stop the mainloop if your app has one. | ||||
| 
 | ||||
| .. versionchanged:: 1.4.0 | ||||
|     Added Android implementation for open_file() | ||||
|     Added ``on_selection`` kwarg for callback function | ||||
| 
 | ||||
| Supported Plaforms | ||||
| ------------------ | ||||
| Android, iOS, macOS, Linux, Windows | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class FileChooser: | ||||
|     ''' | ||||
|     File Chooser facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def open_file(self, *args, **kwargs): | ||||
|         """ | ||||
|         Open the file chooser in "open" mode. | ||||
|         """ | ||||
|         return self._file_selection_dialog(mode="open", *args, **kwargs) | ||||
| 
 | ||||
|     def save_file(self, *args, **kwargs): | ||||
|         """ | ||||
|         Open the file chooser in "save" mode. Confirmation will be asked | ||||
|         when a file with the same name already exists. | ||||
|         """ | ||||
|         return self._file_selection_dialog(mode="save", *args, **kwargs) | ||||
| 
 | ||||
|     def choose_dir(self, *args, **kwargs): | ||||
|         """ | ||||
|         Open the directory chooser. Note that on Windows this is very | ||||
|         limited. Consider writing your own chooser if you target that | ||||
|         platform and are planning on using unsupported features. | ||||
|         """ | ||||
|         return self._file_selection_dialog(mode="dir", *args, **kwargs) | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _file_selection_dialog(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										77
									
								
								sbapp/plyer/facades/flash.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								sbapp/plyer/facades/flash.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| # coding=utf-8 | ||||
| ''' | ||||
| Flash | ||||
| ===== | ||||
| 
 | ||||
| The :class:`Flash` provides access to public methods to use flash of your | ||||
| device. | ||||
| 
 | ||||
| .. note:: | ||||
|     In android you need CAMERA, FLASHLIGHT permissions | ||||
|     to access flash. | ||||
| 
 | ||||
| .. versionadded:: 1.2.5 | ||||
| 
 | ||||
| This can be used to activate the flash of your camera on | ||||
| Android and iOS. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To turn on flash:: | ||||
| 
 | ||||
|     >>> from plyer import flash | ||||
|     >>> flash.on() | ||||
| 
 | ||||
| To turn off flash:: | ||||
| 
 | ||||
|     >>> flash.off() | ||||
| 
 | ||||
| To release flash:: | ||||
| 
 | ||||
|     >>> flash.release() | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Flash: | ||||
|     """ | ||||
|     Flash facade. | ||||
|     """ | ||||
| 
 | ||||
|     def on(self): | ||||
|         """ | ||||
|         Activate the flash | ||||
|         """ | ||||
|         self._on() | ||||
| 
 | ||||
|     def off(self): | ||||
|         """ | ||||
|         Deactiavte the flash | ||||
|         """ | ||||
|         self._off() | ||||
| 
 | ||||
|     def release(self): | ||||
|         """ | ||||
|         Release any access to the Flash / Camera. | ||||
|         Call this when you're done using the Flash. | ||||
|         This will release the Camera, and stop any process. | ||||
| 
 | ||||
|         Next call to `_on` will reactivate it. | ||||
|         """ | ||||
|         self._release() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _on(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _off(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _release(self): | ||||
|         pass | ||||
							
								
								
									
										96
									
								
								sbapp/plyer/facades/gps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								sbapp/plyer/facades/gps.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | ||||
| ''' | ||||
| GPS | ||||
| ==== | ||||
| 
 | ||||
| .. versionadded:: 1.1 | ||||
| 
 | ||||
| .. note:: | ||||
|     On Android `INTERNET`, `ACCESS_FINE_LOCATION`, `ACCESS_COARSE_LOCATION` | ||||
|     permissions are needed. | ||||
| 
 | ||||
| 
 | ||||
| .. note:: | ||||
|     On iOS `NSLocationWhenInUseUsageDescription` key is required for app to | ||||
|     display geolocation usage permission prompt. Key can be added in Xcode | ||||
|     target `info` section or in ``Resources/<YourApp>-info.plist``. | ||||
|     App background mode (`on_pause`) also must be supported. | ||||
| 
 | ||||
| You need to set a `on_location` callback with the :meth:`configure` method. | ||||
| This callback will receive a couple of keywords / values, that might be | ||||
| different depending of their availability on the targeted platform. | ||||
| Lat and lon are always available. | ||||
| 
 | ||||
| - lat: latitude of the last location, in degrees | ||||
| - lon: longitude of the last location, in degrees | ||||
| - speed: speed of the user, in meters/second over ground | ||||
| - bearing: bearing in degrees | ||||
| - altitude: altitude in meters above the sea level | ||||
| 
 | ||||
| Here is an example of the usage of gps:: | ||||
| 
 | ||||
|     from plyer import gps | ||||
| 
 | ||||
|     def print_locations(**kwargs): | ||||
|         print 'lat: {lat}, lon: {lon}'.format(**kwargs) | ||||
| 
 | ||||
|     gps.configure(on_location=print_locations) | ||||
|     gps.start() | ||||
|     # later | ||||
|     gps.stop() | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class GPS: | ||||
|     ''' | ||||
|     GPS facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def configure(self, on_location, on_status=None): | ||||
|         ''' | ||||
|         Configure the GPS object. This method should be called before | ||||
|         :meth:`start`. | ||||
| 
 | ||||
|         :param on_location: Function to call when receiving a new location | ||||
|         :param on_status: Function to call when a status message is received | ||||
|         :type on_location: callable, multiples keys/value will be passed. | ||||
|         :type on_status: callable, args are "message-type", "status" | ||||
| 
 | ||||
|         .. warning:: | ||||
| 
 | ||||
|             The `on_location` and `on_status` callables might be called from | ||||
|             another thread than the thread used for creating the GPS object. | ||||
|         ''' | ||||
|         self.on_location = on_location | ||||
|         self.on_status = on_status | ||||
|         self._configure() | ||||
| 
 | ||||
|     def start(self, minTime=1000, minDistance=1): | ||||
|         ''' | ||||
|         Start the GPS location updates. | ||||
|         Expects 2 parameters: | ||||
|             minTime: milliseconds.  (float) | ||||
|             minDistance: meters. (float) | ||||
|         ''' | ||||
|         self._start(minTime=minTime, minDistance=minDistance) | ||||
| 
 | ||||
|     def stop(self): | ||||
|         ''' | ||||
|         Stop the GPS location updates. | ||||
|         ''' | ||||
|         self._stop() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _configure(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _start(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _stop(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										38
									
								
								sbapp/plyer/facades/gravity.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								sbapp/plyer/facades/gravity.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| class Gravity: | ||||
|     '''Gravity facade. | ||||
| 
 | ||||
|     .. versionadded:: 1.2.5 | ||||
| 
 | ||||
|     Supported Platforms:: Android | ||||
| 
 | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def gravity(self): | ||||
|         '''Property that returns values of the current gravity force | ||||
|         as a (x, y, z) tuple. Returns (None, None, None) | ||||
|         if no data is currently available. | ||||
|         ''' | ||||
|         return self._get_gravity() | ||||
| 
 | ||||
|     def enable(self): | ||||
|         '''Activate the gravity sensor. Throws an error if the | ||||
|         hardware is not available or not implemented on. | ||||
|         ''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         '''Disable the gravity sensor. | ||||
|         ''' | ||||
|         self._disable() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_gravity(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										126
									
								
								sbapp/plyer/facades/gyroscope.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								sbapp/plyer/facades/gyroscope.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,126 @@ | ||||
| ''' | ||||
| Gyroscope | ||||
| ============ | ||||
| 
 | ||||
| The gyroscope measures the rate of rotation around a device's x, y, | ||||
| and z axis. | ||||
| 
 | ||||
| The :class:`Gyroscope` provides access to public methods to | ||||
| use gyroscope of your device. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To enable gyroscope:: | ||||
| 
 | ||||
|     >>> from plyer import gyroscope | ||||
|     >>> gyroscope.enable() | ||||
| 
 | ||||
| To disable gyroscope:: | ||||
| 
 | ||||
|     >>> gyroscope.disable() | ||||
| 
 | ||||
| To get the rate of rotation along the three axes:: | ||||
| 
 | ||||
|     >>> gyroscope.rotation | ||||
|     (-0.0034587313421070576, -0.0073830625042319298, 0.0046892408281564713) | ||||
| 
 | ||||
| To get the uncalibrated rate of rotation along the three axes along with the | ||||
| drift compensation:: | ||||
| 
 | ||||
|     >>> gyroscope.rotation_uncalib | ||||
|     () | ||||
|     where the first three values show the rate of rotation w/o drift | ||||
|     compensation and the last three show the estimated drift along the three | ||||
|     axes. | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Gyroscope: | ||||
|     ''' | ||||
|     Gyroscope facade. | ||||
| 
 | ||||
|     .. versionadded:: 1.3.1 | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def rotation(self): | ||||
|         ''' | ||||
|         Property that returns the rate of rotation around the device's local | ||||
|         X, Y and Z axis. | ||||
| 
 | ||||
|         Along x-axis: angular speed around the X axis | ||||
|         Along y-axis: angular speed around the Y axis | ||||
|         Along z-axis: angular speed around the Z axis | ||||
| 
 | ||||
|         Returns (None, None, None) if no data is currently available. | ||||
|         ''' | ||||
|         return self.get_orientation() | ||||
| 
 | ||||
|     @property | ||||
|     def rotation_uncalib(self): | ||||
|         ''' | ||||
|         Property that returns the current rate of rotation around the X, Y and | ||||
|         Z axis. An estimation of the drift on each axis is reported as well. | ||||
| 
 | ||||
|         Along x-axis: angular speed (w/o drift compensation) around the X axis | ||||
|         Along y-axis: angular speed (w/o drift compensation) around the Y axis | ||||
|         Along z-axis: angular speed (w/o drift compensation) around the Z axis | ||||
| 
 | ||||
|         Along x-axis: estimated drift around X axis | ||||
|         Along y-axis: estimated drift around Y axis | ||||
|         Along z-axis: estimated drift around Z axis | ||||
| 
 | ||||
|         Returns (None, None, None, None, None, None) if no data is currently | ||||
|         available. | ||||
|         ''' | ||||
|         return self.get_rotation_uncalib() | ||||
| 
 | ||||
|     @property | ||||
|     def orientation(self): | ||||
|         ''' | ||||
|         WARNING:: This property is deprecated after API Level 8. | ||||
|         Use `gyroscope.rotation` instead. | ||||
| 
 | ||||
|         Property that returns values of the current Gyroscope sensors, as | ||||
|         a (x, y, z) tuple. Returns (None, None, None) if no data is currently | ||||
|         available. | ||||
|         ''' | ||||
|         return self.get_orientation() | ||||
| 
 | ||||
|     def enable(self): | ||||
|         ''' | ||||
|         Activate the Gyroscope sensor. | ||||
|         ''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         ''' | ||||
|         Disable the Gyroscope sensor. | ||||
|         ''' | ||||
|         self._disable() | ||||
| 
 | ||||
|     def get_orientation(self): | ||||
|         return self._get_orientation() | ||||
| 
 | ||||
|     def get_rotation_uncalib(self): | ||||
|         return self._get_rotation_uncalib() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_rotation_uncalib(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										34
									
								
								sbapp/plyer/facades/humidity.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								sbapp/plyer/facades/humidity.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| class Humidity: | ||||
|     '''Humidity facade. | ||||
|        Humidity sensor returns value of humidity. | ||||
|        With method `enable` you can turn on Humidity sensor and | ||||
|        'disable' method stops the sensor. | ||||
|        Use property `tell` to get humidity value. | ||||
|         | ||||
|        Supported Platforms | ||||
|        ------------------- | ||||
|        Android | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def tell(self): | ||||
|         '''Current humidity''' | ||||
|         return self._get_humidity() | ||||
| 
 | ||||
|     def enable(self): | ||||
|         '''Enable Humidity sensor.''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         '''Disable Humidity sensor.''' | ||||
|         self._disable() | ||||
| 
 | ||||
|     # private | ||||
|     def _get_humidity(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _enable(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _disable(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										104
									
								
								sbapp/plyer/facades/irblaster.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								sbapp/plyer/facades/irblaster.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | ||||
| ''' | ||||
| IrBlaster | ||||
| ============ | ||||
| 
 | ||||
| The :class:`IrBlaster` provides access to public methods by which your device | ||||
| can act as a remote and could be used to control your TV, AC, Music Player, | ||||
| Projectors, Set top box or anything that can be controlled by a remote. | ||||
| 
 | ||||
| .. note:: | ||||
|     - On Android your app needs the TRANSMIT_IR permission which allows an | ||||
|     application to use the device's IR transmitter, If available. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To get transmit an IR sequence:: | ||||
| 
 | ||||
|     >>> from plyer import irblaster | ||||
|     >>> irblaster.transmit(frequency, pattern, mode) | ||||
| 
 | ||||
| To get frequencies:: | ||||
| 
 | ||||
|     >>> irblaster.frequencies | ||||
| 
 | ||||
| To check if IrBlaster exists:: | ||||
| 
 | ||||
|     >>> irblaster.exists() | ||||
|     True/False | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class IrBlaster: | ||||
|     ''' | ||||
|     Infrared blaster facade. | ||||
|     ''' | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def periods_to_microseconds(frequency, pattern): | ||||
|         ''' | ||||
|         Convert a pattern from period counts to microseconds. | ||||
|         ''' | ||||
|         period = 1000000. / frequency | ||||
|         return [period * x for x in pattern] | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def microseconds_to_periods(frequency, pattern): | ||||
|         ''' | ||||
|         Convert a pattern from microseconds to period counts. | ||||
|         ''' | ||||
|         period = 1000000. / frequency | ||||
|         return [x / period for x in pattern] | ||||
| 
 | ||||
|     @property | ||||
|     def frequencies(self): | ||||
|         ''' | ||||
|         Property which contains a list of frequency ranges | ||||
|            supported by the device in the form: | ||||
| 
 | ||||
|            [(from1, to1), | ||||
|             (from2, to2), | ||||
|             ... | ||||
|             (fromN, toN)] | ||||
|         ''' | ||||
|         return self.get_frequencies() | ||||
| 
 | ||||
|     def get_frequencies(self): | ||||
|         return self._get_frequencies() | ||||
| 
 | ||||
|     def transmit(self, frequency, pattern, mode='period'): | ||||
|         ''' | ||||
|         Transmit an IR sequence. | ||||
| 
 | ||||
|         :parameters: | ||||
|             `frequency`: int | ||||
|                 Carrier frequency for the IR transmission. | ||||
|             `pattern`: list[int] | ||||
|                 Burst pair pattern to transmit. | ||||
|             `mode`: str, defaults to 'period' | ||||
|                 Specifies the format of the pattern values. | ||||
|                 Can be 'period' or 'microseconds'. | ||||
|         ''' | ||||
|         return self._transmit(frequency, pattern, mode) | ||||
| 
 | ||||
|     def exists(self): | ||||
|         ''' | ||||
|         Check if the device has an infrared emitter. | ||||
|         ''' | ||||
|         return self._exists() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _get_frequencies(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _transmit(self, frequency, pattern, mode): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _exists(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										32
									
								
								sbapp/plyer/facades/keystore.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								sbapp/plyer/facades/keystore.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| ''' | ||||
| Keystore | ||||
| ======= | ||||
| The :class:`Keystore` provides a mechanism for securing/storing | ||||
| cryptographic keys (such as user credentials) in a container. | ||||
| Typically needed to support authentication APIs such as OAuth2 | ||||
| .. note:: | ||||
|     Typically needed to support authentication APIs such as OAuth2 | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS, Windows, OS X, Linux | ||||
| --------------- | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Keystore: | ||||
|     ''' | ||||
|     Keystore facade | ||||
|     ''' | ||||
| 
 | ||||
|     def set_key(self, servicename, key, value, **kwargs): | ||||
|         self._set_key(servicename, key, value, **kwargs) | ||||
| 
 | ||||
|     def _set_key(self, servicename, key, value, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def get_key(self, servicename, key, **kwargs): | ||||
|         return self._get_key(servicename, key) | ||||
| 
 | ||||
|     def _get_key(self, servicename, key, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										39
									
								
								sbapp/plyer/facades/light.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								sbapp/plyer/facades/light.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| class Light: | ||||
|     '''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. | ||||
| 
 | ||||
|     .. versionadded:: 1.2.5 | ||||
| 
 | ||||
|     Supported Platforms:: Android | ||||
|     ''' | ||||
| 
 | ||||
|     @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() | ||||
							
								
								
									
										93
									
								
								sbapp/plyer/facades/notification.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								sbapp/plyer/facades/notification.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| ''' | ||||
| Notification | ||||
| ============ | ||||
| 
 | ||||
| The :class:`Notification` provides access to public methods to create | ||||
| notifications. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To send notification:: | ||||
| 
 | ||||
|     >>> from plyer import notification | ||||
|     >>> title = 'plyer' | ||||
|     >>> message = 'This is an example.' | ||||
|     >>> notification.notify(title=title, message=message) | ||||
| 
 | ||||
| Android toast notification:: | ||||
| 
 | ||||
|     >>> from plyer import notification | ||||
|     >>> notification.notify(message='hello', toast=True) | ||||
| 
 | ||||
| Android simple notification:: | ||||
| 
 | ||||
|     >>> from plyer import notification | ||||
|     >>> notification.notify(message='hello', toast=True) | ||||
| 
 | ||||
| Notification with custom icon:: | ||||
| 
 | ||||
|     >>> from plyer import notification | ||||
|     >>> notification.notify(title='title', message='hello', app_icon=<path>) | ||||
| 
 | ||||
| .. versionadded:: 1.0.0 | ||||
| 
 | ||||
| .. versionadded:: 1.4.0 | ||||
|    Add implementation of primitive Android popup-like notification (toast) | ||||
| 
 | ||||
| .. versionchanged:: 1.4.0 | ||||
|    Android implementation now supports custom icons for notifications. | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Notification: | ||||
|     ''' | ||||
|     Notification facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def notify(self, title='', message='', app_name='', app_icon='', notification_icon=None, | ||||
|                timeout=10, ticker='', toast=False, hints={}): | ||||
|         ''' | ||||
|         Send a notification. | ||||
| 
 | ||||
|         :param title: Title of the notification | ||||
|         :param message: Message of the notification | ||||
|         :param app_name: Name of the app launching this notification | ||||
|         :param app_icon: Icon to be displayed along with the message | ||||
|         :param timeout: time to display the message for, defaults to 10 | ||||
|         :param ticker: text to display on status bar as the notification | ||||
|                        arrives | ||||
|         :param toast: simple Android message instead of full notification | ||||
|         :param hints: Optional hints that can be used to pass along extra | ||||
|                       instructions on Linux. | ||||
|                       (See https://specifications.freedesktop.org/notification-spec/latest/ar01s08.html)  # noqa: E501 | ||||
| 
 | ||||
|         :type title: str | ||||
|         :type message: str | ||||
|         :type app_name: str | ||||
|         :type app_icon: str | ||||
|         :type timeout: int | ||||
|         :type ticker: str | ||||
|         :type toast: bool | ||||
|         :type hints: dict | ||||
| 
 | ||||
|         .. note:: | ||||
|            When called on Windows, ``app_icon`` has to be a path to | ||||
|            a file in .ICO format. | ||||
| 
 | ||||
|         .. versionadded:: 1.0.0 | ||||
| 
 | ||||
|         .. versionchanged:: 1.4.0 | ||||
|            Add 'toast' keyword argument | ||||
|         ''' | ||||
| 
 | ||||
|         self._notify( | ||||
|             title=title, message=message, | ||||
|             app_icon=app_icon, app_name=app_name, notification_icon=notification_icon, | ||||
|             timeout=timeout, ticker=ticker, toast=toast, hints=hints | ||||
|         ) | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _notify(self, **kwargs): | ||||
|         raise NotImplementedError("No usable implementation found!") | ||||
							
								
								
									
										81
									
								
								sbapp/plyer/facades/orientation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								sbapp/plyer/facades/orientation.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | ||||
| ''' | ||||
| Orientation | ||||
| ========== | ||||
| 
 | ||||
| The :class:`Orientation` provides access to public methods to set orientation | ||||
| of your device. | ||||
| 
 | ||||
| .. note:: | ||||
|     These settings are generally guidelines, the operating | ||||
|     system may choose to ignore them, or they may be overridden by | ||||
|     other system components. | ||||
| 
 | ||||
| .. versionadded:: 1.2.4 | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To set landscape:: | ||||
| 
 | ||||
|     >>> from plyer import orientation | ||||
|     >>> orientation.set_landscape() | ||||
| 
 | ||||
| To set portrait:: | ||||
| 
 | ||||
|     >>> orientation.set_portrait() | ||||
| 
 | ||||
| To set sensor:: | ||||
| 
 | ||||
|     >>> orientation.set_sensor() | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Orientation: | ||||
|     ''' | ||||
|     Orientation facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def set_landscape(self, reverse=False): | ||||
|         ''' | ||||
|         Rotate the app to a landscape orientation. | ||||
| 
 | ||||
|         :param reverse: If True, uses the opposite of the natural | ||||
|                         orientation. | ||||
|         ''' | ||||
|         self._set_landscape(reverse=reverse) | ||||
| 
 | ||||
|     def set_portrait(self, reverse=False): | ||||
|         ''' | ||||
|         Rotate the app to a portrait orientation. | ||||
| 
 | ||||
|         :param reverse: If True, uses the opposite of the natural | ||||
|                         orientation. | ||||
|         ''' | ||||
|         self._set_portrait(reverse=reverse) | ||||
| 
 | ||||
|     def set_sensor(self, mode='any'): | ||||
|         ''' | ||||
|         Rotate freely following sensor information from the device. | ||||
| 
 | ||||
|         :param mode: The rotation mode, should be one of 'any' (rotate | ||||
|                      to any orientation), 'landscape' (choose nearest | ||||
|                      landscape mode) or 'portrait' (choose nearest | ||||
|                      portrait mode). Defaults to 'any'. | ||||
|         ''' | ||||
|         self._set_sensor(mode=mode) | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _set_landscape(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _set_portrait(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _set_sensor(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										42
									
								
								sbapp/plyer/facades/processors.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								sbapp/plyer/facades/processors.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| ''' | ||||
| Number of Processors | ||||
| ======= | ||||
| The :class:`Processors` provides a information on the number of | ||||
| processors in a system | ||||
| .. note:: | ||||
|     Deprecated in favor of `cpu` | ||||
| 
 | ||||
| Simple Example | ||||
| --------------- | ||||
| To get processors status:: | ||||
|     >>> from plyer import processors | ||||
|     >>> processors.status | ||||
|     {'Number_of_Processors': '4'} | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Linux | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Processors: | ||||
|     ''' | ||||
|     Number of Processors info facade. | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def status(self): | ||||
|         ''' | ||||
|         Property that contains a dict with the following fields: | ||||
|              * **Number_of_Processors** *(int)*: Number of Processors in | ||||
|              the system | ||||
|             .. warning:: | ||||
|                 If any of the fields is not readable, it is set as | ||||
|                 None. | ||||
|         ''' | ||||
|         return self.get_state() | ||||
| 
 | ||||
|     def get_state(self): | ||||
|         return self._get_state() | ||||
| 
 | ||||
|     def _get_state(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										44
									
								
								sbapp/plyer/facades/proximity.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								sbapp/plyer/facades/proximity.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| class Proximity: | ||||
|     '''Proximity facade. | ||||
| 
 | ||||
|     The proximity sensor is commonly used to determine distance whether | ||||
|     phone is close to your head. Commonly is used when you have a call | ||||
|     and you stick your phone with your head. Then screen of phone turns off. | ||||
| 
 | ||||
|     Use method `enable` to turn on proximity sensor and method `disable` for | ||||
|     turn off. | ||||
| 
 | ||||
|     To check if some object (or your head) is near sensor check values from | ||||
|     property `proximity`. It returns `True` when object is close. | ||||
| 
 | ||||
|     .. versionadded:: 1.2.5 | ||||
| 
 | ||||
|     Supported Platforms::Android | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def proximity(self): | ||||
|         '''Return True or False depending if there is an object or not. | ||||
| 
 | ||||
|         :return: True if there is an object. Otherwise False. | ||||
|         ''' | ||||
|         return self._get_proximity() | ||||
| 
 | ||||
|     def _enable(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def enable(self): | ||||
|         '''Enable the proximity sensor. | ||||
|         ''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def _disable(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         '''Disable the proximity sensor. | ||||
|         ''' | ||||
|         self._disable() | ||||
| 
 | ||||
|     def _get_proximity(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										57
									
								
								sbapp/plyer/facades/screenshot.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								sbapp/plyer/facades/screenshot.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| ''' | ||||
| Screenshot | ||||
| ========== | ||||
| 
 | ||||
| The :class:`Screenshot` is used for capturing a digital image of what | ||||
| is currently visible on the monitor. | ||||
| 
 | ||||
| The default path for taking screenshot is set in each platform implementation. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To get the file path:: | ||||
| 
 | ||||
|     >>> screenshot.file_path | ||||
|     '/sdcard/test.jpg' | ||||
| 
 | ||||
| To set the file path:: | ||||
| 
 | ||||
|     >>> screenshot.file_path = '/Users/OSXUser/Pictures/screenshot.png' | ||||
| 
 | ||||
| To take screenshot:: | ||||
| 
 | ||||
|     >>> from plyer import screenshot | ||||
|     >>> screenshot.capture() | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Screenshot: | ||||
|     ''' | ||||
|     Screenshot facade. | ||||
|     ''' | ||||
| 
 | ||||
|     _file_path = '' | ||||
| 
 | ||||
|     def __init__(self, file_path=None): | ||||
|         self._file_path = file_path | ||||
| 
 | ||||
|     def capture(self): | ||||
|         self._capture() | ||||
| 
 | ||||
|     @property | ||||
|     def file_path(self): | ||||
|         return self._file_path | ||||
| 
 | ||||
|     @file_path.setter | ||||
|     def file_path(self, location): | ||||
|         ''' | ||||
|         Location of the screenshot. | ||||
|         ''' | ||||
| 
 | ||||
|         self._file_path = location | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _capture(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										51
									
								
								sbapp/plyer/facades/sms.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								sbapp/plyer/facades/sms.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| ''' | ||||
| Sms | ||||
| ==== | ||||
| 
 | ||||
| The :class:`Sms` provides access to sending Sms from your device. | ||||
| 
 | ||||
| .. note:: | ||||
| 
 | ||||
|     On Android your app needs the SEND_SMS permission in order to | ||||
|     send sms messages. | ||||
| 
 | ||||
| .. versionadded:: 1.2.0 | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To send sms:: | ||||
| 
 | ||||
|     >>> from plyer import sms | ||||
|     >>> recipient = 9999222299 | ||||
|     >>> message = 'This is an example.' | ||||
|     >>> sms.send(recipient=recipient, message=message) | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Sms: | ||||
|     ''' | ||||
|     Sms facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def send(self, recipient, message): | ||||
|         ''' | ||||
|         Send SMS or open SMS interface. | ||||
| 
 | ||||
|         :param recipient: The receiver | ||||
|         :param message: the message | ||||
| 
 | ||||
|         :type recipient: number | ||||
|         :type message: str | ||||
|         ''' | ||||
|         self._send(recipient=recipient, message=message) | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _send(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										54
									
								
								sbapp/plyer/facades/spatialorientation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								sbapp/plyer/facades/spatialorientation.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| # coding=utf-8 | ||||
| 
 | ||||
| 
 | ||||
| class SpatialOrientation: | ||||
|     '''Spatial Orientation facade. | ||||
| 
 | ||||
|     Computes the device's orientation based on the rotation matrix. | ||||
| 
 | ||||
|     .. versionadded:: 1.3.1 | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def orientation(self): | ||||
|         '''Property that returns values of the current device orientation | ||||
|         as a (azimuth, pitch, roll) tuple. | ||||
| 
 | ||||
|         Azimuth, angle of rotation about the -z axis. This value represents the | ||||
|         angle between the device's y axis and the magnetic north pole. | ||||
|         The range of values is -π to π. | ||||
| 
 | ||||
|         Pitch, angle of rotation about the x axis. This value represents the | ||||
|         angle between a plane parallel to the device's screen and a plane | ||||
|         parallel to the ground. | ||||
|         The range of values is -π to π. | ||||
| 
 | ||||
|         Roll, angle of rotation about the y axis. This value represents the | ||||
|         angle between a plane perpendicular to the device's screen and a plane | ||||
|         perpendicular to the ground. | ||||
|         The range of values is -π/2 to π/2. | ||||
| 
 | ||||
|         Returns (None, None, None) if no data is currently available. | ||||
| 
 | ||||
|         Supported Platforms:: Android | ||||
|         ''' | ||||
|         return self._get_orientation() or (None, None, None) | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def enable_listener(self): | ||||
|         '''Enable the orientation sensor. | ||||
|         ''' | ||||
|         self._enable_listener() | ||||
| 
 | ||||
|     def _enable_listener(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def disable_listener(self): | ||||
|         '''Disable the orientation sensor. | ||||
|         ''' | ||||
|         self._disable_listener() | ||||
| 
 | ||||
|     def _disable_listener(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										135
									
								
								sbapp/plyer/facades/storagepath.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								sbapp/plyer/facades/storagepath.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,135 @@ | ||||
| ''' | ||||
| Storage Path | ||||
| ============ | ||||
| 
 | ||||
| The StorgePath API can be used to gain access to standard storage locations | ||||
| across platforms such as home directory, root directory, external storage | ||||
| directory, documents, downloads, etc. | ||||
| 
 | ||||
| The :class:`StoragePath` provides access to public methods to access standard | ||||
| storage locations. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To get the path of user's home directory:: | ||||
| 
 | ||||
|     >>> from plyer import storagepath | ||||
|     >>> storagepath.get_home_dir() | ||||
| 
 | ||||
| To get the path of standard downloads directory:: | ||||
| 
 | ||||
|     >>> from plyer import storagepath | ||||
|     >>> storagepath.get_downloads_dir() | ||||
| 
 | ||||
| To get the path of directory holding application files:: | ||||
| 
 | ||||
|     >>> from plyer import storagepath | ||||
|     >>> storagepath.get_application_dir() | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class StoragePath: | ||||
|     ''' | ||||
|     StoragePath facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def get_home_dir(self): | ||||
|         ''' | ||||
|         Get the path of home directory of current user. | ||||
|         ''' | ||||
|         return self._get_home_dir() | ||||
| 
 | ||||
|     def get_external_storage_dir(self): | ||||
|         ''' | ||||
|         Get the path of primary shared or external storage directory. | ||||
|         ''' | ||||
|         return self._get_external_storage_dir() | ||||
| 
 | ||||
|     def get_sdcard_dir(self): | ||||
|         ''' | ||||
|         Get the path of external SD card. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
|         return self._get_sdcard_dir() | ||||
| 
 | ||||
|     def get_root_dir(self): | ||||
|         ''' | ||||
|         Get the path of root of the "system" partition holding the core OS. | ||||
|         ''' | ||||
|         return self._get_root_dir() | ||||
| 
 | ||||
|     def get_documents_dir(self): | ||||
|         ''' | ||||
|         Get the path of standard directory in which to place documents that | ||||
|         have been created by the user. | ||||
|         ''' | ||||
|         return self._get_documents_dir() | ||||
| 
 | ||||
|     def get_downloads_dir(self): | ||||
|         ''' | ||||
|         Get the path of standard directory in which to place files that have | ||||
|         been downloaded by the user. | ||||
|         ''' | ||||
|         return self._get_downloads_dir() | ||||
| 
 | ||||
|     def get_videos_dir(self): | ||||
|         ''' | ||||
|         Get the path of standard directory in which to place videos that are | ||||
|         available to the user. | ||||
|         ''' | ||||
|         return self._get_videos_dir() | ||||
| 
 | ||||
|     def get_music_dir(self): | ||||
|         ''' | ||||
|         Get the path of standard directory in which to place any audio files | ||||
|         that should be in the regular list of music for the user. | ||||
|         ''' | ||||
|         return self._get_music_dir() | ||||
| 
 | ||||
|     def get_pictures_dir(self): | ||||
|         ''' | ||||
|         Standard directory in which to place pictures that are available to | ||||
|         the user. | ||||
|         ''' | ||||
|         return self._get_pictures_dir() | ||||
| 
 | ||||
|     def get_application_dir(self): | ||||
|         ''' | ||||
|         Get the path of the directory holding application files. | ||||
|         ''' | ||||
|         return self._get_application_dir() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _get_home_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_external_storage_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_sdcard_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_root_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_documents_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_downloads_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_videos_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_music_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_pictures_dir(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_application_dir(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										188
									
								
								sbapp/plyer/facades/stt.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								sbapp/plyer/facades/stt.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,188 @@ | ||||
| ''' | ||||
| Speech to Text | ||||
| ============== | ||||
| 
 | ||||
| .. versionadded:: 1.4.0 | ||||
| 
 | ||||
| Speech Recognition facade. | ||||
| 
 | ||||
| In order to check that your device supports voice recognition use method | ||||
| `exist`. | ||||
| 
 | ||||
| Variable `language` indicates which language will be used to match words from | ||||
|  voice. | ||||
| 
 | ||||
| Use `start` to start voice recognition immediately and `stop` to stop. | ||||
| 
 | ||||
| .. note:: | ||||
|     Needed permissions for Android: `RECORD_AUDIO` (and `INTERNET` if you want | ||||
|     online voice recognition API to be used) | ||||
| 
 | ||||
| .. note:: | ||||
|     On Android platform, after execute `start` method you can hear BEEP! | ||||
|     Mute sound in order to disable it. | ||||
| 
 | ||||
| .. note:: | ||||
|     For Android implementation to work there has to be an application with | ||||
|     `android.speech.RecognitionService` implementation present in the system. | ||||
|     Mostly it's `com.google.android.googlequicksearchbox` or "Google" | ||||
|     application (the search bar with the launcher widget). | ||||
| 
 | ||||
| Offline Speech Recognition on Android | ||||
| ------------------------------------- | ||||
| 
 | ||||
| Requires any application that provides an | ||||
| `android.speech.RecognitionService` implementation to the other apps. One of | ||||
| such applications is on a lot of devices preinstalled Google (quick search | ||||
| box). | ||||
| 
 | ||||
| The API prefers offline recognition, but should be able to switch to online | ||||
| alternative in case you don't have a language package installed (`INTERNET` | ||||
| permission necessary). | ||||
| 
 | ||||
| You can enable offline speech recognition this way (Android 8.1): | ||||
| 
 | ||||
| * open the `Settings` app | ||||
| * choose `Language & Input` / `Language & Keyboard` (Samsung might include it | ||||
|   in the `General` category) | ||||
| * choose `On-Screen keyboard` or `Voice search` | ||||
| * choose `Google Keyboard` | ||||
| * choose `Offline Speech recognition` | ||||
| * download language package if you don't have one already | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To start listening:: | ||||
| 
 | ||||
|     >>> from plyer import stt | ||||
|     >>> stt.start() | ||||
| 
 | ||||
| To retrieve partial results while listening:: | ||||
| 
 | ||||
|     >>> assert stt.listening | ||||
|     >>> print(stt.partial_results) | ||||
| 
 | ||||
| To stop listening:: | ||||
| 
 | ||||
|     >>> stt.stop() | ||||
| 
 | ||||
| To retrieve results after the listening stopped:: | ||||
| 
 | ||||
|     >>> print(stt.results) | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class STT: | ||||
|     ''' | ||||
|     Speech to text facade. | ||||
|     ''' | ||||
| 
 | ||||
|     _language = 'en-US' | ||||
|     ''' | ||||
|     Default language in which platform will try to recognize voice. | ||||
|     In order to change language pick one from list by using | ||||
|     `supported_languages` method. | ||||
|     ''' | ||||
| 
 | ||||
|     _supported_languages = [ | ||||
|         'en-US', | ||||
|         'pl-PL' | ||||
|     ] | ||||
| 
 | ||||
|     results = [] | ||||
|     ''' | ||||
|     List of sentences found while listening. It may consist of many similar | ||||
|     and possible sentences that was recognition program. | ||||
|     ''' | ||||
| 
 | ||||
|     errors = [] | ||||
|     ''' | ||||
|     List of errors found while listening. | ||||
|     ''' | ||||
| 
 | ||||
|     partial_results = [] | ||||
|     ''' | ||||
|     List of results found while the listener is still being active. | ||||
|     ''' | ||||
| 
 | ||||
|     prefer_offline = True | ||||
|     ''' | ||||
|     Preference whether to use offline language package necessary for | ||||
|     each platform dependant implementation or online API. | ||||
|     ''' | ||||
| 
 | ||||
|     listening = False | ||||
|     ''' | ||||
|     Current state of listening. | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def supported_languages(self): | ||||
|         ''' | ||||
|         Return list of supported languages used in recognition. | ||||
|         ''' | ||||
| 
 | ||||
|         return self._supported_languages | ||||
| 
 | ||||
|     @property | ||||
|     def language(self): | ||||
|         ''' | ||||
|         Return current language. | ||||
|         ''' | ||||
| 
 | ||||
|         return self._language | ||||
| 
 | ||||
|     @language.setter | ||||
|     def language(self, lang): | ||||
|         ''' | ||||
|         Set current language. | ||||
| 
 | ||||
|         Value can not be set if it's not supported. See `supported_languages` | ||||
|         to get what language you can set. | ||||
| 
 | ||||
|         .. note:: | ||||
|            We obviously can't check each language, therefore if you find | ||||
|            that a specific language is available to you and the only limitation | ||||
|            is our check for the internally defined `supported_languages`, feel | ||||
|            free to open a pull request for adding your language to the list. | ||||
|         ''' | ||||
| 
 | ||||
|         if lang in self.supported_languages: | ||||
|             self._language = lang | ||||
| 
 | ||||
|     # public methods | ||||
|     def start(self): | ||||
|         ''' | ||||
|         Start listening. | ||||
|         ''' | ||||
| 
 | ||||
|         self.results = [] | ||||
|         self.partial_results = [] | ||||
|         self._start() | ||||
|         self.listening = True | ||||
| 
 | ||||
|     def stop(self): | ||||
|         ''' | ||||
|         Stop listening. | ||||
|         ''' | ||||
| 
 | ||||
|         self._stop() | ||||
|         self.listening = False | ||||
| 
 | ||||
|     def exist(self): | ||||
|         ''' | ||||
|         Returns a boolean for speech recognition availability. | ||||
|         ''' | ||||
| 
 | ||||
|         return self._exist() | ||||
| 
 | ||||
|     # private methods | ||||
|     def _start(self): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def _stop(self): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def _exist(self): | ||||
|         raise NotImplementedError | ||||
							
								
								
									
										41
									
								
								sbapp/plyer/facades/temperature.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								sbapp/plyer/facades/temperature.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| # coding=utf-8 | ||||
| 
 | ||||
| 
 | ||||
| class Temperature: | ||||
|     '''Temperature facade. | ||||
| 
 | ||||
|     Temperature sensor is used to measure the ambient room temperature in | ||||
|     degrees Celsius (°C) | ||||
|     With method `enable` you can turn on temperature sensor and 'disable' | ||||
|     method stops the sensor. | ||||
|     Use property `temperature` to get ambient air temperature in degree C. | ||||
| 
 | ||||
|     .. versionadded:: 1.2.5 | ||||
| 
 | ||||
|     Supported Platforms:: Android | ||||
| 
 | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def temperature(self): | ||||
|         '''Current air temperature in degree C.''' | ||||
|         return self._get_temperature() | ||||
| 
 | ||||
|     def enable(self): | ||||
|         '''Enable temperature sensor.''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         '''Disable temperature sensor.''' | ||||
|         self._disable() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _get_temperature(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _enable(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _disable(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										39
									
								
								sbapp/plyer/facades/tts.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								sbapp/plyer/facades/tts.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| ''' | ||||
| TTS | ||||
| ==== | ||||
| 
 | ||||
| The :class:`TTS` provides provides access to public methods to | ||||
| use text to speech of your device. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To speak:: | ||||
| 
 | ||||
|     >>> from plyer import tts | ||||
|     >>> tts.speak(message=message) | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS, Windows, OS X, Linux | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class TTS: | ||||
|     ''' | ||||
|     TextToSpeech facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def speak(self, message=''): | ||||
|         '''Use text to speech capabilities to speak the message. | ||||
| 
 | ||||
|         :param message: What to speak | ||||
|         :type message: str | ||||
|         ''' | ||||
|         self._speak(message=message) | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _speak(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										54
									
								
								sbapp/plyer/facades/uniqueid.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								sbapp/plyer/facades/uniqueid.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| '''UniqueID facade. | ||||
| 
 | ||||
| Returns the following depending on the platform: | ||||
| 
 | ||||
| * **Android**: Android ID | ||||
| * **OS X**: Serial number of the device | ||||
| * **Linux**: Serial number using lshw | ||||
| * **Windows**: MachineGUID from regkey | ||||
| * **iOS**: UUID | ||||
| 
 | ||||
| Simple Example | ||||
| -------------- | ||||
| 
 | ||||
| To get the unique ID:: | ||||
| 
 | ||||
|     >>> from plyer import uniqueid | ||||
|     >>> uniqueid.id | ||||
|     '1b1a7a4958e2a845' | ||||
| 
 | ||||
| .. versionadded:: 1.2.0 | ||||
| 
 | ||||
| .. versionchanged:: 1.2.4 | ||||
|     On Android returns Android ID instead of IMEI. | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS, Windows, OS X, Linux | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class UniqueID: | ||||
|     ''' | ||||
|     UniqueID facade. | ||||
|     ''' | ||||
| 
 | ||||
|     @property | ||||
|     def id(self): | ||||
|         ''' | ||||
|         Property that returns the unique id of the platform. | ||||
|         ''' | ||||
|         return self.get_uid() | ||||
| 
 | ||||
|     def get_uid(self): | ||||
|         ''' | ||||
|         Public method for receiving unique ID via platform-specific | ||||
|         API in plyer.platforms. | ||||
|         ''' | ||||
|         return self._get_uid() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _get_uid(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										97
									
								
								sbapp/plyer/facades/vibrator.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								sbapp/plyer/facades/vibrator.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,97 @@ | ||||
| ''' | ||||
| Vibrator | ||||
| ======= | ||||
| 
 | ||||
| The :class:`Vibrator` provides access to public methods to use vibrator of your | ||||
| device. | ||||
| 
 | ||||
| .. note:: | ||||
|     On Android your app needs the VIBRATE permission to | ||||
|     access the vibrator. | ||||
| 
 | ||||
| Simple Examples | ||||
| --------------- | ||||
| 
 | ||||
| To vibrate your device:: | ||||
| 
 | ||||
|     >>> from plyer import vibrator | ||||
|     >>> time=2 | ||||
|     >>> vibrator.vibrate(time=time) | ||||
| 
 | ||||
| To set a pattern:: | ||||
| 
 | ||||
|     >>> vibrator.pattern(pattern=pattern, repeat=repeat) | ||||
| 
 | ||||
| To know whether vibrator exists or not:: | ||||
| 
 | ||||
|     >>> vibrator.exists() | ||||
| 
 | ||||
| To cancel vibration:: | ||||
| 
 | ||||
|     >>> vibrator.cancel() | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Android, iOS | ||||
| 
 | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Vibrator: | ||||
|     ''' | ||||
|     Vibration facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def vibrate(self, time=1): | ||||
|         ''' | ||||
|         Ask the vibrator to vibrate for the given period. | ||||
| 
 | ||||
|         :param time: Time to vibrate for, in seconds. Default is 1. | ||||
|         ''' | ||||
|         self._vibrate(time=time) | ||||
| 
 | ||||
|     def pattern(self, pattern=(0, 1), repeat=-1): | ||||
|         ''' | ||||
|         Ask the vibrator to vibrate with the given pattern, with an | ||||
|         optional repeat. | ||||
| 
 | ||||
|         :param pattern: Pattern to vibrate with. Should be a list of | ||||
|             times in seconds. The first number is how long to wait | ||||
|             before vibrating, and subsequent numbers are times to | ||||
|             vibrate and not vibrate alternately. | ||||
|             Defaults to ``[0, 1]``. | ||||
| 
 | ||||
|         :param repeat: Index at which to repeat the pattern. When the | ||||
|             vibration pattern reaches this index, it will start again | ||||
|             from the beginning. Defaults to ``-1``, which means no | ||||
|             repeat. | ||||
|         ''' | ||||
|         self._pattern(pattern=pattern, repeat=repeat) | ||||
| 
 | ||||
|     def exists(self): | ||||
|         ''' | ||||
|         Check if the device has a vibrator. Returns True or | ||||
|         False. | ||||
|         ''' | ||||
|         return self._exists() | ||||
| 
 | ||||
|     def cancel(self): | ||||
|         ''' | ||||
|         Cancels any current vibration, and stops the vibrator. | ||||
|         ''' | ||||
|         self._cancel() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _vibrate(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _pattern(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _exists(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _cancel(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										187
									
								
								sbapp/plyer/facades/wifi.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								sbapp/plyer/facades/wifi.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,187 @@ | ||||
| ''' | ||||
| Wifi Facade. | ||||
| ============= | ||||
| 
 | ||||
| The :class:`Wifi` is to provide access to the wifi of your mobile/ desktop | ||||
| devices. | ||||
| 
 | ||||
| It currently supports `connecting`, `disconnecting`, `scanning`, `getting | ||||
| available wifi network list` and `getting network information`. | ||||
| 
 | ||||
| Simple examples | ||||
| --------------- | ||||
| 
 | ||||
| To enable/ turn on wifi scanning:: | ||||
| 
 | ||||
|     >>> from plyer import wifi | ||||
|     >>> wifi.start_scanning() | ||||
| 
 | ||||
| Once the wifi is enabled/ turned on, then this command starts to scan | ||||
| all the nearby available wifi networks. | ||||
| 
 | ||||
| To get network info:: | ||||
| 
 | ||||
|     >>> from plyer import wifi | ||||
|     >>> wifi.start_scanning() | ||||
|     >>> return wifi.get_network_info(name) | ||||
| 
 | ||||
| Returns network details of the network who's name/ssid is provided in the | ||||
| `name` parameter. | ||||
| 
 | ||||
| To connect to a network:: | ||||
| 
 | ||||
|     >>> from plyer import wifi | ||||
|     >>> wifi.start_scanning() | ||||
|     >>> wifi.connect(network, parameters) | ||||
| 
 | ||||
| This connects to the network who's name/ssid is provided under `network` | ||||
| parameter and along with other necessary methods for connection | ||||
| which depends upon platform to platform. | ||||
| 
 | ||||
| please visit following files for more details about requirements of | ||||
| `paramaters` argument in `connect` method: | ||||
| 
 | ||||
|     plyer/platforms/win/wifi.py | ||||
|     plyer/platforms/macosx/wifi.py | ||||
|     plyer/platforms/win/wifi.py | ||||
| 
 | ||||
| To disconnect from wifi:: | ||||
| 
 | ||||
|     >>> from plyer import wifi | ||||
|     >>> wifi.disconnect() | ||||
| 
 | ||||
| This disconnects your device from any wifi network. | ||||
| 
 | ||||
| To get available wifi networks:: | ||||
| 
 | ||||
|     >>> from plyer import wifi | ||||
|     >>> wifi.start_scanning() | ||||
|     >>> return wifi.get_available_wifi() | ||||
| 
 | ||||
| This returns all the available wifi networks near the device. | ||||
| 
 | ||||
| Supported Platforms | ||||
| ------------------- | ||||
| Windows, OS X, Linux | ||||
| 
 | ||||
| Ex: 6 | ||||
| ---------- | ||||
| 
 | ||||
| from plyer import wifi | ||||
| wifi.enable() | ||||
| 
 | ||||
| This enables wifi device. | ||||
| 
 | ||||
| Ex: 7 | ||||
| ---------- | ||||
| 
 | ||||
| from plyer import wifi | ||||
| wifi.disable() | ||||
| 
 | ||||
| This disable wifi device | ||||
| ''' | ||||
| 
 | ||||
| 
 | ||||
| class Wifi: | ||||
|     ''' | ||||
|     Wifi Facade. | ||||
|     ''' | ||||
| 
 | ||||
|     def is_enabled(self): | ||||
|         ''' | ||||
|         Return enabled status of WiFi hardware. | ||||
|         ''' | ||||
|         return self._is_enabled() | ||||
| 
 | ||||
|     def is_connected(self, interface=None): | ||||
|         ''' | ||||
|         Return connection state of WiFi interface. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
|         return self._is_connected(interface=interface) | ||||
| 
 | ||||
|     @property | ||||
|     def interfaces(self): | ||||
|         ''' | ||||
|         List all available WiFi interfaces. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def start_scanning(self, interface=None): | ||||
|         ''' | ||||
|         Turn on scanning. | ||||
|         ''' | ||||
|         return self._start_scanning(interface=interface) | ||||
| 
 | ||||
|     def get_network_info(self, name): | ||||
|         ''' | ||||
|         Return a dictionary of specified network. | ||||
|         ''' | ||||
|         return self._get_network_info(name=name) | ||||
| 
 | ||||
|     def get_available_wifi(self): | ||||
|         ''' | ||||
|         Returns a list of all the available wifi. | ||||
|         ''' | ||||
|         return self._get_available_wifi() | ||||
| 
 | ||||
|     def connect(self, network, parameters, interface=None): | ||||
|         ''' | ||||
|         Method to connect to some network. | ||||
|         ''' | ||||
|         self._connect( | ||||
|             network=network, | ||||
|             parameters=parameters, | ||||
|             interface=interface | ||||
|         ) | ||||
| 
 | ||||
|     def disconnect(self, interface=None): | ||||
|         ''' | ||||
|         To disconnect from some network. | ||||
|         ''' | ||||
|         self._disconnect(interface=interface) | ||||
| 
 | ||||
|     def enable(self): | ||||
|         ''' | ||||
|         Wifi interface power state is set to "ON". | ||||
|         ''' | ||||
|         self._enable() | ||||
| 
 | ||||
|     def disable(self): | ||||
|         ''' | ||||
|         Wifi interface power state is set to "OFF". | ||||
|         ''' | ||||
|         self._disable() | ||||
| 
 | ||||
|     # private | ||||
| 
 | ||||
|     def _is_enabled(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _is_connected(self, interface=None): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _start_scanning(self, interface=None): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_network_info(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_available_wifi(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _connect(self, **kwargs): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _disconnect(self, interface=None): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										0
									
								
								sbapp/plyer/platforms/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								sbapp/plyer/platforms/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										18
									
								
								sbapp/plyer/platforms/android/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								sbapp/plyer/platforms/android/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| from os import environ | ||||
| from jnius import autoclass | ||||
| 
 | ||||
| ANDROID_VERSION = autoclass('android.os.Build$VERSION') | ||||
| SDK_INT = ANDROID_VERSION.SDK_INT | ||||
| 
 | ||||
| try: | ||||
|     from android import config | ||||
|     ns = config.JAVA_NAMESPACE | ||||
| except (ImportError, AttributeError): | ||||
|     ns = 'org.renpy.android' | ||||
| 
 | ||||
| if 'PYTHON_SERVICE_ARGUMENT' in environ: | ||||
|     PythonService = autoclass(ns + '.PythonService') | ||||
|     activity = PythonService.mService | ||||
| else: | ||||
|     PythonActivity = autoclass(ns + '.PythonActivity') | ||||
|     activity = PythonActivity.mActivity | ||||
							
								
								
									
										79
									
								
								sbapp/plyer/platforms/android/accelerometer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								sbapp/plyer/platforms/android/accelerometer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| ''' | ||||
| Android accelerometer | ||||
| --------------------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Accelerometer | ||||
| from jnius import PythonJavaClass, java_method, autoclass, cast | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class AccelerometerSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.SensorManager = cast( | ||||
|             'android.hardware.SensorManager', | ||||
|             activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         ) | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_ACCELEROMETER | ||||
|         ) | ||||
| 
 | ||||
|         self.values = [None, None, 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.values = event.values[:3] | ||||
| 
 | ||||
|     @java_method('(Landroid/hardware/Sensor;I)V') | ||||
|     def onAccuracyChanged(self, sensor, accuracy): | ||||
|         # Maybe, do something in future? | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class AndroidAccelerometer(Accelerometer): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.bState = False | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         if (not self.bState): | ||||
|             self.listener = AccelerometerSensorListener() | ||||
|             self.listener.enable() | ||||
|             self.bState = True | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         if (self.bState): | ||||
|             self.bState = False | ||||
|             self.listener.disable() | ||||
|             del self.listener | ||||
| 
 | ||||
|     def _get_acceleration(self): | ||||
|         if (self.bState): | ||||
|             return tuple(self.listener.values) | ||||
|         else: | ||||
|             return (None, None, None) | ||||
| 
 | ||||
|     def __del__(self): | ||||
|         if(self.bState): | ||||
|             self._disable() | ||||
|         super().__del__() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidAccelerometer() | ||||
							
								
								
									
										58
									
								
								sbapp/plyer/platforms/android/audio.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								sbapp/plyer/platforms/android/audio.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| from jnius import autoclass | ||||
| 
 | ||||
| from plyer.facades.audio import Audio | ||||
| 
 | ||||
| # Recorder Classes | ||||
| MediaRecorder = autoclass('android.media.MediaRecorder') | ||||
| AudioSource = autoclass('android.media.MediaRecorder$AudioSource') | ||||
| OutputFormat = autoclass('android.media.MediaRecorder$OutputFormat') | ||||
| AudioEncoder = autoclass('android.media.MediaRecorder$AudioEncoder') | ||||
| 
 | ||||
| # Player Classes | ||||
| MediaPlayer = autoclass('android.media.MediaPlayer') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidAudio(Audio): | ||||
|     '''Audio for android. | ||||
| 
 | ||||
|     For recording audio we use MediaRecorder Android class. | ||||
|     For playing audio we use MediaPlayer Android class. | ||||
|     ''' | ||||
| 
 | ||||
|     def __init__(self, file_path=None): | ||||
|         default_path = '/sdcard/testrecorder.3gp' | ||||
|         super().__init__(file_path or default_path) | ||||
| 
 | ||||
|         self._recorder = None | ||||
|         self._player = None | ||||
| 
 | ||||
|     def _start(self): | ||||
|         self._recorder = MediaRecorder() | ||||
|         self._recorder.setAudioSource(AudioSource.DEFAULT) | ||||
|         self._recorder.setOutputFormat(OutputFormat.DEFAULT) | ||||
|         self._recorder.setAudioEncoder(AudioEncoder.DEFAULT) | ||||
|         self._recorder.setOutputFile(self.file_path) | ||||
| 
 | ||||
|         self._recorder.prepare() | ||||
|         self._recorder.start() | ||||
| 
 | ||||
|     def _stop(self): | ||||
|         if self._recorder: | ||||
|             self._recorder.stop() | ||||
|             self._recorder.release() | ||||
|             self._recorder = None | ||||
| 
 | ||||
|         if self._player: | ||||
|             self._player.stop() | ||||
|             self._player.release() | ||||
|             self._player = None | ||||
| 
 | ||||
|     def _play(self): | ||||
|         self._player = MediaPlayer() | ||||
|         self._player.setDataSource(self.file_path) | ||||
|         self._player.prepare() | ||||
|         self._player.start() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidAudio() | ||||
							
								
								
									
										65
									
								
								sbapp/plyer/platforms/android/barometer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								sbapp/plyer/platforms/android/barometer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| from jnius import autoclass | ||||
| from jnius import cast | ||||
| from jnius import java_method | ||||
| from jnius import PythonJavaClass | ||||
| 
 | ||||
| from plyer.facades import Barometer | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| ActivityInfo = autoclass('android.content.pm.ActivityInfo') | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class BarometerSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) | ||||
|         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 AndroidBarometer(Barometer): | ||||
| 
 | ||||
|     listener = None | ||||
| 
 | ||||
|     def _get_pressure(self): | ||||
|         if self.listener and self.listener.value: | ||||
|             pressure = self.listener.value | ||||
|             return pressure | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         if not self.listener: | ||||
|             self.listener = BarometerSensorListener() | ||||
|             self.listener.enable() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         if self.listener: | ||||
|             self.listener.disable() | ||||
|             delattr(self, 'listener') | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidBarometer() | ||||
							
								
								
									
										47
									
								
								sbapp/plyer/platforms/android/battery.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								sbapp/plyer/platforms/android/battery.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| ''' | ||||
| Module of Android API for plyer.battery. | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass, cast | ||||
| from plyer.platforms.android import activity | ||||
| from plyer.facades import Battery | ||||
| 
 | ||||
| Intent = autoclass('android.content.Intent') | ||||
| BatteryManager = autoclass('android.os.BatteryManager') | ||||
| IntentFilter = autoclass('android.content.IntentFilter') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidBattery(Battery): | ||||
|     ''' | ||||
|     Implementation of Android battery API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _get_state(self): | ||||
|         status = {"isCharging": None, "percentage": None} | ||||
| 
 | ||||
|         ifilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) | ||||
| 
 | ||||
|         battery_status = cast( | ||||
|             'android.content.Intent', | ||||
|             activity.registerReceiver(None, ifilter) | ||||
|         ) | ||||
| 
 | ||||
|         query = battery_status.getIntExtra(BatteryManager.EXTRA_STATUS, -1) | ||||
|         is_charging = query == BatteryManager.BATTERY_STATUS_CHARGING | ||||
|         is_full = query == BatteryManager.BATTERY_STATUS_FULL | ||||
| 
 | ||||
|         level = battery_status.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) | ||||
|         scale = battery_status.getIntExtra(BatteryManager.EXTRA_SCALE, -1) | ||||
|         percentage = (level / float(scale)) * 100 | ||||
| 
 | ||||
|         status['isCharging'] = is_charging or is_full | ||||
|         status['percentage'] = percentage | ||||
| 
 | ||||
|         return status | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return AndroidBattery() | ||||
							
								
								
									
										32
									
								
								sbapp/plyer/platforms/android/bluetooth.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								sbapp/plyer/platforms/android/bluetooth.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| ''' | ||||
| Module of Android API for plyer.bluetooth. | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass | ||||
| from plyer.platforms.android import activity | ||||
| from plyer.facades import Bluetooth | ||||
| 
 | ||||
| Global = autoclass('android.provider.Settings$Global') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidBluetooth(Bluetooth): | ||||
|     ''' | ||||
|     Implementation of Android Bluetooth API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _get_info(self): | ||||
|         bluetooth_enabled = Global.getString( | ||||
|             activity.getContentResolver(), | ||||
|             Global.BLUETOOTH_ON | ||||
|         ) | ||||
|         status = 'off' | ||||
|         if bluetooth_enabled: | ||||
|             status = 'on' | ||||
|         return status | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return AndroidBluetooth() | ||||
							
								
								
									
										34
									
								
								sbapp/plyer/platforms/android/brightness.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										34
									
								
								sbapp/plyer/platforms/android/brightness.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,34 @@ | ||||
| ''' | ||||
| Android Brightness | ||||
| ------------------ | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass | ||||
| from plyer.facades import Brightness | ||||
| from android import mActivity | ||||
| 
 | ||||
| System = autoclass('android.provider.Settings$System') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidBrightness(Brightness): | ||||
| 
 | ||||
|     def _current_level(self): | ||||
| 
 | ||||
|         System.putInt( | ||||
|             mActivity.getContentResolver(), | ||||
|             System.SCREEN_BRIGHTNESS_MODE, | ||||
|             System.SCREEN_BRIGHTNESS_MODE_MANUAL) | ||||
|         cr_level = System.getInt( | ||||
|             mActivity.getContentResolver(), | ||||
|             System.SCREEN_BRIGHTNESS) | ||||
|         return (cr_level / 255.) * 100 | ||||
| 
 | ||||
|     def _set_level(self, level): | ||||
|         System.putInt( | ||||
|             mActivity.getContentResolver(), | ||||
|             System.SCREEN_BRIGHTNESS, | ||||
|             (level / 100.) * 255) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidBrightness() | ||||
							
								
								
									
										29
									
								
								sbapp/plyer/platforms/android/call.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								sbapp/plyer/platforms/android/call.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| ''' | ||||
| Android Call | ||||
| ----------- | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass | ||||
| from plyer.facades import Call | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Intent = autoclass('android.content.Intent') | ||||
| uri = autoclass('android.net.Uri') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidCall(Call): | ||||
| 
 | ||||
|     def _makecall(self, **kwargs): | ||||
| 
 | ||||
|         intent = Intent(Intent.ACTION_CALL) | ||||
|         tel = kwargs.get('tel') | ||||
|         intent.setData(uri.parse("tel:{}".format(tel))) | ||||
|         activity.startActivity(intent) | ||||
| 
 | ||||
|     def _dialcall(self, **kwargs): | ||||
|         intent_ = Intent(Intent.ACTION_DIAL) | ||||
|         activity.startActivity(intent_) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidCall() | ||||
							
								
								
									
										59
									
								
								sbapp/plyer/platforms/android/camera.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								sbapp/plyer/platforms/android/camera.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| import android | ||||
| import android.activity | ||||
| from os import remove | ||||
| from jnius import autoclass, cast | ||||
| from plyer.facades import Camera | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Intent = autoclass('android.content.Intent') | ||||
| PythonActivity = autoclass('org.kivy.android.PythonActivity') | ||||
| MediaStore = autoclass('android.provider.MediaStore') | ||||
| Uri = autoclass('android.net.Uri') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidCamera(Camera): | ||||
| 
 | ||||
|     def _take_picture(self, on_complete, filename=None): | ||||
|         assert(on_complete is not None) | ||||
|         self.on_complete = on_complete | ||||
|         self.filename = filename | ||||
|         android.activity.unbind(on_activity_result=self._on_activity_result) | ||||
|         android.activity.bind(on_activity_result=self._on_activity_result) | ||||
|         intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) | ||||
|         uri = Uri.parse('file://' + filename) | ||||
|         parcelable = cast('android.os.Parcelable', uri) | ||||
|         intent.putExtra(MediaStore.EXTRA_OUTPUT, parcelable) | ||||
|         activity.startActivityForResult(intent, 0x123) | ||||
| 
 | ||||
|     def _take_video(self, on_complete, filename=None): | ||||
|         assert(on_complete is not None) | ||||
|         self.on_complete = on_complete | ||||
|         self.filename = filename | ||||
|         android.activity.unbind(on_activity_result=self._on_activity_result) | ||||
|         android.activity.bind(on_activity_result=self._on_activity_result) | ||||
|         intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE) | ||||
|         uri = Uri.parse('file://' + filename) | ||||
|         parcelable = cast('android.os.Parcelable', uri) | ||||
|         intent.putExtra(MediaStore.EXTRA_OUTPUT, parcelable) | ||||
| 
 | ||||
|         # 0 = low quality, suitable for MMS messages, | ||||
|         # 1 = high quality | ||||
|         intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1) | ||||
|         activity.startActivityForResult(intent, 0x123) | ||||
| 
 | ||||
|     def _on_activity_result(self, requestCode, resultCode, intent): | ||||
|         if requestCode != 0x123: | ||||
|             return | ||||
|         android.activity.unbind(on_activity_result=self._on_activity_result) | ||||
|         if self.on_complete(self.filename): | ||||
|             self._remove(self.filename) | ||||
| 
 | ||||
|     def _remove(self, fn): | ||||
|         try: | ||||
|             remove(fn) | ||||
|         except OSError: | ||||
|             pass | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidCamera() | ||||
							
								
								
									
										119
									
								
								sbapp/plyer/platforms/android/compass.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								sbapp/plyer/platforms/android/compass.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | ||||
| ''' | ||||
| Android Compass | ||||
| --------------------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Compass | ||||
| from jnius import PythonJavaClass, java_method, autoclass, cast | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class MFUSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED) | ||||
|         self.values = [None, None, None, None, None, 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.values = event.values[:6] | ||||
| 
 | ||||
|     @java_method('(Landroid/hardware/Sensor;I)V') | ||||
|     def onAccuracyChanged(self, sensor, accuracy): | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class MagneticFieldSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.SensorManager = cast( | ||||
|             'android.hardware.SensorManager', | ||||
|             activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         ) | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_MAGNETIC_FIELD | ||||
|         ) | ||||
| 
 | ||||
|         self.values = [None, None, 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.values = event.values[:3] | ||||
| 
 | ||||
|     @java_method('(Landroid/hardware/Sensor;I)V') | ||||
|     def onAccuracyChanged(self, sensor, accuracy): | ||||
|         # Maybe, do something in future? | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class AndroidCompass(Compass): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.bState = False | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         if (not self.bState): | ||||
|             self.listenerm = MagneticFieldSensorListener() | ||||
|             self.listenermu = MFUSensorListener() | ||||
|             self.listenerm.enable() | ||||
|             self.listenermu.enable() | ||||
|             self.bState = True | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         if (self.bState): | ||||
|             self.bState = False | ||||
|             self.listenerm.disable() | ||||
|             self.listenermu.disable() | ||||
|             del self.listenerm | ||||
|             del self.listenermu | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         if (self.bState): | ||||
|             return tuple(self.listenerm.values) | ||||
|         else: | ||||
|             return (None, None, None) | ||||
| 
 | ||||
|     def _get_field_uncalib(self): | ||||
|         if (self.bState): | ||||
|             return tuple(self.listenermu.values) | ||||
|         else: | ||||
|             return (None, None, None, None, None, None) | ||||
| 
 | ||||
|     def __del__(self): | ||||
|         if(self.bState): | ||||
|             self._disable() | ||||
|         super().__del__() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidCompass() | ||||
							
								
								
									
										33
									
								
								sbapp/plyer/platforms/android/devicename.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								sbapp/plyer/platforms/android/devicename.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| ''' | ||||
| Module of Android API for plyer.devicename. | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass | ||||
| from plyer.facades import DeviceName | ||||
| 
 | ||||
| Build = autoclass('android.os.Build') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidDeviceName(DeviceName): | ||||
|     ''' | ||||
|     Implementation of Android devicename API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _get_device_name(self): | ||||
|         """ | ||||
|         Method to get the device name aka model in an android environment. | ||||
| 
 | ||||
|         Changed the implementation from 'android.provider.Settings.Global' to | ||||
|         'android.os.Build' because 'android.provider.Settings.Global' was | ||||
|         introduced in API 17 whereas 'android.os.Build' is present since API 1 | ||||
| 
 | ||||
|         Thereby making this method more backward compatible. | ||||
|         """ | ||||
|         return Build.MODEL | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return AndroidDeviceName() | ||||
							
								
								
									
										58
									
								
								sbapp/plyer/platforms/android/email.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								sbapp/plyer/platforms/android/email.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| ''' | ||||
| Module of Android API for plyer.email. | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass, cast | ||||
| from plyer.facades import Email | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Intent = autoclass('android.content.Intent') | ||||
| AndroidString = autoclass('java.lang.String') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidEmail(Email): | ||||
|     ''' | ||||
|     Implementation of Android email API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _send(self, **kwargs): | ||||
|         intent = Intent(Intent.ACTION_SEND) | ||||
|         intent.setType('text/plain') | ||||
| 
 | ||||
|         recipient = kwargs.get('recipient') | ||||
|         subject = kwargs.get('subject') | ||||
|         text = kwargs.get('text') | ||||
|         create_chooser = kwargs.get('create_chooser') | ||||
| 
 | ||||
|         if recipient: | ||||
|             intent.putExtra(Intent.EXTRA_EMAIL, [recipient]) | ||||
|         if subject: | ||||
|             android_subject = cast( | ||||
|                 'java.lang.CharSequence', | ||||
|                 AndroidString(subject) | ||||
|             ) | ||||
|             intent.putExtra(Intent.EXTRA_SUBJECT, android_subject) | ||||
|         if text: | ||||
|             android_text = cast( | ||||
|                 'java.lang.CharSequence', | ||||
|                 AndroidString(text) | ||||
|             ) | ||||
|             intent.putExtra(Intent.EXTRA_TEXT, android_text) | ||||
| 
 | ||||
|         if create_chooser: | ||||
|             chooser_title = cast( | ||||
|                 'java.lang.CharSequence', | ||||
|                 AndroidString('Send message with:') | ||||
|             ) | ||||
|             activity.startActivity( | ||||
|                 Intent.createChooser(intent, chooser_title) | ||||
|             ) | ||||
|         else: | ||||
|             activity.startActivity(intent) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return AndroidEmail() | ||||
							
								
								
									
										447
									
								
								sbapp/plyer/platforms/android/filechooser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										447
									
								
								sbapp/plyer/platforms/android/filechooser.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,447 @@ | ||||
| ''' | ||||
| Android file chooser | ||||
| -------------------- | ||||
| 
 | ||||
| Android runs ``Activity`` asynchronously via pausing our ``PythonActivity`` | ||||
| and starting a new one in the foreground. This means | ||||
| ``AndroidFileChooser._open_file()`` will always return the default value of | ||||
| ``AndroidFileChooser.selection`` i.e. ``None``. | ||||
| 
 | ||||
| After the ``Activity`` (for us it's the file chooser ``Intent``) is completed, | ||||
| Android moves it to the background (or destroys or whatever is implemented) | ||||
| and pushes ``PythonActivity`` to the foreground. | ||||
| 
 | ||||
| We have a custom listener for ``android.app.Activity.onActivityResult()`` | ||||
| via `android` package from `python-for-android` recipe, | ||||
| ``AndroidFileChooser._on_activity_result()`` which is called independently of | ||||
| any our action (we may call anything from our application in Python and this | ||||
| handler will be called nevertheless on each ``android.app.Activity`` result | ||||
| in the system). | ||||
| 
 | ||||
| In the handler we check if the ``request_code`` matches the code passed to the | ||||
| ``Context.startActivityForResult()`` i.e. if the result from | ||||
| ``android.app.Activity`` is indeed meant for our ``PythonActivity`` and then we | ||||
| proceed. | ||||
| 
 | ||||
| Since the ``android.app.Activity.onActivityResult()`` is the only way for us | ||||
| to intercept the result and we have a handler bound via ``android`` package, | ||||
| we need to get the path/file/... selection to the user the same way. | ||||
| 
 | ||||
| Threading + ``Thread.join()`` or ``time.sleep()`` or any other kind of waiting | ||||
| for the result is not an option because: | ||||
| 
 | ||||
| 1) ``android.app.Activity.onActivityResult()`` might remain unexecuted if | ||||
| the launched file chooser activity does not return the result (``Activity`` | ||||
| dies/freezes/etc). | ||||
| 
 | ||||
| 2) Thread will be still waiting for the result e.g. an update of a value or | ||||
| to actually finish, however the result from the call of | ||||
| ``AndroidFileChooser._open_file()`` will be returned nevertheless and anything | ||||
| using that result will use an incorrect one i.e. the default value of | ||||
| ``AndroidFilechooser.selection`` (``None``). | ||||
| 
 | ||||
| .. versionadded:: 1.4.0 | ||||
| ''' | ||||
| 
 | ||||
| from os.path import join, basename | ||||
| from random import randint | ||||
| 
 | ||||
| from android import activity, mActivity | ||||
| from jnius import autoclass, cast, JavaException | ||||
| from plyer.facades import FileChooser | ||||
| from plyer import storagepath | ||||
| 
 | ||||
| Environment = autoclass("android.os.Environment") | ||||
| String = autoclass('java.lang.String') | ||||
| Intent = autoclass('android.content.Intent') | ||||
| Activity = autoclass('android.app.Activity') | ||||
| DocumentsContract = autoclass('android.provider.DocumentsContract') | ||||
| ContentUris = autoclass('android.content.ContentUris') | ||||
| Uri = autoclass('android.net.Uri') | ||||
| Long = autoclass('java.lang.Long') | ||||
| IMedia = autoclass('android.provider.MediaStore$Images$Media') | ||||
| VMedia = autoclass('android.provider.MediaStore$Video$Media') | ||||
| AMedia = autoclass('android.provider.MediaStore$Audio$Media') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidFileChooser(FileChooser): | ||||
|     ''' | ||||
|     FileChooser implementation for Android using | ||||
|     the built-in file browser via Intent. | ||||
| 
 | ||||
|     .. versionadded:: 1.4.0 | ||||
|     ''' | ||||
| 
 | ||||
|     # filechooser activity <-> result pair identification | ||||
|     select_code = None | ||||
| 
 | ||||
|     # default selection value | ||||
|     selection = None | ||||
| 
 | ||||
|     # select multiple files | ||||
|     multiple = False | ||||
| 
 | ||||
|     # mime types | ||||
|     mime_type = { | ||||
|         "doc": "application/msword", | ||||
|         "docx": "application/vnd.openxmlformats-officedocument." + | ||||
|                 "wordprocessingml.document", | ||||
|         "ppt": "application/vnd.ms-powerpoint", | ||||
|         "pptx": "application/vnd.openxmlformats-officedocument." + | ||||
|                 "presentationml.presentation", | ||||
|         "xls": "application/vnd.ms-excel", | ||||
|         "xlsx": "application/vnd.openxmlformats-officedocument." + | ||||
|                 "spreadsheetml.sheet", | ||||
|         "text": "text/*", | ||||
|         "pdf": "application/pdf", | ||||
|         "zip": "application/zip", | ||||
|         "image": "image/*", | ||||
|         "video": "video/*", | ||||
|         "audio": "audio/*", | ||||
|         "application": "application/*"} | ||||
| 
 | ||||
|     selected_mime_type = None | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         self.select_code = randint(123456, 654321) | ||||
|         self.selection = None | ||||
| 
 | ||||
|         # bind a function for a response from filechooser activity | ||||
|         activity.bind(on_activity_result=self._on_activity_result) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _handle_selection(selection): | ||||
|         ''' | ||||
|         Dummy placeholder for returning selection from | ||||
|         ``android.app.Activity.onActivityResult()``. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
|         return selection | ||||
| 
 | ||||
|     def _open_file(self, **kwargs): | ||||
|         ''' | ||||
|         Running Android Activity is non-blocking and the only call | ||||
|         that blocks is onActivityResult running in GUI thread | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         # set up selection handler | ||||
|         # startActivityForResult is async | ||||
|         # onActivityResult is sync | ||||
|         self._handle_selection = kwargs.pop( | ||||
|             'on_selection', self._handle_selection | ||||
|         ) | ||||
|         self.selected_mime_type = \ | ||||
|             kwargs.pop("filters")[0] if "filters" in kwargs else "" | ||||
| 
 | ||||
|         # create Intent for opening | ||||
|         file_intent = Intent(Intent.ACTION_GET_CONTENT) | ||||
|         if not self.selected_mime_type or \ | ||||
|             type(self.selected_mime_type) != str or \ | ||||
|                 self.selected_mime_type not in self.mime_type: | ||||
|             file_intent.setType("*/*") | ||||
|         else: | ||||
|             file_intent.setType(self.mime_type[self.selected_mime_type]) | ||||
|         file_intent.addCategory( | ||||
|             Intent.CATEGORY_OPENABLE | ||||
|         ) | ||||
| 
 | ||||
|         # use putExtra to allow multiple file selection | ||||
|         if kwargs.get('multiple', self.multiple): | ||||
|             file_intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, True) | ||||
| 
 | ||||
|         # start a new activity from PythonActivity | ||||
|         # which creates a filechooser via intent | ||||
|         mActivity.startActivityForResult( | ||||
|             Intent.createChooser(file_intent, cast( | ||||
|                 'java.lang.CharSequence', | ||||
|                 String("FileChooser") | ||||
|             )), | ||||
|             self.select_code | ||||
|         ) | ||||
| 
 | ||||
|     def _on_activity_result(self, request_code, result_code, data): | ||||
|         ''' | ||||
|         Listener for ``android.app.Activity.onActivityResult()`` assigned | ||||
|         via ``android.activity.bind()``. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         # not our response | ||||
|         if request_code != self.select_code: | ||||
|             return | ||||
| 
 | ||||
|         if result_code != Activity.RESULT_OK: | ||||
|             # The action had been cancelled. | ||||
|             return | ||||
| 
 | ||||
|         selection = [] | ||||
|         # Process multiple URI if multiple files selected | ||||
|         try: | ||||
|             for count in range(data.getClipData().getItemCount()): | ||||
|                 ele = self._resolve_uri( | ||||
|                     data.getClipData().getItemAt(count).getUri()) or [] | ||||
|                 selection.append(ele) | ||||
|         except Exception: | ||||
|             selection = [self._resolve_uri(data.getData()), ] | ||||
| 
 | ||||
|         # return value to object | ||||
|         self.selection = selection | ||||
|         # return value via callback | ||||
|         self._handle_selection(selection) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _handle_external_documents(uri): | ||||
|         ''' | ||||
|         Selection from the system filechooser when using ``Phone`` | ||||
|         or ``Internal storage`` or ``SD card`` option from menu. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         file_id = DocumentsContract.getDocumentId(uri) | ||||
|         file_type, file_name = file_id.split(':') | ||||
| 
 | ||||
|         # internal SD card mostly mounted as a files storage in phone | ||||
|         internal = storagepath.get_external_storage_dir() | ||||
| 
 | ||||
|         # external (removable) SD card i.e. microSD | ||||
|         external = storagepath.get_sdcard_dir() | ||||
|         try: | ||||
|             external_base = basename(external) | ||||
|         except TypeError: | ||||
|             external_base = basename(internal) | ||||
| 
 | ||||
|         # resolve sdcard path | ||||
|         sd_card = internal | ||||
| 
 | ||||
|         # because external might have /storage/.../1 or other suffix | ||||
|         # and file_type might be only a part of the real folder in /storage | ||||
|         if file_type in external_base or external_base in file_type: | ||||
|             sd_card = external | ||||
|         elif file_type == "home": | ||||
|             sd_card = join(Environment.getExternalStorageDirectory( | ||||
|             ).getAbsolutePath(), Environment.DIRECTORY_DOCUMENTS) | ||||
| 
 | ||||
|         return join(sd_card, file_name) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _handle_media_documents(uri): | ||||
|         ''' | ||||
|         Selection from the system filechooser when using ``Images`` | ||||
|         or ``Videos`` or ``Audio`` option from menu. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         file_id = DocumentsContract.getDocumentId(uri) | ||||
|         file_type, file_name = file_id.split(':') | ||||
|         selection = '_id=?' | ||||
| 
 | ||||
|         if file_type == 'image': | ||||
|             uri = IMedia.EXTERNAL_CONTENT_URI | ||||
|         elif file_type == 'video': | ||||
|             uri = VMedia.EXTERNAL_CONTENT_URI | ||||
|         elif file_type == 'audio': | ||||
|             uri = AMedia.EXTERNAL_CONTENT_URI | ||||
|         return file_name, selection, uri | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _handle_downloads_documents(uri): | ||||
|         ''' | ||||
|         Selection from the system filechooser when using ``Downloads`` | ||||
|         option from menu. Might not work all the time due to: | ||||
| 
 | ||||
|         1) invalid URI: | ||||
| 
 | ||||
|         jnius.jnius.JavaException: | ||||
|             JVM exception occurred: Unknown URI: | ||||
|             content://downloads/public_downloads/1034 | ||||
| 
 | ||||
|         2) missing URI / android permissions | ||||
| 
 | ||||
|         jnius.jnius.JavaException: | ||||
|             JVM exception occurred: | ||||
|             Permission Denial: reading | ||||
|             com.android.providers.downloads.DownloadProvider uri | ||||
|             content://downloads/all_downloads/1034 from pid=2532, uid=10455 | ||||
|             requires android.permission.ACCESS_ALL_DOWNLOADS, | ||||
|             or grantUriPermission() | ||||
| 
 | ||||
|         Workaround: | ||||
|             Selecting path from ``Phone`` -> ``Download`` -> ``<file>`` | ||||
|             (or ``Internal storage``) manually. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         # known locations, differ between machines | ||||
|         downloads = [ | ||||
|             'content://downloads/public_downloads', | ||||
|             'content://downloads/my_downloads', | ||||
| 
 | ||||
|             # all_downloads requires separate permission | ||||
|             # android.permission.ACCESS_ALL_DOWNLOADS | ||||
|             'content://downloads/all_downloads' | ||||
|         ] | ||||
| 
 | ||||
|         file_id = DocumentsContract.getDocumentId(uri) | ||||
|         try_uris = [ | ||||
|             ContentUris.withAppendedId( | ||||
|                 Uri.parse(down), Long.valueOf(file_id) | ||||
|             ) | ||||
|             for down in downloads | ||||
|         ] | ||||
| 
 | ||||
|         # try all known Download folder uris | ||||
|         # and handle JavaExceptions due to different locations | ||||
|         # for content:// downloads or missing permission | ||||
|         path = None | ||||
|         for down in try_uris: | ||||
|             try: | ||||
|                 path = AndroidFileChooser._parse_content( | ||||
|                     uri=down, projection=['_data'], | ||||
|                     selection=None, | ||||
|                     selection_args=None, | ||||
|                     sort_order=None | ||||
|                 ) | ||||
| 
 | ||||
|             except JavaException: | ||||
|                 import traceback | ||||
|                 traceback.print_exc() | ||||
| 
 | ||||
|             # we got a path, ignore the rest | ||||
|             if path: | ||||
|                 break | ||||
| 
 | ||||
|         # alternative approach to Downloads by joining | ||||
|         # all data items from Activity result | ||||
|         if not path: | ||||
|             for down in try_uris: | ||||
|                 try: | ||||
|                     path = AndroidFileChooser._parse_content( | ||||
|                         uri=down, projection=None, | ||||
|                         selection=None, | ||||
|                         selection_args=None, | ||||
|                         sort_order=None, | ||||
|                         index_all=True | ||||
|                     ) | ||||
| 
 | ||||
|                 except JavaException: | ||||
|                     import traceback | ||||
|                     traceback.print_exc() | ||||
| 
 | ||||
|                 # we got a path, ignore the rest | ||||
|                 if path: | ||||
|                     break | ||||
|         return path | ||||
| 
 | ||||
|     def _resolve_uri(self, uri): | ||||
|         ''' | ||||
|         Resolve URI input from ``android.app.Activity.onActivityResult()``. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         uri_authority = uri.getAuthority() | ||||
|         uri_scheme = uri.getScheme().lower() | ||||
| 
 | ||||
|         path = None | ||||
|         file_name = None | ||||
|         selection = None | ||||
|         downloads = None | ||||
| 
 | ||||
|         # This does not allow file selected from google photos or gallery | ||||
|         # or even any other file explorer to work | ||||
|         # not a document URI, nothing to convert from | ||||
|         # if not DocumentsContract.isDocumentUri(mActivity, uri): | ||||
|         #     return path | ||||
| 
 | ||||
|         if uri_authority == 'com.android.externalstorage.documents': | ||||
|             return self._handle_external_documents(uri) | ||||
| 
 | ||||
|         # in case a user selects a file from 'Downloads' section | ||||
|         # note: this won't be triggered if a user selects a path directly | ||||
|         #       e.g.: Phone -> Download -> <some file> | ||||
|         elif uri_authority == 'com.android.providers.downloads.documents': | ||||
|             path = downloads = self._handle_downloads_documents(uri) | ||||
| 
 | ||||
|         elif uri_authority == 'com.android.providers.media.documents': | ||||
|             file_name, selection, uri = self._handle_media_documents(uri) | ||||
| 
 | ||||
|         # parse content:// scheme to path | ||||
|         if uri_scheme == 'content' and not downloads: | ||||
|             try: | ||||
|                 path = self._parse_content( | ||||
|                     uri=uri, projection=['_data'], selection=selection, | ||||
|                     selection_args=file_name, sort_order=None | ||||
|                 ) | ||||
|             except JavaException:  # handles array error for selection_args | ||||
|                 path = self._parse_content( | ||||
|                     uri=uri, projection=['_data'], selection=selection, | ||||
|                     selection_args=[file_name], sort_order=None | ||||
|                 ) | ||||
| 
 | ||||
|         # nothing to parse, file:// will return a proper path | ||||
|         elif uri_scheme == 'file': | ||||
|             path = uri.getPath() | ||||
| 
 | ||||
|         return path | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _parse_content( | ||||
|             uri, projection, selection, selection_args, sort_order, | ||||
|             index_all=False | ||||
|     ): | ||||
|         ''' | ||||
|         Parser for ``content://`` URI returned by some Android resources. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         result = None | ||||
|         resolver = mActivity.getContentResolver() | ||||
|         read = Intent.FLAG_GRANT_READ_URI_PERMISSION | ||||
|         write = Intent.FLAG_GRANT_READ_URI_PERMISSION | ||||
|         persist = Intent.FLAG_GRANT_READ_URI_PERMISSION | ||||
| 
 | ||||
|         # grant permission for our activity | ||||
|         mActivity.grantUriPermission( | ||||
|             mActivity.getPackageName(), | ||||
|             uri, | ||||
|             read | write | persist | ||||
|         ) | ||||
| 
 | ||||
|         if not index_all: | ||||
|             cursor = resolver.query( | ||||
|                 uri, projection, selection, | ||||
|                 selection_args, sort_order | ||||
|             ) | ||||
| 
 | ||||
|             idx = cursor.getColumnIndex(projection[0]) | ||||
|             if idx != -1 and cursor.moveToFirst(): | ||||
|                 result = cursor.getString(idx) | ||||
|         else: | ||||
|             result = [] | ||||
|             cursor = resolver.query( | ||||
|                 uri, projection, selection, | ||||
|                 selection_args, sort_order | ||||
|             ) | ||||
|             while cursor.moveToNext(): | ||||
|                 for idx in range(cursor.getColumnCount()): | ||||
|                     result.append(cursor.getString(idx)) | ||||
|             result = '/'.join(result) | ||||
|         return result | ||||
| 
 | ||||
|     def _file_selection_dialog(self, **kwargs): | ||||
|         mode = kwargs.pop('mode', None) | ||||
|         if mode == 'open': | ||||
|             self._open_file(**kwargs) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidFileChooser() | ||||
							
								
								
									
										55
									
								
								sbapp/plyer/platforms/android/flash.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								sbapp/plyer/platforms/android/flash.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| # coding=utf-8 | ||||
| """ | ||||
| Flash | ||||
| ----- | ||||
| """ | ||||
| 
 | ||||
| from plyer.facades import Flash | ||||
| from jnius import autoclass | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Camera = autoclass("android.hardware.Camera") | ||||
| CameraParameters = autoclass("android.hardware.Camera$Parameters") | ||||
| SurfaceTexture = autoclass("android.graphics.SurfaceTexture") | ||||
| PackageManager = autoclass('android.content.pm.PackageManager') | ||||
| pm = activity.getPackageManager() | ||||
| flash_available = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH) | ||||
| 
 | ||||
| 
 | ||||
| class AndroidFlash(Flash): | ||||
|     _camera = None | ||||
| 
 | ||||
|     def _on(self): | ||||
|         if self._camera is None: | ||||
|             self._camera_open() | ||||
|         if not self._camera: | ||||
|             return | ||||
|         self._camera.setParameters(self._f_on) | ||||
| 
 | ||||
|     def _off(self): | ||||
|         if not self._camera: | ||||
|             return | ||||
|         self._camera.setParameters(self._f_off) | ||||
| 
 | ||||
|     def _release(self): | ||||
|         if not self._camera: | ||||
|             return | ||||
|         self._camera.stopPreview() | ||||
|         self._camera.release() | ||||
|         self._camera = None | ||||
| 
 | ||||
|     def _camera_open(self): | ||||
|         if not flash_available: | ||||
|             return | ||||
|         self._camera = Camera.open() | ||||
|         self._f_on = Camera.getParameters() | ||||
|         self._f_off = Camera.getParameters() | ||||
|         self._f_on.setFlashMode(CameraParameters.FLASH_MODE_TORCH) | ||||
|         self._f_off.setFlashMode(CameraParameters.FLASH_MODE_OFF) | ||||
|         self._camera.startPreview() | ||||
|         # Need this for Nexus 5 | ||||
|         self._camera.setPreviewTexture(SurfaceTexture(0)) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidFlash() | ||||
							
								
								
									
										82
									
								
								sbapp/plyer/platforms/android/gps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								sbapp/plyer/platforms/android/gps.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | ||||
| ''' | ||||
| Android GPS | ||||
| ----------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import GPS | ||||
| from plyer.platforms.android import activity | ||||
| from jnius import autoclass, java_method, PythonJavaClass | ||||
| 
 | ||||
| Looper = autoclass('android.os.Looper') | ||||
| LocationManager = autoclass('android.location.LocationManager') | ||||
| Context = autoclass('android.content.Context') | ||||
| 
 | ||||
| 
 | ||||
| class _LocationListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/location/LocationListener'] | ||||
| 
 | ||||
|     def __init__(self, root): | ||||
|         self.root = root | ||||
|         super().__init__() | ||||
| 
 | ||||
|     @java_method('(Landroid/location/Location;)V') | ||||
|     def onLocationChanged(self, location): | ||||
|         self.root.on_location( | ||||
|             lat=location.getLatitude(), | ||||
|             lon=location.getLongitude(), | ||||
|             speed=location.getSpeed(), | ||||
|             bearing=location.getBearing(), | ||||
|             altitude=location.getAltitude(), | ||||
|             accuracy=location.getAccuracy()) | ||||
| 
 | ||||
|     @java_method('(Ljava/lang/String;)V') | ||||
|     def onProviderEnabled(self, status): | ||||
|         if self.root.on_status: | ||||
|             self.root.on_status('provider-enabled', status) | ||||
| 
 | ||||
|     @java_method('(Ljava/lang/String;)V') | ||||
|     def onProviderDisabled(self, status): | ||||
|         if self.root.on_status: | ||||
|             self.root.on_status('provider-disabled', status) | ||||
| 
 | ||||
|     @java_method('(Ljava/lang/String;ILandroid/os/Bundle;)V') | ||||
|     def onStatusChanged(self, provider, status, extras): | ||||
|         if self.root.on_status: | ||||
|             s_status = 'unknown' | ||||
|             if status == 0x00: | ||||
|                 s_status = 'out-of-service' | ||||
|             elif status == 0x01: | ||||
|                 s_status = 'temporarily-unavailable' | ||||
|             elif status == 0x02: | ||||
|                 s_status = 'available' | ||||
|             self.root.on_status('provider-status', '{}: {}'.format( | ||||
|                 provider, s_status)) | ||||
| 
 | ||||
| 
 | ||||
| class AndroidGPS(GPS): | ||||
| 
 | ||||
|     def _configure(self): | ||||
|         if not hasattr(self, '_location_manager'): | ||||
|             self._location_manager = activity.getSystemService( | ||||
|                 Context.LOCATION_SERVICE | ||||
|             ) | ||||
|             self._location_listener = _LocationListener(self) | ||||
| 
 | ||||
|     def _start(self, **kwargs): | ||||
|         min_time = kwargs.get('minTime') | ||||
|         min_distance = kwargs.get('minDistance') | ||||
|         providers = self._location_manager.getProviders(False).toArray() | ||||
|         for provider in providers: | ||||
|             self._location_manager.requestLocationUpdates( | ||||
|                 provider, | ||||
|                 min_time,  # minTime, in milliseconds | ||||
|                 min_distance,  # minDistance, in meters | ||||
|                 self._location_listener, | ||||
|                 Looper.getMainLooper()) | ||||
| 
 | ||||
|     def _stop(self): | ||||
|         self._location_manager.removeUpdates(self._location_listener) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidGPS() | ||||
							
								
								
									
										84
									
								
								sbapp/plyer/platforms/android/gravity.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								sbapp/plyer/platforms/android/gravity.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | ||||
| ''' | ||||
| Android gravity | ||||
| --------------------- | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass | ||||
| from jnius import cast | ||||
| from jnius import java_method | ||||
| from jnius import PythonJavaClass | ||||
| 
 | ||||
| from plyer.facades import Gravity | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class GravitySensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
| 
 | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_GRAVITY | ||||
|         ) | ||||
| 
 | ||||
|         self.values = [None, None, 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.values = event.values[:3] | ||||
| 
 | ||||
|     @java_method('(Landroid/hardware/Sensor;I)V') | ||||
|     def onAccuracyChanged(self, sensor, accuracy): | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class AndroidGravity(Gravity): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.state = False | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         if not self.state: | ||||
|             self.listener = GravitySensorListener() | ||||
|             self.listener.enable() | ||||
|             self.state = True | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         if self.state: | ||||
|             self.state = False | ||||
|             self.listener.disable() | ||||
|             del self.listener | ||||
| 
 | ||||
|     def _get_gravity(self): | ||||
|         if self.state: | ||||
|             return tuple(self.listener.values) | ||||
|         else: | ||||
|             return (None, None, None) | ||||
| 
 | ||||
|     def __del__(self): | ||||
|         if self.state: | ||||
|             self._disable() | ||||
|         super().__del__() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidGravity() | ||||
							
								
								
									
										119
									
								
								sbapp/plyer/platforms/android/gyroscope.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								sbapp/plyer/platforms/android/gyroscope.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | ||||
| ''' | ||||
| Android Gyroscope | ||||
| ----------------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Gyroscope | ||||
| from jnius import PythonJavaClass, java_method, autoclass, cast | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class GyroscopeSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.SensorManager = cast( | ||||
|             'android.hardware.SensorManager', | ||||
|             activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         ) | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_GYROSCOPE | ||||
|         ) | ||||
| 
 | ||||
|         self.values = [None, None, 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.values = event.values[:3] | ||||
| 
 | ||||
|     @java_method('(Landroid/hardware/Sensor;I)V') | ||||
|     def onAccuracyChanged(self, sensor, accuracy): | ||||
|         # Maybe, do something in future? | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class GyroUncalibratedSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_GYROSCOPE_UNCALIBRATED) | ||||
|         self.values = [None, None, None, None, None, 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.values = event.values[:6] | ||||
| 
 | ||||
|     @java_method('(Landroid/hardware/Sensor;I)V') | ||||
|     def onAccuracyChanged(self, sensor, accuracy): | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class AndroidGyroscope(Gyroscope): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.bState = False | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         if (not self.bState): | ||||
|             self.listenerg = GyroscopeSensorListener() | ||||
|             self.listenergu = GyroUncalibratedSensorListener() | ||||
|             self.listenerg.enable() | ||||
|             self.listenergu.enable() | ||||
|             self.bState = True | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         if (self.bState): | ||||
|             self.bState = False | ||||
|             self.listenerg.disable() | ||||
|             self.listenergu.disable() | ||||
|             del self.listenerg | ||||
|             del self.listenergu | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         if (self.bState): | ||||
|             return tuple(self.listenerg.values) | ||||
|         else: | ||||
|             return (None, None, None) | ||||
| 
 | ||||
|     def _get_rotation_uncalib(self): | ||||
|         if (self.bState): | ||||
|             return tuple(self.listenergu.values) | ||||
|         else: | ||||
|             return (None, None, None, None, None, None) | ||||
| 
 | ||||
|     def __del__(self): | ||||
|         if(self.bState): | ||||
|             self._disable() | ||||
|         super().__del__() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidGyroscope() | ||||
							
								
								
									
										107
									
								
								sbapp/plyer/platforms/android/humidity.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								sbapp/plyer/platforms/android/humidity.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,107 @@ | ||||
| from jnius import autoclass | ||||
| from jnius import cast | ||||
| from jnius import java_method | ||||
| from jnius import PythonJavaClass | ||||
| from math import exp | ||||
| from plyer.facades import Humidity | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| ActivityInfo = autoclass('android.content.pm.ActivityInfo') | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class RelativeHumiditySensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_RELATIVE_HUMIDITY) | ||||
|         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 AmbientTemperatureSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_AMBIENT_TEMPERATURE) | ||||
|         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 AndroidHumidity(Humidity): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.state = False | ||||
| 
 | ||||
|     def _get_humidity(self): | ||||
|         if self.state: | ||||
|             m = 17.62 | ||||
|             Tn = 243.12 | ||||
|             Ta = 216.7 | ||||
|             Rh = self.listener_r.value | ||||
|             Tc = self.listener_a.value | ||||
|             A = 6.112 | ||||
|             K = 273.15 | ||||
|             humidity = (Ta * (Rh / 100) * A * exp(m * Tc / (Tn + Tc)) | ||||
|                         / (K + Tc)) | ||||
|             return humidity | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         if not self.state: | ||||
|             self.listener_r = RelativeHumiditySensorListener() | ||||
|             self.listener_a = AmbientTemperatureSensorListener() | ||||
|             self.listener_r.enable() | ||||
|             self.listener_a.enable() | ||||
|             self.state = True | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         if self.state: | ||||
|             self.listener_r.disable() | ||||
|             self.listener_a.disable() | ||||
|             self.state = False | ||||
|             delattr(self, 'listener_r') | ||||
|             delattr(self, 'listener_a') | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidHumidity() | ||||
							
								
								
									
										55
									
								
								sbapp/plyer/platforms/android/irblaster.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								sbapp/plyer/platforms/android/irblaster.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| from jnius import autoclass | ||||
| 
 | ||||
| from plyer.facades import IrBlaster | ||||
| from plyer.platforms.android import activity, SDK_INT, ANDROID_VERSION | ||||
| 
 | ||||
| if SDK_INT >= 19: | ||||
|     Context = autoclass('android.content.Context') | ||||
|     ir_manager = activity.getSystemService(Context.CONSUMER_IR_SERVICE) | ||||
| else: | ||||
|     ir_manager = None | ||||
| 
 | ||||
| 
 | ||||
| class AndroidIrBlaster(IrBlaster): | ||||
|     def _exists(self): | ||||
|         if ir_manager and ir_manager.hasIrEmitter(): | ||||
|             return True | ||||
|         return False | ||||
| 
 | ||||
|     @property | ||||
|     def multiply_pulse(self): | ||||
|         '''Android 4.4.3+ uses microseconds instead of period counts | ||||
|         ''' | ||||
|         return not (SDK_INT == 19 | ||||
|                     and int(str(ANDROID_VERSION.RELEASE).rsplit('.', 1)[-1]) | ||||
|                     < 3) | ||||
| 
 | ||||
|     def _get_frequencies(self): | ||||
|         if not ir_manager: | ||||
|             return None | ||||
| 
 | ||||
|         if hasattr(self, '_frequencies'): | ||||
|             return self._frequencies | ||||
| 
 | ||||
|         ir_frequencies = ir_manager.getCarrierFrequencies() | ||||
|         if not ir_frequencies: | ||||
|             return [] | ||||
| 
 | ||||
|         frequencies = [] | ||||
|         for freqrange in ir_frequencies: | ||||
|             freq = (freqrange.getMinFrequency(), freqrange.getMaxFrequency()) | ||||
|             frequencies.append(freq) | ||||
| 
 | ||||
|         self._frequencies = frequencies | ||||
|         return frequencies | ||||
| 
 | ||||
|     def _transmit(self, frequency, pattern, mode): | ||||
|         if self.multiply_pulse and mode == 'period': | ||||
|             pattern = self.periods_to_microseconds(frequency, pattern) | ||||
|         elif not self.multiply_pulse and mode == 'microseconds': | ||||
|             pattern = self.microseconds_to_periods(frequency, pattern) | ||||
|         ir_manager.transmit(frequency, pattern) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidIrBlaster() | ||||
							
								
								
									
										25
									
								
								sbapp/plyer/platforms/android/keystore.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								sbapp/plyer/platforms/android/keystore.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| from plyer.facades import Keystore | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| 
 | ||||
| class AndroidKeystore(Keystore): | ||||
| 
 | ||||
|     def _set_key(self, servicename, key, value, **kwargs): | ||||
|         mode = kwargs.get("mode", 0) | ||||
|         settings = activity.getSharedPreferences(servicename, mode) | ||||
|         editor = settings.edit() | ||||
|         editor.putString(key, value) | ||||
|         editor.commit() | ||||
| 
 | ||||
|     def _get_key(self, servicename, key, **kwargs): | ||||
|         mode = kwargs.get("mode", 0) | ||||
|         default = kwargs.get("default", "__None") | ||||
|         settings = activity.getSharedPreferences(servicename, mode) | ||||
|         ret = settings.getString(key, default) | ||||
|         if ret == "__None": | ||||
|             ret = None | ||||
|         return ret | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidKeystore() | ||||
							
								
								
									
										63
									
								
								sbapp/plyer/platforms/android/light.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								sbapp/plyer/platforms/android/light.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| from jnius import autoclass | ||||
| from jnius import cast | ||||
| from jnius import java_method | ||||
| from jnius 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().__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() | ||||
							
								
								
									
										208
									
								
								sbapp/plyer/platforms/android/notification.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								sbapp/plyer/platforms/android/notification.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,208 @@ | ||||
| ''' | ||||
| Module of Android API for plyer.notification. | ||||
| 
 | ||||
| .. versionadded:: 1.0.0 | ||||
| 
 | ||||
| .. versionchanged:: 1.4.0 | ||||
|     Fixed notifications not displaying due to missing NotificationChannel | ||||
|     required by Android Oreo 8.0+ (API 26+). | ||||
| 
 | ||||
| .. versionchanged:: 1.4.0 | ||||
|     Added simple toaster notification. | ||||
| 
 | ||||
| .. versionchanged:: 1.4.0 | ||||
|     Fixed notifications not displaying big icons properly. | ||||
|     Added option for custom big icon via `icon`. | ||||
| ''' | ||||
| 
 | ||||
| from android import python_act | ||||
| from android.runnable import run_on_ui_thread | ||||
| from jnius import autoclass, cast | ||||
| 
 | ||||
| from plyer.facades import Notification | ||||
| from plyer.platforms.android import activity, SDK_INT | ||||
| 
 | ||||
| AndroidString = autoclass('java.lang.String') | ||||
| Context = autoclass('android.content.Context') | ||||
| NotificationBuilder = autoclass('android.app.Notification$Builder') | ||||
| NotificationManager = autoclass('android.app.NotificationManager') | ||||
| PendingIntent = autoclass('android.app.PendingIntent') | ||||
| Intent = autoclass('android.content.Intent') | ||||
| Toast = autoclass('android.widget.Toast') | ||||
| BitmapFactory = autoclass('android.graphics.BitmapFactory') | ||||
| Icon = autoclass("android.graphics.drawable.Icon") | ||||
| 
 | ||||
| 
 | ||||
| class AndroidNotification(Notification): | ||||
|     ''' | ||||
|     Implementation of Android notification API. | ||||
| 
 | ||||
|     .. versionadded:: 1.0.0 | ||||
|     ''' | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         package_name = activity.getPackageName() | ||||
|         self._ns = None | ||||
|         self._channel_id = package_name | ||||
| 
 | ||||
|         pm = activity.getPackageManager() | ||||
|         info = pm.getActivityInfo(activity.getComponentName(), 0) | ||||
|         if info.icon == 0: | ||||
|             # Take the application icon instead. | ||||
|             info = pm.getApplicationInfo(package_name, 0) | ||||
| 
 | ||||
|         self._app_icon = info.icon | ||||
| 
 | ||||
|     def _get_notification_service(self): | ||||
|         if not self._ns: | ||||
|             self._ns = cast(NotificationManager, activity.getSystemService( | ||||
|                 Context.NOTIFICATION_SERVICE | ||||
|             )) | ||||
|         return self._ns | ||||
| 
 | ||||
|     def _build_notification_channel(self, name): | ||||
|         ''' | ||||
|         Create a NotificationChannel using channel id of the application | ||||
|         package name (com.xyz, org.xyz, ...) and channel name same as the | ||||
|         provided notification title if the API is high enough, otherwise | ||||
|         do nothing. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         if SDK_INT < 26: | ||||
|             return | ||||
| 
 | ||||
|         channel = autoclass('android.app.NotificationChannel') | ||||
| 
 | ||||
|         app_channel = channel( | ||||
|             self._channel_id, name, NotificationManager.IMPORTANCE_DEFAULT | ||||
|         ) | ||||
|         self._get_notification_service().createNotificationChannel( | ||||
|             app_channel | ||||
|         ) | ||||
|         return app_channel | ||||
| 
 | ||||
|     @run_on_ui_thread | ||||
|     def _toast(self, message): | ||||
|         ''' | ||||
|         Display a popup-like small notification at the bottom of the screen. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
|         Toast.makeText( | ||||
|             activity, | ||||
|             cast('java.lang.CharSequence', AndroidString(message)), | ||||
|             Toast.LENGTH_LONG | ||||
|         ).show() | ||||
| 
 | ||||
|     def _set_icons(self, notification, icon=None, notification_icon=None): | ||||
|         ''' | ||||
|         Set the small application icon displayed at the top panel together with | ||||
|         WiFi, battery percentage and time and the big optional icon (preferably | ||||
|         PNG format with transparent parts) displayed directly in the | ||||
|         notification body. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
|         if notification_icon == None: | ||||
|             app_icon = self._app_icon | ||||
|         else: | ||||
|             notification_icon_bitmap = BitmapFactory.decodeFile(notification_icon) | ||||
|             app_icon = Icon.createWithBitmap(notification_icon_bitmap) | ||||
| 
 | ||||
|         notification.setSmallIcon(app_icon) | ||||
| 
 | ||||
|         bitmap_icon = app_icon | ||||
|         if icon is not None: | ||||
|             bitmap_icon = BitmapFactory.decodeFile(icon) | ||||
|             notification.setLargeIcon(bitmap_icon) | ||||
|         elif icon == '': | ||||
|             # we don't want the big icon set, | ||||
|             # only the small one in the top panel | ||||
|             pass | ||||
|         else: | ||||
|             bitmap_icon = BitmapFactory.decodeResource( | ||||
|                 python_act.getResources(), app_icon | ||||
|             ) | ||||
|             notification.setLargeIcon(bitmap_icon) | ||||
| 
 | ||||
|     def _build_notification(self, title): | ||||
|         ''' | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
|         if SDK_INT < 26: | ||||
|             noti = NotificationBuilder(activity) | ||||
|         else: | ||||
|             self._channel = self._build_notification_channel(title) | ||||
|             noti = NotificationBuilder(activity, self._channel_id) | ||||
|         return noti | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _set_open_behavior(notification): | ||||
|         ''' | ||||
|         Open the source application when user opens the notification. | ||||
| 
 | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
| 
 | ||||
|         # create Intent that navigates back to the application | ||||
|         app_context = activity.getApplication().getApplicationContext() | ||||
|         notification_intent = Intent(app_context, python_act) | ||||
| 
 | ||||
|         # set flags to run our application Activity | ||||
|         notification_intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) | ||||
|         notification_intent.setAction(Intent.ACTION_MAIN) | ||||
|         notification_intent.addCategory(Intent.CATEGORY_LAUNCHER) | ||||
| 
 | ||||
|         # get our application Activity | ||||
|         pending_intent = PendingIntent.getActivity( | ||||
|             app_context, 0, notification_intent, 0 | ||||
|         ) | ||||
| 
 | ||||
|         notification.setContentIntent(pending_intent) | ||||
|         notification.setAutoCancel(True) | ||||
| 
 | ||||
|     def _open_notification(self, notification): | ||||
|         if SDK_INT >= 16: | ||||
|             notification = notification.build() | ||||
|         else: | ||||
|             notification = notification.getNotification() | ||||
| 
 | ||||
|         self._get_notification_service().notify(0, notification) | ||||
| 
 | ||||
|     def _notify(self, **kwargs): | ||||
|         noti = None | ||||
|         message = kwargs.get('message').encode('utf-8') | ||||
|         ticker = kwargs.get('ticker').encode('utf-8') | ||||
|         title = AndroidString( | ||||
|             kwargs.get('title', '').encode('utf-8') | ||||
|         ) | ||||
|         icon = kwargs.get('app_icon') | ||||
|         notification_icon = kwargs.get('notification_icon') | ||||
| 
 | ||||
|         # decide whether toast only or proper notification | ||||
|         if kwargs.get('toast'): | ||||
|             self._toast(message) | ||||
|             return | ||||
|         else: | ||||
|             noti = self._build_notification(title) | ||||
| 
 | ||||
|         # set basic properties for notification | ||||
|         noti.setContentTitle(title) | ||||
|         noti.setContentText(AndroidString(message)) | ||||
|         noti.setTicker(AndroidString(ticker)) | ||||
| 
 | ||||
|         # set additional flags for notification | ||||
|         self._set_icons(noti, icon=icon, notification_icon=notification_icon) | ||||
|         self._set_open_behavior(noti) | ||||
| 
 | ||||
|         # launch | ||||
|         self._open_notification(noti) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return AndroidNotification() | ||||
							
								
								
									
										43
									
								
								sbapp/plyer/platforms/android/orientation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								sbapp/plyer/platforms/android/orientation.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| from jnius import autoclass | ||||
| from plyer.platforms.android import activity | ||||
| from plyer.facades import Orientation | ||||
| 
 | ||||
| ActivityInfo = autoclass('android.content.pm.ActivityInfo') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidOrientation(Orientation): | ||||
| 
 | ||||
|     def _set_landscape(self, **kwargs): | ||||
|         reverse = kwargs.get('reverse') | ||||
|         if reverse: | ||||
|             activity.setRequestedOrientation( | ||||
|                 ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) | ||||
|         else: | ||||
|             activity.setRequestedOrientation( | ||||
|                 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) | ||||
| 
 | ||||
|     def _set_portrait(self, **kwargs): | ||||
|         reverse = kwargs.get('reverse') | ||||
|         if reverse: | ||||
|             activity.setRequestedOrientation( | ||||
|                 ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) | ||||
|         else: | ||||
|             activity.setRequestedOrientation( | ||||
|                 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) | ||||
| 
 | ||||
|     def _set_sensor(self, **kwargs): | ||||
|         mode = kwargs.get('mode') | ||||
| 
 | ||||
|         if mode == 'any': | ||||
|             activity.setRequestedOrientation( | ||||
|                 ActivityInfo.SCREEN_ORIENTATION_SENSOR) | ||||
|         elif mode == 'landscape': | ||||
|             activity.setRequestedOrientation( | ||||
|                 ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) | ||||
|         elif mode == 'portrait': | ||||
|             activity.setRequestedOrientation( | ||||
|                 ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidOrientation() | ||||
							
								
								
									
										69
									
								
								sbapp/plyer/platforms/android/proximity.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								sbapp/plyer/platforms/android/proximity.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | ||||
| from jnius import autoclass | ||||
| from jnius import cast | ||||
| from jnius import java_method | ||||
| from jnius import PythonJavaClass | ||||
| 
 | ||||
| from plyer.platforms.android import activity | ||||
| from plyer.facades import Proximity | ||||
| 
 | ||||
| ActivityInfo = autoclass('android.content.pm.ActivityInfo') | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class ProximitySensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_PROXIMITY) | ||||
|         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 AndroidProximity(Proximity): | ||||
| 
 | ||||
|     listener = None | ||||
| 
 | ||||
|     def _enable(self, **kwargs): | ||||
|         if not self.listener: | ||||
|             self.listener = ProximitySensorListener() | ||||
|             self.listener.enable() | ||||
| 
 | ||||
|     def _disable(self, **kwargs): | ||||
|         if self.listener: | ||||
|             self.listener.disable() | ||||
|             delattr(self, 'listener') | ||||
| 
 | ||||
|     def _get_proximity(self): | ||||
|         if self.listener: | ||||
|             value = self.listener.value | ||||
|             # value is 0.0 when proxime sensor is covered. In other case | ||||
|             # value is 5.0 because in smartphone, optical proximity sensors | ||||
|             # are used. | ||||
|             return value < 5.0 | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidProximity() | ||||
							
								
								
									
										25
									
								
								sbapp/plyer/platforms/android/sms.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								sbapp/plyer/platforms/android/sms.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| ''' | ||||
| Android SMS | ||||
| ----------- | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass | ||||
| from plyer.facades import Sms | ||||
| 
 | ||||
| SmsManager = autoclass('android.telephony.SmsManager') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidSms(Sms): | ||||
| 
 | ||||
|     def _send(self, **kwargs): | ||||
|         sms = SmsManager.getDefault() | ||||
| 
 | ||||
|         recipient = kwargs.get('recipient') | ||||
|         message = kwargs.get('message') | ||||
| 
 | ||||
|         if sms: | ||||
|             sms.sendTextMessage(recipient, None, message, None, None) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidSms() | ||||
							
								
								
									
										118
									
								
								sbapp/plyer/platforms/android/spatialorientation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								sbapp/plyer/platforms/android/spatialorientation.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,118 @@ | ||||
| from jnius import autoclass | ||||
| from jnius import cast | ||||
| from jnius import java_method | ||||
| from jnius import PythonJavaClass | ||||
| from plyer.platforms.android import activity | ||||
| from plyer.facades import SpatialOrientation | ||||
| 
 | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class AccelerometerSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.SensorManager = cast( | ||||
|             'android.hardware.SensorManager', | ||||
|             activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         ) | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_ACCELEROMETER | ||||
|         ) | ||||
|         self.values = [None, None, 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.values = event.values[:3] | ||||
| 
 | ||||
|     @java_method('(Landroid/hardware/Sensor;I)V') | ||||
|     def onAccuracyChanged(self, sensor, accuracy): | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class MagnetometerSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_MAGNETIC_FIELD) | ||||
|         self.values = [None, None, 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.values = event.values[:3] | ||||
| 
 | ||||
|     @java_method('(Landroid/hardware/Sensor;I)V') | ||||
|     def onAccuracyChanged(self, sensor, accuracy): | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class AndroidSpOrientation(SpatialOrientation): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.state = False | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         if self.state: | ||||
|             rotation = [0] * 9 | ||||
|             inclination = [0] * 9 | ||||
|             gravity = [] | ||||
|             geomagnetic = [] | ||||
|             gravity = self.listener_a.values | ||||
|             geomagnetic = self.listener_m.values | ||||
|             if gravity[0] is not None and geomagnetic[0] is not None: | ||||
|                 ff_state = SensorManager.getRotationMatrix( | ||||
|                     rotation, inclination, | ||||
|                     gravity, geomagnetic | ||||
|                 ) | ||||
|                 if ff_state: | ||||
|                     values = [0, 0, 0] | ||||
|                     values = SensorManager.getOrientation( | ||||
|                         rotation, values | ||||
|                     ) | ||||
|                 return values | ||||
| 
 | ||||
|     def _enable_listener(self, **kwargs): | ||||
|         if not self.state: | ||||
|             self.listener_a = AccelerometerSensorListener() | ||||
|             self.listener_m = MagnetometerSensorListener() | ||||
|             self.listener_a.enable() | ||||
|             self.listener_m.enable() | ||||
|             self.state = True | ||||
| 
 | ||||
|     def _disable_listener(self, **kwargs): | ||||
|         if self.state: | ||||
|             self.listener_a.disable() | ||||
|             self.listener_m.disable() | ||||
|             self.state = False | ||||
|             delattr(self, 'listener_a') | ||||
|             delattr(self, 'listener_m') | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidSpOrientation() | ||||
							
								
								
									
										69
									
								
								sbapp/plyer/platforms/android/storagepath.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										69
									
								
								sbapp/plyer/platforms/android/storagepath.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,69 @@ | ||||
| ''' | ||||
| Android Storage Path | ||||
| -------------------- | ||||
| ''' | ||||
| 
 | ||||
| from os import listdir, access, R_OK | ||||
| from os.path import join | ||||
| from plyer.facades import StoragePath | ||||
| from jnius import autoclass | ||||
| from android import mActivity | ||||
| 
 | ||||
| Environment = autoclass('android.os.Environment') | ||||
| Context = autoclass('android.content.Context') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidStoragePath(StoragePath): | ||||
| 
 | ||||
|     def _get_home_dir(self): | ||||
|         return Environment.getDataDirectory().getAbsolutePath() | ||||
| 
 | ||||
|     def _get_external_storage_dir(self): | ||||
|         return Environment.getExternalStorageDirectory().getAbsolutePath() | ||||
| 
 | ||||
|     def _get_sdcard_dir(self): | ||||
|         ''' | ||||
|         .. versionadded:: 1.4.0 | ||||
|         ''' | ||||
|         # folder in /storage/ that is readable | ||||
|         # and is not internal SD card | ||||
|         path = None | ||||
|         for folder in listdir('/storage'): | ||||
|             folder = join('/storage', folder) | ||||
|             if folder in self._get_external_storage_dir(): | ||||
|                 continue | ||||
|             if not access(folder, R_OK): | ||||
|                 continue | ||||
|             path = folder | ||||
|             break | ||||
|         return path | ||||
| 
 | ||||
|     def _get_root_dir(self): | ||||
|         return Environment.getRootDirectory().getAbsolutePath() | ||||
| 
 | ||||
|     def _get_documents_dir(self): | ||||
|         return Environment.getExternalStoragePublicDirectory( | ||||
|             Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() | ||||
| 
 | ||||
|     def _get_downloads_dir(self): | ||||
|         return Environment.getExternalStoragePublicDirectory( | ||||
|             Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() | ||||
| 
 | ||||
|     def _get_videos_dir(self): | ||||
|         return Environment.getExternalStoragePublicDirectory( | ||||
|             Environment.DIRECTORY_MOVIES).getAbsolutePath() | ||||
| 
 | ||||
|     def _get_music_dir(self): | ||||
|         return Environment.getExternalStoragePublicDirectory( | ||||
|             Environment.DIRECTORY_MUSIC).getAbsolutePath() | ||||
| 
 | ||||
|     def _get_pictures_dir(self): | ||||
|         return Environment.getExternalStoragePublicDirectory( | ||||
|             Environment.DIRECTORY_PICTURES).getAbsolutePath() | ||||
| 
 | ||||
|     def _get_application_dir(self): | ||||
|         return mActivity.getFilesDir().getParentFile().getParent() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidStoragePath() | ||||
							
								
								
									
										252
									
								
								sbapp/plyer/platforms/android/stt.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								sbapp/plyer/platforms/android/stt.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,252 @@ | ||||
| from android.runnable import run_on_ui_thread | ||||
| 
 | ||||
| from jnius import autoclass | ||||
| from jnius import java_method | ||||
| from jnius import PythonJavaClass | ||||
| 
 | ||||
| from plyer.facades import STT | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| ArrayList = autoclass('java.util.ArrayList') | ||||
| Bundle = autoclass('android.os.Bundle') | ||||
| Context = autoclass('android.content.Context') | ||||
| Intent = autoclass('android.content.Intent') | ||||
| RecognizerIntent = autoclass('android.speech.RecognizerIntent') | ||||
| RecognitionListener = autoclass('android.speech.RecognitionListener') | ||||
| SpeechRecognizer = autoclass('android.speech.SpeechRecognizer') | ||||
| 
 | ||||
| SpeechResults = SpeechRecognizer.RESULTS_RECOGNITION | ||||
| 
 | ||||
| 
 | ||||
| class SpeechListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/speech/RecognitionListener'] | ||||
| 
 | ||||
|     # class variables because PythonJavaClass class failed | ||||
|     # to see them later in getters and setters | ||||
|     _error_callback = None | ||||
|     _result_callback = None | ||||
|     _partial_result_callback = None | ||||
|     _volume_callback = None | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
| 
 | ||||
|         # overwrite class variables in the object | ||||
|         self._error_callback = None | ||||
|         self._result_callback = None | ||||
|         self._partial_result_callback = None | ||||
|         self._volume_callback = None | ||||
| 
 | ||||
|     # error handling | ||||
|     @property | ||||
|     def error_callback(self): | ||||
|         return self._error_callback | ||||
| 
 | ||||
|     @error_callback.setter | ||||
|     def error_callback(self, callback): | ||||
|         ''' | ||||
|         Set error callback. It is called when error occurs. | ||||
| 
 | ||||
|         :param callback: function with one parameter for error message | ||||
|         ''' | ||||
| 
 | ||||
|         self._error_callback = callback | ||||
| 
 | ||||
|     # result handling | ||||
|     @property | ||||
|     def result_callback(self): | ||||
|         return self._result_callback | ||||
| 
 | ||||
|     @result_callback.setter | ||||
|     def result_callback(self, callback): | ||||
|         ''' | ||||
|         Set result callback. It is called when results are received. | ||||
| 
 | ||||
|         :param callback: function with one parameter for lists of strings | ||||
|         ''' | ||||
| 
 | ||||
|         self._result_callback = callback | ||||
| 
 | ||||
|     @property | ||||
|     def partial_result_callback(self): | ||||
|         return self._partial_result_callback | ||||
| 
 | ||||
|     @partial_result_callback.setter | ||||
|     def partial_result_callback(self, callback): | ||||
|         ''' | ||||
|         Set partial result callback. It is called when partial results are | ||||
|         received while the listener is still in listening mode. | ||||
| 
 | ||||
|         :param callback: function with one parameter for lists of strings | ||||
|         ''' | ||||
| 
 | ||||
|         self._partial_result_callback = callback | ||||
| 
 | ||||
|     # voice changes handling | ||||
|     @property | ||||
|     def volume_callback(self): | ||||
|         return self._volume_callback | ||||
| 
 | ||||
|     @volume_callback.setter | ||||
|     def volume_callback(self, callback): | ||||
|         ''' | ||||
|         Set volume voice callback. | ||||
| 
 | ||||
|         It is called when loudness of the voice changes. | ||||
| 
 | ||||
|         :param callback: function with one parameter for volume RMS dB (float). | ||||
|         ''' | ||||
|         self._volume_callback = callback | ||||
| 
 | ||||
|     # Implementation Java Interfaces | ||||
|     @java_method('()V') | ||||
|     def onBeginningOfSpeech(self): | ||||
|         pass | ||||
| 
 | ||||
|     @java_method('([B)V') | ||||
|     def onBufferReceived(self, buffer): | ||||
|         pass | ||||
| 
 | ||||
|     @java_method('()V') | ||||
|     def onEndOfSpeech(self): | ||||
|         pass | ||||
| 
 | ||||
|     @java_method('(I)V') | ||||
|     def onError(self, error): | ||||
|         msg = '' | ||||
|         if error == SpeechRecognizer.ERROR_AUDIO: | ||||
|             msg = 'audio' | ||||
|         if error == SpeechRecognizer.ERROR_CLIENT: | ||||
|             msg = 'client' | ||||
|         if error == SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS: | ||||
|             msg = 'insufficient_permissions' | ||||
|         if error == SpeechRecognizer.ERROR_NETWORK: | ||||
|             msg = 'network' | ||||
|         if error == SpeechRecognizer.ERROR_NETWORK_TIMEOUT: | ||||
|             msg = 'network_timeout' | ||||
|         if error == SpeechRecognizer.ERROR_NO_MATCH: | ||||
|             msg = 'no_match' | ||||
|         if error == SpeechRecognizer.ERROR_RECOGNIZER_BUSY: | ||||
|             msg = 'recognizer_busy' | ||||
|         if error == SpeechRecognizer.ERROR_SERVER: | ||||
|             msg = 'server' | ||||
|         if error == SpeechRecognizer.ERROR_SPEECH_TIMEOUT: | ||||
|             msg = 'speech_timeout' | ||||
| 
 | ||||
|         if msg and self.error_callback: | ||||
|             self.error_callback('error:' + msg) | ||||
| 
 | ||||
|     @java_method('(ILandroid/os/Bundle;)V') | ||||
|     def onEvent(self, event_type, params): | ||||
|         pass | ||||
| 
 | ||||
|     @java_method('(Landroid/os/Bundle;)V') | ||||
|     def onPartialResults(self, results): | ||||
|         texts = [] | ||||
|         matches = results.getStringArrayList(SpeechResults) | ||||
|         for match in matches.toArray(): | ||||
|             if isinstance(match, bytes): | ||||
|                 match = match.decode('utf-8') | ||||
|             texts.append(match) | ||||
| 
 | ||||
|         if texts and self.partial_result_callback: | ||||
|             self.partial_result_callback(texts) | ||||
| 
 | ||||
|     @java_method('(Landroid/os/Bundle;)V') | ||||
|     def onReadyForSpeech(self, params): | ||||
|         pass | ||||
| 
 | ||||
|     @java_method('(Landroid/os/Bundle;)V') | ||||
|     def onResults(self, results): | ||||
|         texts = [] | ||||
|         matches = results.getStringArrayList(SpeechResults) | ||||
|         for match in matches.toArray(): | ||||
|             if isinstance(match, bytes): | ||||
|                 match = match.decode('utf-8') | ||||
|             texts.append(match) | ||||
| 
 | ||||
|         if texts and self.result_callback: | ||||
|             self.result_callback(texts) | ||||
| 
 | ||||
|     @java_method('(F)V') | ||||
|     def onRmsChanged(self, rmsdB): | ||||
|         if self.volume_callback: | ||||
|             self.volume_callback(rmsdB) | ||||
| 
 | ||||
| 
 | ||||
| class AndroidSpeech(STT): | ||||
|     ''' | ||||
|     Android Speech Implementation. | ||||
| 
 | ||||
|     Android class `SpeechRecognizer`'s listening deactivates automatically. | ||||
| 
 | ||||
|     Class methods `_on_error()`, `_on_result()` listeners. You can find | ||||
|     documentation here: | ||||
|     https://developer.android.com/reference/android/speech/RecognitionListener | ||||
|     ''' | ||||
| 
 | ||||
|     def _on_error(self, msg): | ||||
|         self.errors.append(msg) | ||||
|         self.stop() | ||||
| 
 | ||||
|     def _on_result(self, messages): | ||||
|         self.results.extend(messages) | ||||
|         self.stop() | ||||
| 
 | ||||
|     def _on_partial(self, messages): | ||||
|         self.partial_results.extend(messages) | ||||
| 
 | ||||
|     @run_on_ui_thread | ||||
|     def _start(self): | ||||
|         intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) | ||||
|         intent.putExtra( | ||||
|             RecognizerIntent.EXTRA_CALLING_PACKAGE, | ||||
|             activity.getPackageName() | ||||
|         ) | ||||
| 
 | ||||
|         # language preferences | ||||
|         intent.putExtra( | ||||
|             RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, self.language | ||||
|         ) | ||||
|         intent.putExtra( | ||||
|             RecognizerIntent.EXTRA_LANGUAGE_MODEL, | ||||
|             RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH | ||||
|         ) | ||||
| 
 | ||||
|         # results settings | ||||
|         intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1000) | ||||
|         intent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, True) | ||||
|         if self.prefer_offline: | ||||
|             intent.putExtra(RecognizerIntent.EXTRA_PREFER_OFFLINE, True) | ||||
| 
 | ||||
|         # listener and callbacks | ||||
|         listener = SpeechListener() | ||||
|         listener.error_callback = self._on_error | ||||
|         listener.result_callback = self._on_result | ||||
|         listener.partial_result_callback = self._on_partial | ||||
| 
 | ||||
|         # create recognizer and start | ||||
|         self.speech = SpeechRecognizer.createSpeechRecognizer(activity) | ||||
|         self.speech.setRecognitionListener(listener) | ||||
|         self.speech.startListening(intent) | ||||
| 
 | ||||
|     @run_on_ui_thread | ||||
|     def _stop(self): | ||||
|         if not self.speech: | ||||
|             return | ||||
| 
 | ||||
|         # stop listening | ||||
|         self.speech.stopListening() | ||||
| 
 | ||||
|         # free object | ||||
|         self.speech.destroy() | ||||
|         self.speech = None | ||||
| 
 | ||||
|     def _exist(self): | ||||
|         return bool( | ||||
|             SpeechRecognizer.isRecognitionAvailable(activity) | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidSpeech() | ||||
							
								
								
									
										66
									
								
								sbapp/plyer/platforms/android/temperature.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								sbapp/plyer/platforms/android/temperature.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| from jnius import autoclass | ||||
| from jnius import cast | ||||
| from jnius import java_method | ||||
| from jnius import PythonJavaClass | ||||
| 
 | ||||
| from plyer.facades import Temperature | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| ActivityInfo = autoclass('android.content.pm.ActivityInfo') | ||||
| Context = autoclass('android.content.Context') | ||||
| Sensor = autoclass('android.hardware.Sensor') | ||||
| SensorManager = autoclass('android.hardware.SensorManager') | ||||
| 
 | ||||
| 
 | ||||
| class TemperatureSensorListener(PythonJavaClass): | ||||
|     __javainterfaces__ = ['android/hardware/SensorEventListener'] | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         service = activity.getSystemService(Context.SENSOR_SERVICE) | ||||
|         self.SensorManager = cast('android.hardware.SensorManager', service) | ||||
| 
 | ||||
|         self.sensor = self.SensorManager.getDefaultSensor( | ||||
|             Sensor.TYPE_AMBIENT_TEMPERATURE) | ||||
|         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 AndroidTemperature(Temperature): | ||||
| 
 | ||||
|     listener = None | ||||
| 
 | ||||
|     def _get_temperature(self): | ||||
|         if self.listener and self.listener.value: | ||||
|             temperature = self.listener.value | ||||
|             return temperature | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         if not self.listener: | ||||
|             self.listener = TemperatureSensorListener() | ||||
|             self.listener.enable() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         if self.listener: | ||||
|             self.listener.disable() | ||||
|             delattr(self, 'listener') | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidTemperature() | ||||
							
								
								
									
										34
									
								
								sbapp/plyer/platforms/android/tts.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								sbapp/plyer/platforms/android/tts.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| from time import sleep | ||||
| from jnius import autoclass | ||||
| from plyer.facades import TTS | ||||
| from plyer.platforms.android import activity | ||||
| 
 | ||||
| Locale = autoclass('java.util.Locale') | ||||
| TextToSpeech = autoclass('android.speech.tts.TextToSpeech') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidTextToSpeech(TTS): | ||||
|     def _speak(self, **kwargs): | ||||
|         tts = TextToSpeech(activity, None) | ||||
| 
 | ||||
|         tts.setLanguage(Locale.US) | ||||
| 
 | ||||
|         retries = 0  # First try rarely succeeds due to some timing issue | ||||
|         message = kwargs.get('message') | ||||
| 
 | ||||
|         # first try for while loop | ||||
|         speak_status = tts.speak( | ||||
|             message, TextToSpeech.QUEUE_FLUSH, None | ||||
|         ) | ||||
| 
 | ||||
|         # -1 indicates error. Let's wait and then try again | ||||
|         while retries < 100 and speak_status == -1: | ||||
|             sleep(0.1) | ||||
|             retries += 1 | ||||
|             speak_status = tts.speak( | ||||
|                 message, TextToSpeech.QUEUE_FLUSH, None | ||||
|             ) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return AndroidTextToSpeech() | ||||
							
								
								
									
										28
									
								
								sbapp/plyer/platforms/android/uniqueid.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								sbapp/plyer/platforms/android/uniqueid.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| ''' | ||||
| Module of Android API for plyer.uniqueid. | ||||
| ''' | ||||
| 
 | ||||
| from jnius import autoclass | ||||
| from plyer.platforms.android import activity | ||||
| from plyer.facades import UniqueID | ||||
| 
 | ||||
| Secure = autoclass('android.provider.Settings$Secure') | ||||
| 
 | ||||
| 
 | ||||
| class AndroidUniqueID(UniqueID): | ||||
|     ''' | ||||
|     Implementation of Android uniqueid API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _get_uid(self): | ||||
|         return Secure.getString( | ||||
|             activity.getContentResolver(), | ||||
|             Secure.ANDROID_ID | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return AndroidUniqueID() | ||||
							
								
								
									
										63
									
								
								sbapp/plyer/platforms/android/vibrator.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								sbapp/plyer/platforms/android/vibrator.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| """Implementation Vibrator for Android.""" | ||||
| 
 | ||||
| from jnius import autoclass, cast | ||||
| from plyer.facades import Vibrator | ||||
| from plyer.platforms.android import activity | ||||
| from plyer.platforms.android import SDK_INT | ||||
| 
 | ||||
| Context = autoclass("android.content.Context") | ||||
| vibrator_service = activity.getSystemService(Context.VIBRATOR_SERVICE) | ||||
| vibrator = cast("android.os.Vibrator", vibrator_service) | ||||
| if SDK_INT >= 26: | ||||
|     VibrationEffect = autoclass("android.os.VibrationEffect") | ||||
| 
 | ||||
| 
 | ||||
| class AndroidVibrator(Vibrator): | ||||
|     """Android Vibrator class. | ||||
| 
 | ||||
|     Supported features: | ||||
|         * vibrate for some period of time. | ||||
|         * vibrate from given pattern. | ||||
|         * cancel vibration. | ||||
|         * check whether Vibrator exists. | ||||
|     """ | ||||
| 
 | ||||
|     def _vibrate(self, time=None, **kwargs): | ||||
|         if vibrator: | ||||
|             if SDK_INT >= 26: | ||||
|                 vibrator.vibrate( | ||||
|                     VibrationEffect.createOneShot( | ||||
|                         int(1000 * time), VibrationEffect.DEFAULT_AMPLITUDE | ||||
|                     ) | ||||
|                 ) | ||||
|             else: | ||||
|                 vibrator.vibrate(int(1000 * time)) | ||||
| 
 | ||||
|     def _pattern(self, pattern=None, repeat=None, **kwargs): | ||||
|         pattern = [int(1000 * time) for time in pattern] | ||||
| 
 | ||||
|         if vibrator: | ||||
|             if SDK_INT >= 26: | ||||
|                 vibrator.vibrate( | ||||
|                     VibrationEffect.createWaveform(pattern, repeat) | ||||
|                 ) | ||||
|             else: | ||||
|                 vibrator.vibrate(pattern, repeat) | ||||
| 
 | ||||
|     def _exists(self, **kwargs): | ||||
|         if SDK_INT >= 11: | ||||
|             return vibrator.hasVibrator() | ||||
|         elif vibrator_service is None: | ||||
|             raise NotImplementedError() | ||||
|         return True | ||||
| 
 | ||||
|     def _cancel(self, **kwargs): | ||||
|         vibrator.cancel() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     """Returns Vibrator with android features. | ||||
| 
 | ||||
|     :return: instance of class AndroidVibrator | ||||
|     """ | ||||
|     return AndroidVibrator() | ||||
							
								
								
									
										0
									
								
								sbapp/plyer/platforms/ios/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								sbapp/plyer/platforms/ios/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										34
									
								
								sbapp/plyer/platforms/ios/accelerometer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								sbapp/plyer/platforms/ios/accelerometer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| ''' | ||||
| iOS accelerometer | ||||
| ----------------- | ||||
| 
 | ||||
| Taken from: http://pyobjus.readthedocs.org/en/latest/pyobjus_ios.html \ | ||||
|             #accessing-accelerometer | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Accelerometer | ||||
| from pyobjus import autoclass | ||||
| 
 | ||||
| 
 | ||||
| class IosAccelerometer(Accelerometer): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.bridge = autoclass('bridge').alloc().init() | ||||
|         self.bridge.motionManager.setAccelerometerUpdateInterval_(0.1) | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         self.bridge.startAccelerometer() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         self.bridge.stopAccelerometer() | ||||
| 
 | ||||
|     def _get_acceleration(self): | ||||
|         return ( | ||||
|             self.bridge.ac_x, | ||||
|             self.bridge.ac_y, | ||||
|             self.bridge.ac_z) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IosAccelerometer() | ||||
							
								
								
									
										31
									
								
								sbapp/plyer/platforms/ios/barometer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								sbapp/plyer/platforms/ios/barometer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| ''' | ||||
| iOS Barometer | ||||
| ------------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Barometer | ||||
| from pyobjus import autoclass | ||||
| 
 | ||||
| 
 | ||||
| class iOSBarometer(Barometer): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.bridge = autoclass('bridge').alloc().init() | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         self.bridge.startRelativeAltitude() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         self.bridge.stopRelativeAltitude() | ||||
| 
 | ||||
|     def _get_pressure(self): | ||||
|         ''' | ||||
|         1 kPa = 10 hPa | ||||
|         ''' | ||||
|         return ( | ||||
|             self.bridge.pressure * 10) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return iOSBarometer() | ||||
							
								
								
									
										47
									
								
								sbapp/plyer/platforms/ios/battery.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								sbapp/plyer/platforms/ios/battery.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| ''' | ||||
| Module of iOS API for plyer.battery. | ||||
| ''' | ||||
| 
 | ||||
| from pyobjus import autoclass | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| from plyer.facades import Battery | ||||
| 
 | ||||
| load_framework('/System/Library/Frameworks/UIKit.framework') | ||||
| UIDevice = autoclass('UIDevice') | ||||
| 
 | ||||
| 
 | ||||
| class IOSBattery(Battery): | ||||
|     ''' | ||||
|     Implementation of iOS battery API. | ||||
|     ''' | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.device = UIDevice.currentDevice() | ||||
| 
 | ||||
|     def _get_state(self): | ||||
|         status = {"isCharging": None, "percentage": None} | ||||
| 
 | ||||
|         if not self.device.batteryMonitoringEnabled: | ||||
|             self.device.setBatteryMonitoringEnabled_(True) | ||||
| 
 | ||||
|         if self.device.batteryState == 0: | ||||
|             is_charging = None | ||||
|         elif self.device.batteryState == 2: | ||||
|             is_charging = True | ||||
|         else: | ||||
|             is_charging = False | ||||
| 
 | ||||
|         percentage = self.device.batteryLevel * 100. | ||||
| 
 | ||||
|         status['isCharging'] = is_charging | ||||
|         status['percentage'] = percentage | ||||
| 
 | ||||
|         return status | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return IOSBattery() | ||||
							
								
								
									
										27
									
								
								sbapp/plyer/platforms/ios/brightness.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								sbapp/plyer/platforms/ios/brightness.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| ''' | ||||
| iOS Brightness | ||||
| -------------- | ||||
| ''' | ||||
| 
 | ||||
| from pyobjus import autoclass | ||||
| from plyer.facades import Brightness | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| 
 | ||||
| load_framework('/System/Library/Frameworks/UIKit.framework') | ||||
| UIScreen = autoclass('UIScreen') | ||||
| 
 | ||||
| 
 | ||||
| class iOSBrightness(Brightness): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.screen = UIScreen.mainScreen() | ||||
| 
 | ||||
|     def _current_level(self): | ||||
|         return self.screen.brightness * 100 | ||||
| 
 | ||||
|     def set_level(self, level): | ||||
|         self.screen.brightness = level / 100 | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return iOSBrightness() | ||||
							
								
								
									
										29
									
								
								sbapp/plyer/platforms/ios/call.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								sbapp/plyer/platforms/ios/call.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| ''' | ||||
| IOS Call | ||||
| ---------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Call | ||||
| from pyobjus import autoclass, objc_str | ||||
| 
 | ||||
| NSURL = autoclass('NSURL') | ||||
| NSString = autoclass('NSString') | ||||
| UIApplication = autoclass('UIApplication') | ||||
| 
 | ||||
| 
 | ||||
| class IOSCall(Call): | ||||
| 
 | ||||
|     def _makecall(self, **kwargs): | ||||
|         tel = kwargs.get('tel') | ||||
|         url = "tel://" + tel | ||||
|         nsurl = NSURL.alloc().initWithString_(objc_str(url)) | ||||
| 
 | ||||
|         UIApplication.sharedApplication().openURL_(nsurl) | ||||
| 
 | ||||
|     def _dialcall(self, **kwargs): | ||||
|         pass | ||||
|         # Not possible, Access not provided by iPhone SDK | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IOSCall() | ||||
							
								
								
									
										52
									
								
								sbapp/plyer/platforms/ios/camera.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								sbapp/plyer/platforms/ios/camera.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| from os import remove | ||||
| from plyer.facades import Camera | ||||
| 
 | ||||
| from plyer.utils import reify | ||||
| 
 | ||||
| 
 | ||||
| class iOSCamera(Camera): | ||||
| 
 | ||||
|     @reify | ||||
|     def photos(self): | ||||
|         # pyPhotoLibrary is a ios recipe/module that | ||||
|         # interacts with the gallery and the camera on ios. | ||||
|         from photolibrary import PhotosLibrary | ||||
|         return PhotosLibrary() | ||||
| 
 | ||||
|     def _take_picture(self, on_complete, filename=None): | ||||
|         assert(on_complete is not None) | ||||
|         self.on_complete = on_complete | ||||
|         self.filename = filename | ||||
|         photos = self.photos | ||||
| 
 | ||||
|         if not photos.isCameraAvailable(): | ||||
|             # no camera hardware | ||||
|             return False | ||||
| 
 | ||||
|         photos.bind(on_image_captured=self.capture_callback) | ||||
|         self._capture_filename = filename | ||||
|         photos.capture_image(filename) | ||||
|         return True | ||||
| 
 | ||||
|     def capture_callback(self, photolibrary): | ||||
|         # Image was chosen | ||||
| 
 | ||||
|         # unbind | ||||
|         self.photos.unbind(on_image_captured=self.capture_callback) | ||||
| 
 | ||||
|         if self.on_complete(self.filename): | ||||
|             self._remove(self.filename) | ||||
| 
 | ||||
|     def _take_video(self, on_complete, filename=None): | ||||
|         assert(on_complete is not None) | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def _remove(self, fn): | ||||
|         try: | ||||
|             remove(fn) | ||||
|         except OSError: | ||||
|             print('Could not remove photo!') | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return iOSCamera() | ||||
							
								
								
									
										43
									
								
								sbapp/plyer/platforms/ios/compass.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								sbapp/plyer/platforms/ios/compass.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| ''' | ||||
| iOS Compass | ||||
| ----------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Compass | ||||
| from pyobjus import autoclass | ||||
| 
 | ||||
| 
 | ||||
| class IosCompass(Compass): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.bridge = autoclass('bridge').alloc().init() | ||||
|         self.bridge.motionManager.setMagnetometerUpdateInterval_(0.1) | ||||
|         self.bridge.motionManager.setDeviceMotionUpdateInterval_(0.1) | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         self.bridge.startMagnetometer() | ||||
|         self.bridge.startDeviceMotionWithReferenceFrame() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         self.bridge.stopMagnetometer() | ||||
|         self.bridge.stopDeviceMotion() | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         return ( | ||||
|             self.bridge.mf_x, | ||||
|             self.bridge.mf_y, | ||||
|             self.bridge.mf_z) | ||||
| 
 | ||||
|     def _get_field_uncalib(self): | ||||
|         return ( | ||||
|             self.bridge.mg_x, | ||||
|             self.bridge.mg_y, | ||||
|             self.bridge.mg_z, | ||||
|             self.bridge.mg_x - self.bridge.mf_x, | ||||
|             self.bridge.mg_y - self.bridge.mf_y, | ||||
|             self.bridge.mg_z - self.bridge.mf_z) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IosCompass() | ||||
							
								
								
									
										52
									
								
								sbapp/plyer/platforms/ios/email.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								sbapp/plyer/platforms/ios/email.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| ''' | ||||
| Module of iOS API for plyer.email. | ||||
| ''' | ||||
| 
 | ||||
| try: | ||||
|     from urllib.parse import quote | ||||
| except ImportError: | ||||
|     from urllib import quote | ||||
| 
 | ||||
| from plyer.facades import Email | ||||
| from pyobjus import autoclass, objc_str | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| 
 | ||||
| load_framework('/System/Library/Frameworks/UIKit.framework') | ||||
| 
 | ||||
| NSURL = autoclass('NSURL') | ||||
| NSString = autoclass('NSString') | ||||
| UIApplication = autoclass('UIApplication') | ||||
| 
 | ||||
| 
 | ||||
| class IOSEmail(Email): | ||||
|     ''' | ||||
|     Implementation of iOS battery API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _send(self, **kwargs): | ||||
|         recipient = kwargs.get('recipient') | ||||
|         subject = kwargs.get('subject') | ||||
|         text = kwargs.get('text') | ||||
| 
 | ||||
|         uri = "mailto:" | ||||
|         if recipient: | ||||
|             uri += str(recipient) | ||||
|         if subject: | ||||
|             uri += "?" if "?" not in uri else "&" | ||||
|             uri += "subject=" | ||||
|             uri += quote(str(subject)) | ||||
|         if text: | ||||
|             uri += "?" if "?" not in uri else "&" | ||||
|             uri += "body=" | ||||
|             uri += quote(str(text)) | ||||
| 
 | ||||
|         nsurl = NSURL.alloc().initWithString_(objc_str(uri)) | ||||
| 
 | ||||
|         UIApplication.sharedApplication().openURL_(nsurl) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return IOSEmail() | ||||
							
								
								
									
										81
									
								
								sbapp/plyer/platforms/ios/filechooser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								sbapp/plyer/platforms/ios/filechooser.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | ||||
| ''' | ||||
| IOS file chooser | ||||
| -------------------- | ||||
| 
 | ||||
| This module houses the iOS implementation of the plyer FileChooser. | ||||
| 
 | ||||
| .. versionadded:: 1.4.4 | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import FileChooser | ||||
| from pyobjus import autoclass, protocol | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| 
 | ||||
| 
 | ||||
| load_framework('/System/Library/Frameworks/Photos.framework') | ||||
| 
 | ||||
| 
 | ||||
| class IOSFileChooser(FileChooser): | ||||
|     ''' | ||||
|     FileChooser implementation for IOS using | ||||
|     the built-in file browser via UIImagePickerController. | ||||
| 
 | ||||
|     .. versionadded:: 1.4.0 | ||||
|     ''' | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         self._on_selection = None | ||||
| 
 | ||||
|     def _file_selection_dialog(self, *args, **kwargs): | ||||
|         """ | ||||
|         Function called when action is required, A "mode" parameter specifies | ||||
|         which and is one of "open", "save" or "dir". | ||||
|         """ | ||||
|         self._on_selection = kwargs["on_selection"] | ||||
|         if kwargs["mode"] == "open": | ||||
|             self._open() | ||||
|         else: | ||||
|             raise NotImplementedError() | ||||
| 
 | ||||
|     def _get_picker(self): | ||||
|         """ | ||||
|         Return an instantiated and configured UIImagePickerController. | ||||
|         """ | ||||
|         picker = autoclass("UIImagePickerController") | ||||
|         po = picker.alloc().init() | ||||
|         po.sourceType = 0 | ||||
|         po.delegate = self | ||||
|         return po | ||||
| 
 | ||||
|     def _open(self): | ||||
|         """ | ||||
|         Launch the native iOS file browser. Upon selection, the | ||||
|         `imagePickerController_didFinishPickingMediaWithInfo_` delegate is | ||||
|         called where we close the file browser and handle the result. | ||||
|         """ | ||||
|         picker = self._get_picker() | ||||
|         UIApplication = autoclass('UIApplication') | ||||
|         vc = UIApplication.sharedApplication().keyWindow.rootViewController() | ||||
|         vc.presentViewController_animated_completion_(picker, True, None) | ||||
| 
 | ||||
|     @protocol('UIImagePickerControllerDelegate') | ||||
|     def imagePickerController_didFinishPickingMediaWithInfo_( | ||||
|             self, image_picker, frozen_dict): | ||||
|         """ | ||||
|         Delegate which handles the result of the image selection process. | ||||
|         """ | ||||
|         image_picker.dismissViewControllerAnimated_completion_(True, None) | ||||
| 
 | ||||
|         # Note: We need to call this Objective C class as there is currently | ||||
|         #       no way to call a non-class function via pyobjus. And here, | ||||
|         #       we have to use the `UIImagePNGRepresentation` to get the png | ||||
|         #       representation. For this, please ensure you are using an | ||||
|         #       appropriate version of kivy-ios. | ||||
|         native_image_picker = autoclass("NativeImagePicker").alloc().init() | ||||
|         path = native_image_picker.writeToPNG_(frozen_dict) | ||||
|         self._on_selection([path.UTF8String()]) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IOSFileChooser() | ||||
							
								
								
									
										50
									
								
								sbapp/plyer/platforms/ios/flash.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								sbapp/plyer/platforms/ios/flash.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| # coding=utf-8 | ||||
| """ | ||||
| Flash | ||||
| ----- | ||||
| """ | ||||
| from plyer.facades import Flash | ||||
| from pyobjus import autoclass | ||||
| 
 | ||||
| NSString = autoclass("NSString") | ||||
| AVCaptureDevice = autoclass("AVCaptureDevice") | ||||
| AVMediaTypeVideo = NSString.alloc().initWithUTF8String_("vide") | ||||
| AVCaptureTorchModeOff = 0 | ||||
| AVCaptureTorchModeOn = 1 | ||||
| 
 | ||||
| 
 | ||||
| class IosFlash(Flash): | ||||
|     _camera = None | ||||
| 
 | ||||
|     def _on(self): | ||||
|         if self._camera is None: | ||||
|             self._camera_open() | ||||
|         if not self._camera: | ||||
|             return | ||||
|         self._camera.lockForConfiguration_(None) | ||||
|         try: | ||||
|             self._camera.setTorchMode(AVCaptureTorchModeOn) | ||||
|         finally: | ||||
|             self._camera.unlockForConfiguration() | ||||
| 
 | ||||
|     def _off(self): | ||||
|         if not self._camera: | ||||
|             return | ||||
|         self._camera.lockForConfiguration_(None) | ||||
|         try: | ||||
|             self._camera.setTorchMode(AVCaptureTorchModeOff) | ||||
|         finally: | ||||
|             self._camera.unlockForConfiguration() | ||||
| 
 | ||||
|     def _release(self): | ||||
|         pass | ||||
| 
 | ||||
|     def _camera_open(self): | ||||
|         device = AVCaptureDevice.defaultDeviceWithMediaType_(AVMediaTypeVideo) | ||||
|         if not device: | ||||
|             return | ||||
|         self._camera = device | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IosFlash() | ||||
							
								
								
									
										80
									
								
								sbapp/plyer/platforms/ios/gps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								sbapp/plyer/platforms/ios/gps.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| ''' | ||||
| iOS GPS | ||||
| ----------- | ||||
| ''' | ||||
| 
 | ||||
| from pyobjus import autoclass, protocol | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| from plyer.facades import GPS | ||||
| 
 | ||||
| load_framework('/System/Library/Frameworks/CoreLocation.framework') | ||||
| CLLocationManager = autoclass('CLLocationManager') | ||||
| 
 | ||||
| 
 | ||||
| class IosGPS(GPS): | ||||
|     def _configure(self): | ||||
|         if not hasattr(self, '_location_manager'): | ||||
|             self._location_manager = CLLocationManager.alloc().init() | ||||
| 
 | ||||
|     def _start(self, **kwargs): | ||||
|         self._location_manager.delegate = self | ||||
| 
 | ||||
|         self._location_manager.requestWhenInUseAuthorization() | ||||
|         # NSLocationWhenInUseUsageDescription key must exist in Info.plist | ||||
|         # file. When the authorization prompt is displayed your app goes | ||||
|         # into pause mode and if your app doesn't support background mode | ||||
|         # it will crash. | ||||
|         self._location_manager.startUpdatingLocation() | ||||
| 
 | ||||
|     def _stop(self): | ||||
|         self._location_manager.stopUpdatingLocation() | ||||
| 
 | ||||
|     @protocol('CLLocationManagerDelegate') | ||||
|     def locationManager_didChangeAuthorizationStatus_(self, manager, status): | ||||
|         if self.on_status: | ||||
|             s_status = '' | ||||
|             provider_status = '' | ||||
|             provider = 'standard-ios-provider' | ||||
|             if status == 0: | ||||
|                 provider_status = 'provider-disabled' | ||||
|                 s_status = 'notDetermined' | ||||
|             elif status == 1: | ||||
|                 provider_status = 'provider-enabled' | ||||
|                 s_status = 'restricted' | ||||
|             elif status == 2: | ||||
|                 provider_status = 'provider-disabled' | ||||
|                 s_status = 'denied' | ||||
|             elif status == 3: | ||||
|                 provider_status = 'provider-enabled' | ||||
|                 s_status = 'authorizedAlways' | ||||
|             elif status == 4: | ||||
|                 provider_status = 'provider-enabled' | ||||
|                 s_status = 'authorizedWhenInUse' | ||||
|             self.on_status(provider_status, '{}: {}'.format( | ||||
|                 provider, s_status)) | ||||
| 
 | ||||
|     @protocol('CLLocationManagerDelegate') | ||||
|     def locationManager_didUpdateLocations_(self, manager, locations): | ||||
|         location = manager.location | ||||
| 
 | ||||
|         description = location.description.UTF8String() | ||||
|         split_description = description.split('<')[-1].split('>')[0].split(',') | ||||
| 
 | ||||
|         lat, lon = [float(coord) for coord in split_description] | ||||
|         acc = float(description.split(' +/- ')[-1].split('m ')[0]) | ||||
| 
 | ||||
|         speed = location.speed | ||||
|         altitude = location.altitude | ||||
|         course = location.course | ||||
| 
 | ||||
|         self.on_location( | ||||
|             lat=lat, | ||||
|             lon=lon, | ||||
|             speed=speed, | ||||
|             bearing=course, | ||||
|             altitude=altitude, | ||||
|             accuracy=acc) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IosGPS() | ||||
							
								
								
									
										31
									
								
								sbapp/plyer/platforms/ios/gravity.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								sbapp/plyer/platforms/ios/gravity.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| ''' | ||||
| iOS Gravity | ||||
| ----------- | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Gravity | ||||
| from pyobjus import autoclass | ||||
| 
 | ||||
| 
 | ||||
| class iOSGravity(Gravity): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.bridge = autoclass('bridge').alloc().init() | ||||
|         self.bridge.motionManager.setDeviceMotionUpdateInterval_(0.1) | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         self.bridge.startDeviceMotion() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         self.bridge.stopDeviceMotion() | ||||
| 
 | ||||
|     def _get_gravity(self): | ||||
|         return ( | ||||
|             self.bridge.g_x, | ||||
|             self.bridge.g_y, | ||||
|             self.bridge.g_z) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return iOSGravity() | ||||
							
								
								
									
										55
									
								
								sbapp/plyer/platforms/ios/gyroscope.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								sbapp/plyer/platforms/ios/gyroscope.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| ''' | ||||
| iOS Gyroscope | ||||
| --------------------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Gyroscope | ||||
| from pyobjus import autoclass | ||||
| 
 | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| 
 | ||||
| load_framework('/System/Library/Frameworks/UIKit.framework') | ||||
| UIDevice = autoclass('UIDevice') | ||||
| 
 | ||||
| device = UIDevice.currentDevice() | ||||
| 
 | ||||
| 
 | ||||
| class IosGyroscope(Gyroscope): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.bridge = autoclass('bridge').alloc().init() | ||||
| 
 | ||||
|         if int(device.systemVersion.UTF8String().split('.')[0]) <= 4: | ||||
|             self.bridge.motionManager.setGyroscopeUpdateInterval_(0.1) | ||||
|         else: | ||||
|             self.bridge.motionManager.setGyroUpdateInterval_(0.1) | ||||
| 
 | ||||
|         self.bridge.motionManager.setDeviceMotionUpdateInterval_(0.1) | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         self.bridge.startGyroscope() | ||||
|         self.bridge.startDeviceMotion() | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         self.bridge.stopGyroscope() | ||||
|         self.bridge.stopDeviceMotion() | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         return ( | ||||
|             self.bridge.rotation_rate_x, | ||||
|             self.bridge.rotation_rate_y, | ||||
|             self.bridge.rotation_rate_z) | ||||
| 
 | ||||
|     def _get_rotation_uncalib(self): | ||||
|         return ( | ||||
|             self.bridge.gy_x, | ||||
|             self.bridge.gy_y, | ||||
|             self.bridge.gy_z, | ||||
|             self.bridge.gy_x - self.bridge.rotation_rate_x, | ||||
|             self.bridge.gy_y - self.bridge.rotation_rate_y, | ||||
|             self.bridge.gy_z - self.bridge.rotation_rate_z) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IosGyroscope() | ||||
							
								
								
									
										23
									
								
								sbapp/plyer/platforms/ios/keystore.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								sbapp/plyer/platforms/ios/keystore.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| from plyer.facades import Keystore | ||||
| from pyobjus import autoclass, objc_str | ||||
| 
 | ||||
| NSUserDefaults = autoclass('NSUserDefaults') | ||||
| 
 | ||||
| 
 | ||||
| class IosKeystore(Keystore): | ||||
| 
 | ||||
|     def _set_key(self, servicename, key, value, **kwargs): | ||||
|         NSUserDefaults.standardUserDefaults().setObject_forKey_( | ||||
|             objc_str(value), objc_str(key)) | ||||
| 
 | ||||
|     def _get_key(self, servicename, key, **kwargs): | ||||
|         ret = NSUserDefaults.standardUserDefaults().stringForKey_( | ||||
|             objc_str(key)) | ||||
|         if ret is not None: | ||||
|             return ret.UTF8String() | ||||
|         else: | ||||
|             return ret | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IosKeystore() | ||||
							
								
								
									
										43
									
								
								sbapp/plyer/platforms/ios/sms.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								sbapp/plyer/platforms/ios/sms.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| ''' | ||||
| IOS Sms | ||||
| ---------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Sms | ||||
| from pyobjus import autoclass, objc_str | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| 
 | ||||
| NSURL = autoclass('NSURL') | ||||
| NSString = autoclass('NSString') | ||||
| UIApplication = autoclass('UIApplication') | ||||
| load_framework('/System/Library/Frameworks/MessageUI.framework') | ||||
| 
 | ||||
| 
 | ||||
| class IOSSms(Sms): | ||||
| 
 | ||||
|     def _send(self, **kwargs): | ||||
|         ''' | ||||
|         This method provides sending messages to recipients. | ||||
| 
 | ||||
|         Expects 2 parameters in kwargs: | ||||
|             - recipient: String type | ||||
|             - message: String type | ||||
| 
 | ||||
|         Opens a message interface with recipient and message information. | ||||
|         ''' | ||||
|         recipient = kwargs.get('recipient') | ||||
|         message = kwargs.get('message') | ||||
|         url = "sms:" | ||||
|         if recipient: | ||||
|             # Apple has not supported multiple recipients yet. | ||||
|             url += str(recipient) | ||||
|         if message: | ||||
|             # Apple has to supported it yet. | ||||
|             pass | ||||
| 
 | ||||
|         nsurl = NSURL.alloc().initWithString_(objc_str(url)) | ||||
|         UIApplication.sharedApplication().openURL_(nsurl) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return IOSSms() | ||||
							
								
								
									
										31
									
								
								sbapp/plyer/platforms/ios/spatialorientation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								sbapp/plyer/platforms/ios/spatialorientation.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| ''' | ||||
| iOS Spatial Orientation | ||||
| ----------------------- | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import SpatialOrientation | ||||
| from pyobjus import autoclass | ||||
| 
 | ||||
| 
 | ||||
| class iOSSpatialOrientation(SpatialOrientation): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.bridge = autoclass('bridge').alloc().init() | ||||
|         self.bridge.motionManager.setDeviceMotionUpdateInterval_(0.1) | ||||
| 
 | ||||
|     def _enable_listener(self): | ||||
|         self.bridge.startDeviceMotion() | ||||
| 
 | ||||
|     def _disable_listener(self): | ||||
|         self.bridge.stopDeviceMotion() | ||||
| 
 | ||||
|     def _get_orientation(self): | ||||
|         return ( | ||||
|             self.bridge.sp_yaw, | ||||
|             self.bridge.sp_pitch, | ||||
|             self.bridge.sp_roll) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return iOSSpatialOrientation() | ||||
							
								
								
									
										62
									
								
								sbapp/plyer/platforms/ios/storagepath.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								sbapp/plyer/platforms/ios/storagepath.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | ||||
| ''' | ||||
| iOS Storage Path | ||||
| -------------------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import StoragePath | ||||
| from pyobjus import autoclass | ||||
| import os | ||||
| 
 | ||||
| NSFileManager = autoclass('NSFileManager') | ||||
| 
 | ||||
| # Directory constants (NSSearchPathDirectory enumeration) | ||||
| NSApplicationDirectory = 1 | ||||
| NSDocumentDirectory = 9 | ||||
| NSDownloadsDirectory = 15 | ||||
| NSMoviesDirectory = 17 | ||||
| NSMusicDirectory = 18 | ||||
| NSPicturesDirectory = 19 | ||||
| 
 | ||||
| 
 | ||||
| class iOSStoragePath(StoragePath): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.defaultManager = NSFileManager.defaultManager() | ||||
| 
 | ||||
|     def _get_home_dir(self): | ||||
|         return os.path.expanduser('~/') | ||||
| 
 | ||||
|     def _get_external_storage_dir(self): | ||||
|         return 'This feature is not implemented for this platform.' | ||||
| 
 | ||||
|     def _get_root_dir(self): | ||||
|         return 'This feature is not implemented for this platform.' | ||||
| 
 | ||||
|     def _get_documents_dir(self): | ||||
|         return self.defaultManager.URLsForDirectory_inDomains_( | ||||
|             NSDocumentDirectory, 1).firstObject().absoluteString.UTF8String() | ||||
| 
 | ||||
|     def _get_downloads_dir(self): | ||||
|         return self.defaultManager.URLsForDirectory_inDomains_( | ||||
|             NSDownloadsDirectory, 1).firstObject().absoluteString.UTF8String() | ||||
| 
 | ||||
|     def _get_videos_dir(self): | ||||
|         return self.defaultManager.URLsForDirectory_inDomains_( | ||||
|             NSMoviesDirectory, 1).firstObject().absoluteString.UTF8String() | ||||
| 
 | ||||
|     def _get_music_dir(self): | ||||
|         return self.defaultManager.URLsForDirectory_inDomains_( | ||||
|             NSMusicDirectory, 1).firstObject().absoluteString.UTF8String() | ||||
| 
 | ||||
|     def _get_pictures_dir(self): | ||||
|         return self.defaultManager.URLsForDirectory_inDomains_( | ||||
|             NSPicturesDirectory, 1).firstObject().absoluteString.UTF8String() | ||||
| 
 | ||||
|     def _get_application_dir(self): | ||||
|         return self.defaultManager.URLsForDirectory_inDomains_( | ||||
|             NSApplicationDirectory, 1).firstObject().absoluteString.\ | ||||
|             UTF8String() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return iOSStoragePath() | ||||
							
								
								
									
										37
									
								
								sbapp/plyer/platforms/ios/tts.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								sbapp/plyer/platforms/ios/tts.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| from pyobjus import autoclass, objc_str | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| 
 | ||||
| from plyer.facades import TTS | ||||
| 
 | ||||
| load_framework('/System/Library/Frameworks/AVFoundation.framework') | ||||
| AVSpeechUtterance = autoclass('AVSpeechUtterance') | ||||
| AVSpeechSynthesizer = autoclass('AVSpeechSynthesizer') | ||||
| AVSpeechSynthesisVoice = autoclass('AVSpeechSynthesisVoice') | ||||
| 
 | ||||
| 
 | ||||
| class iOSTextToSpeech(TTS): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.synth = AVSpeechSynthesizer.alloc().init() | ||||
|         self.voice = None | ||||
| 
 | ||||
|     def _set_locale(self, locale="en-US"): | ||||
|         self.voice = AVSpeechSynthesisVoice.voiceWithLanguage_( | ||||
|             objc_str(locale) | ||||
|         ) | ||||
| 
 | ||||
|     def _speak(self, **kwargs): | ||||
|         message = kwargs.get('message') | ||||
| 
 | ||||
|         if(not self.voice): | ||||
|             self._set_locale() | ||||
| 
 | ||||
|         utterance = \ | ||||
|             AVSpeechUtterance.speechUtteranceWithString_(objc_str(message)) | ||||
| 
 | ||||
|         utterance.voice = self.voice | ||||
|         self.synth.speakUtterance_(utterance) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return iOSTextToSpeech() | ||||
							
								
								
									
										27
									
								
								sbapp/plyer/platforms/ios/uniqueid.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								sbapp/plyer/platforms/ios/uniqueid.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| ''' | ||||
| Module of iOS API for plyer.uniqueid. | ||||
| ''' | ||||
| 
 | ||||
| from pyobjus import autoclass | ||||
| from pyobjus.dylib_manager import load_framework | ||||
| from plyer.facades import UniqueID | ||||
| 
 | ||||
| load_framework('/System/Library/Frameworks/UIKit.framework') | ||||
| UIDevice = autoclass('UIDevice') | ||||
| 
 | ||||
| 
 | ||||
| class IOSUniqueID(UniqueID): | ||||
|     ''' | ||||
|     Implementation of iOS uniqueid API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _get_uid(self): | ||||
|         uuid = UIDevice.currentDevice().identifierForVendor.UUIDString() | ||||
|         return uuid.UTF8String() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return IOSUniqueID() | ||||
							
								
								
									
										43
									
								
								sbapp/plyer/platforms/ios/vibrator.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								sbapp/plyer/platforms/ios/vibrator.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| '''Implementation Vibrator for iOS. | ||||
| 
 | ||||
| Install: Add AudioToolbox framework to your application. | ||||
| ''' | ||||
| 
 | ||||
| import ctypes | ||||
| from plyer.facades import Vibrator | ||||
| 
 | ||||
| 
 | ||||
| class IosVibrator(Vibrator): | ||||
|     '''iOS Vibrator class. | ||||
| 
 | ||||
|     iOS doesn't support any feature. | ||||
|     All time, pattern, repetition are ignored. | ||||
|     ''' | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         try: | ||||
|             self._func = ctypes.CDLL(None).AudioServicesPlaySystemSound | ||||
|         except AttributeError: | ||||
|             self._func = None | ||||
| 
 | ||||
|     def _vibrate(self, time=None, **kwargs): | ||||
|         # kSystemSoundID_Vibrate is 0x00000FFF | ||||
|         self._func(0xFFF) | ||||
| 
 | ||||
|     def _pattern(self, pattern=None, repeat=None, **kwargs): | ||||
|         self._vibrate() | ||||
| 
 | ||||
|     def _exists(self, **kwargs): | ||||
|         return self._func is not None | ||||
| 
 | ||||
|     def _cancel(self, **kwargs): | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     '''Returns Vibrator | ||||
| 
 | ||||
|     :return: instance of class IosVibrator | ||||
|     ''' | ||||
|     return IosVibrator() | ||||
							
								
								
									
										0
									
								
								sbapp/plyer/platforms/linux/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								sbapp/plyer/platforms/linux/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										35
									
								
								sbapp/plyer/platforms/linux/accelerometer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								sbapp/plyer/platforms/linux/accelerometer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| ''' | ||||
| Linux accelerometer | ||||
| --------------------- | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Accelerometer | ||||
| import glob | ||||
| import re | ||||
| 
 | ||||
| 
 | ||||
| class LinuxAccelerometer(Accelerometer): | ||||
| 
 | ||||
|     def _enable(self): | ||||
|         pass | ||||
| 
 | ||||
|     def _disable(self): | ||||
|         pass | ||||
| 
 | ||||
|     def _get_acceleration(self): | ||||
|         try: | ||||
|             pos = glob.glob("/sys/devices/platform/*/position")[0] | ||||
|         except IndexError: | ||||
|             raise Exception('Could not enable accelerometer!') | ||||
| 
 | ||||
|         with open(pos, "r") as p: | ||||
|             t = p.read() | ||||
|             coords = re.findall(r"[-]?\d+\.?\d*", t) | ||||
|             # Apparently the acceleration on sysfs goes from -1000 to 1000. | ||||
|             # I divide it by 100 to make it equivalent to Android. | ||||
|             # The negative is because the coordinates are inverted on Linux | ||||
|             return [float(i) / -100 for i in coords] | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return LinuxAccelerometer() | ||||
							
								
								
									
										102
									
								
								sbapp/plyer/platforms/linux/battery.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								sbapp/plyer/platforms/linux/battery.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| ''' | ||||
| Module of Linux API for plyer.battery. | ||||
| ''' | ||||
| 
 | ||||
| from math import floor | ||||
| from os import environ | ||||
| from os.path import exists, join | ||||
| from subprocess import Popen, PIPE | ||||
| from plyer.facades import Battery | ||||
| from plyer.utils import whereis_exe | ||||
| 
 | ||||
| 
 | ||||
| class LinuxBattery(Battery): | ||||
|     ''' | ||||
|     Implementation of Linux battery API via accessing the sysclass power_supply | ||||
|     path from the kernel. | ||||
|     ''' | ||||
| 
 | ||||
|     def _get_state(self): | ||||
|         status = {"isCharging": None, "percentage": None} | ||||
| 
 | ||||
|         kernel_bat_path = join('/sys', 'class', 'power_supply', 'BAT0') | ||||
|         uevent = join(kernel_bat_path, 'uevent') | ||||
| 
 | ||||
|         with open(uevent) as fle: | ||||
|             lines = [ | ||||
|                 line.decode('utf-8').strip() | ||||
|                 for line in fle.readlines() | ||||
|             ] | ||||
|         output = { | ||||
|             line.split('=')[0]: line.split('=')[1] | ||||
|             for line in lines | ||||
|         } | ||||
| 
 | ||||
|         is_charging = output['POWER_SUPPLY_STATUS'] == 'Charging' | ||||
|         total = float(output['POWER_SUPPLY_CHARGE_FULL']) | ||||
|         now = float(output['POWER_SUPPLY_CHARGE_NOW']) | ||||
| 
 | ||||
|         capacity = floor(now / total * 100) | ||||
| 
 | ||||
|         status['percentage'] = capacity | ||||
|         status['isCharging'] = is_charging | ||||
|         return status | ||||
| 
 | ||||
| 
 | ||||
| class UPowerBattery(Battery): | ||||
|     ''' | ||||
|     Implementation of UPower battery API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _get_state(self): | ||||
|         # if no LANG specified, return empty string | ||||
|         old_lang = environ.get('LANG', '') | ||||
|         environ['LANG'] = 'C' | ||||
|         status = {"isCharging": None, "percentage": None} | ||||
| 
 | ||||
|         # We are supporting only one battery now | ||||
|         # this will fail if there is no object with such path, | ||||
|         # however it's safer than 'upower -d' which provides | ||||
|         # multiple unrelated 'state' and 'percentage' keywords | ||||
|         dev = "/org/freedesktop/UPower/devices/battery_BAT0" | ||||
|         upower_process = Popen( | ||||
|             ["upower", "--show-info", dev], | ||||
|             stdout=PIPE | ||||
|         ) | ||||
|         output = upower_process.communicate()[0].decode() | ||||
|         environ['LANG'] = old_lang | ||||
|         if not output: | ||||
|             return status | ||||
|         state = percentage = None | ||||
| 
 | ||||
|         for line in output.splitlines(): | ||||
|             if 'state' in line: | ||||
|                 state = line.rpartition(':')[-1].strip() | ||||
| 
 | ||||
|             if 'percentage' in line: | ||||
|                 percentage = line.rpartition(':')[-1].strip()[:-1] | ||||
| 
 | ||||
|                 # switching decimal comma to dot | ||||
|                 # (different LC_NUMERIC locale) | ||||
|                 percentage = float( | ||||
|                     percentage.replace(',', '.') | ||||
|                 ) | ||||
| 
 | ||||
|         if state: | ||||
|             status['isCharging'] = state == "charging" | ||||
|         status['percentage'] = percentage | ||||
|         return status | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     import sys | ||||
|     if whereis_exe('upower'): | ||||
|         return UPowerBattery() | ||||
|     sys.stderr.write("upower not found.") | ||||
| 
 | ||||
|     if exists(join('/sys', 'class', 'power_supply', 'BAT0')): | ||||
|         return LinuxBattery() | ||||
|     return Battery() | ||||
							
								
								
									
										29
									
								
								sbapp/plyer/platforms/linux/brightness.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										29
									
								
								sbapp/plyer/platforms/linux/brightness.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,29 @@ | ||||
| ''' | ||||
| Linux Brightness | ||||
| ---------------- | ||||
| 
 | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import Brightness | ||||
| import subprocess | ||||
| import os | ||||
| 
 | ||||
| 
 | ||||
| class LinuxBrightness(Brightness): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         if os.system("which xbacklight"): | ||||
|             msg = ("It looks like 'xbacklight' is not installed. Try " | ||||
|                    "installing it with your distribution's package manager.") | ||||
|             raise Exception(msg) | ||||
| 
 | ||||
|     def _current_level(self): | ||||
|         cr_level = subprocess.check_output(["xbacklight", "-get"]) | ||||
|         return str(cr_level) | ||||
| 
 | ||||
|     def _set_level(self, level): | ||||
|         subprocess.call(["xbacklight", "-set", str(level)]) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return LinuxBrightness() | ||||
							
								
								
									
										116
									
								
								sbapp/plyer/platforms/linux/cpu.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								sbapp/plyer/platforms/linux/cpu.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,116 @@ | ||||
| ''' | ||||
| Module of Linux API for plyer.cpu. | ||||
| ''' | ||||
| 
 | ||||
| from os.path import join | ||||
| from os import environ, listdir | ||||
| from subprocess import Popen, PIPE | ||||
| from plyer.facades import CPU | ||||
| from plyer.utils import whereis_exe | ||||
| 
 | ||||
| 
 | ||||
| class LinuxCPU(CPU): | ||||
|     ''' | ||||
|     Implementation of Linux CPU API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _sockets(self): | ||||
|         # physical CPU sockets (or slots) on motherboard | ||||
|         sockets = []  # list of CPU ids from kernel | ||||
| 
 | ||||
|         # open Linux kernel data file for CPU | ||||
|         with open('/proc/cpuinfo', 'rb') as fle: | ||||
|             lines = fle.readlines() | ||||
| 
 | ||||
|         # go through the lines and obtain physical CPU ids | ||||
|         for line in lines: | ||||
|             line = line.decode('utf-8') | ||||
|             if 'physical id' not in line: | ||||
|                 continue | ||||
|             cpuid = line.split(':')[1].strip() | ||||
|             sockets.append(cpuid) | ||||
| 
 | ||||
|         # total sockets is the length of unique CPU ids from kernel | ||||
|         sockets = len(set(sockets)) | ||||
|         return sockets | ||||
| 
 | ||||
|     def _physical(self): | ||||
|         # cores | ||||
|         physical = []  # list of CPU ids from kernel | ||||
| 
 | ||||
|         # open Linux kernel data file for CPU | ||||
|         with open('/proc/cpuinfo', 'rb') as fle: | ||||
|             lines = fle.readlines() | ||||
| 
 | ||||
|         # go through the lines and obtain CPU core ids | ||||
|         for line in lines: | ||||
|             line = line.decode('utf-8') | ||||
|             if 'core id' not in line: | ||||
|                 continue | ||||
|             cpuid = line.split(':')[1].strip() | ||||
|             physical.append(cpuid) | ||||
| 
 | ||||
|         # total cores (socket * core per socket) | ||||
|         # is the length of unique CPU core ids from kernel | ||||
|         physical = len(set(physical)) | ||||
|         return physical | ||||
| 
 | ||||
|     def _logical(self): | ||||
|         # cores * threads | ||||
|         logical = None | ||||
|         old_lang = environ.get('LANG', '') | ||||
|         environ['LANG'] = 'C' | ||||
| 
 | ||||
|         _logical = Popen(['nproc', '--all'], stdout=PIPE) | ||||
|         output = _logical.communicate()[0].decode('utf-8').strip() | ||||
|         if output: | ||||
|             logical = int(output) | ||||
| 
 | ||||
|         environ['LANG'] = old_lang | ||||
|         return logical | ||||
| 
 | ||||
|     def _cache(self): | ||||
|         values = {key: 0 for key in ('L1', 'L2', 'L3')} | ||||
|         cpu_path = join('/sys', 'devices', 'system', 'cpu') | ||||
| 
 | ||||
|         # get present cores from kernel device | ||||
|         with open(join(cpu_path, 'present')) as fle: | ||||
|             present = fle.read().decode('utf-8') | ||||
|         present = present.strip().split('-') | ||||
| 
 | ||||
|         if len(present) == 2: | ||||
|             present = range(int(present[1]) + 1) | ||||
|         else: | ||||
|             present = [present[0]] | ||||
| 
 | ||||
|         cores = ['cpu{}'.format(i) for i in present] | ||||
|         for core in cores: | ||||
|             indicies = [ | ||||
|                 # get 'indexN' files from 'cache' folder assuming | ||||
|                 # the filename is in range index0 to index99 | ||||
|                 # in case a wild 'index_whatevercontent' file appears | ||||
|                 fle for fle in listdir(join(cpu_path, core, 'cache')) | ||||
|                 if fle.startswith('index') and len(fle) <= len('index') + 2 | ||||
|             ] | ||||
| 
 | ||||
|             for index in indicies: | ||||
|                 index_type = join(cpu_path, core, 'cache', index, 'level') | ||||
|                 with open(index_type, 'rb') as fle: | ||||
|                     cache_level = fle.read().decode('utf-8').strip() | ||||
|                 values['L{}'.format(cache_level)] += 1 | ||||
|         return values | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _numa(): | ||||
|         return | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     import sys | ||||
|     if whereis_exe('nproc'): | ||||
|         return LinuxCPU() | ||||
|     sys.stderr.write("nproc not found.") | ||||
|     return CPU() | ||||
							
								
								
									
										23
									
								
								sbapp/plyer/platforms/linux/devicename.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								sbapp/plyer/platforms/linux/devicename.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| ''' | ||||
| Module of Linux API for plyer.devicename. | ||||
| ''' | ||||
| 
 | ||||
| import socket | ||||
| from plyer.facades import DeviceName | ||||
| 
 | ||||
| 
 | ||||
| class LinuxDeviceName(DeviceName): | ||||
|     ''' | ||||
|     Implementation of Linux DeviceName API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _get_device_name(self): | ||||
|         hostname = socket.gethostname() | ||||
|         return hostname | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     return LinuxDeviceName() | ||||
							
								
								
									
										47
									
								
								sbapp/plyer/platforms/linux/email.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								sbapp/plyer/platforms/linux/email.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| ''' | ||||
| Module of Linux API for plyer.email. | ||||
| ''' | ||||
| 
 | ||||
| import subprocess | ||||
| try: | ||||
|     from urllib.parse import quote | ||||
| except ImportError: | ||||
|     from urllib import quote | ||||
| from plyer.facades import Email | ||||
| from plyer.utils import whereis_exe | ||||
| 
 | ||||
| 
 | ||||
| class LinuxEmail(Email): | ||||
|     ''' | ||||
|     Implementation of Linux email API. | ||||
|     ''' | ||||
| 
 | ||||
|     def _send(self, **kwargs): | ||||
|         recipient = kwargs.get('recipient') | ||||
|         subject = kwargs.get('subject') | ||||
|         text = kwargs.get('text') | ||||
| 
 | ||||
|         uri = "mailto:" | ||||
|         if recipient: | ||||
|             uri += str(recipient) | ||||
|         if subject: | ||||
|             uri += "?" if "?" not in uri else "&" | ||||
|             uri += "subject=" | ||||
|             uri += quote(str(subject)) | ||||
|         if text: | ||||
|             uri += "?" if "?" not in uri else "&" | ||||
|             uri += "body=" | ||||
|             uri += quote(str(text)) | ||||
| 
 | ||||
|         subprocess.Popen(["xdg-open", uri]) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     ''' | ||||
|     Instance for facade proxy. | ||||
|     ''' | ||||
|     import sys | ||||
|     if whereis_exe('xdg-open'): | ||||
|         return LinuxEmail() | ||||
|     sys.stderr.write("xdg-open not found.") | ||||
|     return Email() | ||||
							
								
								
									
										269
									
								
								sbapp/plyer/platforms/linux/filechooser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								sbapp/plyer/platforms/linux/filechooser.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,269 @@ | ||||
| ''' | ||||
| Linux file chooser | ||||
| ------------------ | ||||
| ''' | ||||
| 
 | ||||
| from plyer.facades import FileChooser | ||||
| from distutils.spawn import find_executable as which | ||||
| import os | ||||
| import subprocess as sp | ||||
| import time | ||||
| 
 | ||||
| 
 | ||||
| class SubprocessFileChooser: | ||||
|     '''A file chooser implementation that allows using | ||||
|     subprocess back-ends. | ||||
|     Normally you only need to override _gen_cmdline, executable, | ||||
|     separator and successretcode. | ||||
|     ''' | ||||
| 
 | ||||
|     executable = "" | ||||
|     '''The name of the executable of the back-end. | ||||
|     ''' | ||||
| 
 | ||||
|     separator = "|" | ||||
|     '''The separator used by the back-end. Override this for automatic | ||||
|     splitting, or override _split_output. | ||||
|     ''' | ||||
| 
 | ||||
|     successretcode = 0 | ||||
|     '''The return code which is returned when the user doesn't close the | ||||
|     dialog without choosing anything, or when the app doesn't crash. | ||||
|     ''' | ||||
| 
 | ||||
|     path = None | ||||
|     multiple = False | ||||
|     filters = [] | ||||
|     preview = False | ||||
|     title = None | ||||
|     icon = None | ||||
|     show_hidden = False | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         self._handle_selection = kwargs.pop( | ||||
|             'on_selection', self._handle_selection | ||||
|         ) | ||||
| 
 | ||||
|         # Simulate Kivy's behavior | ||||
|         for i in kwargs: | ||||
|             setattr(self, i, kwargs[i]) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _handle_selection(selection): | ||||
|         ''' | ||||
|         Dummy placeholder for returning selection from chooser. | ||||
|         ''' | ||||
|         return selection | ||||
| 
 | ||||
|     _process = None | ||||
| 
 | ||||
|     def _run_command(self, cmd): | ||||
|         self._process = sp.Popen(cmd, stdout=sp.PIPE) | ||||
|         while True: | ||||
|             ret = self._process.poll() | ||||
|             if ret is not None: | ||||
|                 if ret == self.successretcode: | ||||
|                     out = self._process.communicate()[0].strip().decode('utf8') | ||||
|                     return self._set_and_return_selection( | ||||
|                         self._split_output(out)) | ||||
|                 else: | ||||
|                     return self._set_and_return_selection(None) | ||||
|             time.sleep(0.1) | ||||
| 
 | ||||
|     def _set_and_return_selection(self, value): | ||||
|         self.selection = value | ||||
|         self._handle_selection(value) | ||||
|         return value | ||||
| 
 | ||||
|     def _split_output(self, out): | ||||
|         '''This methods receives the output of the back-end and turns | ||||
|         it into a list of paths. | ||||
|         ''' | ||||
|         return out.split(self.separator) | ||||
| 
 | ||||
|     def _gen_cmdline(self): | ||||
|         '''Returns the command line of the back-end, based on the current | ||||
|         properties. You need to override this. | ||||
|         ''' | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|     def run(self): | ||||
|         return self._run_command(self._gen_cmdline()) | ||||
| 
 | ||||
| 
 | ||||
| class ZenityFileChooser(SubprocessFileChooser): | ||||
|     '''A FileChooser implementation using Zenity (on GNU/Linux). | ||||
| 
 | ||||
|     Not implemented features: | ||||
|     * show_hidden | ||||
|     * preview | ||||
|     ''' | ||||
| 
 | ||||
|     executable = "zenity" | ||||
|     separator = "|" | ||||
|     successretcode = 0 | ||||
| 
 | ||||
|     def _gen_cmdline(self): | ||||
|         cmdline = [ | ||||
|             which(self.executable), | ||||
|             "--file-selection", | ||||
|             "--confirm-overwrite" | ||||
|         ] | ||||
|         if self.multiple: | ||||
|             cmdline += ["--multiple"] | ||||
|         if self.mode == "save": | ||||
|             cmdline += ["--save"] | ||||
|         elif self.mode == "dir": | ||||
|             cmdline += ["--directory"] | ||||
|         if self.path: | ||||
|             cmdline += ["--filename", self.path] | ||||
|         if self.title: | ||||
|             cmdline += ["--name", self.title] | ||||
|         if self.icon: | ||||
|             cmdline += ["--window-icon", self.icon] | ||||
|         for f in self.filters: | ||||
|             if type(f) == str: | ||||
|                 cmdline += ["--file-filter", f] | ||||
|             else: | ||||
|                 cmdline += [ | ||||
|                     "--file-filter", | ||||
|                     "{name} | {flt}".format(name=f[0], flt=" ".join(f[1:])) | ||||
|                 ] | ||||
|         return cmdline | ||||
| 
 | ||||
| 
 | ||||
| class KDialogFileChooser(SubprocessFileChooser): | ||||
|     '''A FileChooser implementation using KDialog (on GNU/Linux). | ||||
| 
 | ||||
|     Not implemented features: | ||||
|     * show_hidden | ||||
|     * preview | ||||
|     ''' | ||||
| 
 | ||||
|     executable = "kdialog" | ||||
|     separator = "\n" | ||||
|     successretcode = 0 | ||||
| 
 | ||||
|     def _gen_cmdline(self): | ||||
|         cmdline = [which(self.executable)] | ||||
| 
 | ||||
|         filt = [] | ||||
| 
 | ||||
|         for f in self.filters: | ||||
|             if type(f) == str: | ||||
|                 filt += [f] | ||||
|             else: | ||||
|                 filt += list(f[1:]) | ||||
| 
 | ||||
|         if self.mode == "dir": | ||||
|             cmdline += [ | ||||
|                 "--getexistingdirectory", | ||||
|                 (self.path if self.path else os.path.expanduser("~")) | ||||
|             ] | ||||
|         elif self.mode == "save": | ||||
|             cmdline += [ | ||||
|                 "--getsavefilename", | ||||
|                 (self.path if self.path else os.path.expanduser("~")), | ||||
|                 " ".join(filt) | ||||
|             ] | ||||
|         else: | ||||
|             cmdline += [ | ||||
|                 "--getopenfilename", | ||||
|                 (self.path if self.path else os.path.expanduser("~")), | ||||
|                 " ".join(filt) | ||||
|             ] | ||||
|         if self.multiple: | ||||
|             cmdline += ["--multiple", "--separate-output"] | ||||
|         if self.title: | ||||
|             cmdline += ["--title", self.title] | ||||
|         if self.icon: | ||||
|             cmdline += ["--icon", self.icon] | ||||
|         return cmdline | ||||
| 
 | ||||
| 
 | ||||
| class YADFileChooser(SubprocessFileChooser): | ||||
|     '''A NativeFileChooser implementation using YAD (on GNU/Linux). | ||||
| 
 | ||||
|     Not implemented features: | ||||
|     * show_hidden | ||||
|     ''' | ||||
| 
 | ||||
|     executable = "yad" | ||||
|     separator = "|?|" | ||||
|     successretcode = 0 | ||||
| 
 | ||||
|     def _gen_cmdline(self): | ||||
|         cmdline = [ | ||||
|             which(self.executable), | ||||
|             "--file-selection", | ||||
|             "--confirm-overwrite", | ||||
|             "--geometry", | ||||
|             "800x600+150+150" | ||||
|         ] | ||||
|         if self.multiple: | ||||
|             cmdline += ["--multiple", "--separator", self.separator] | ||||
|         if self.mode == "save": | ||||
|             cmdline += ["--save"] | ||||
|         elif self.mode == "dir": | ||||
|             cmdline += ["--directory"] | ||||
|         if self.preview: | ||||
|             cmdline += ["--add-preview"] | ||||
|         if self.path: | ||||
|             cmdline += ["--filename", self.path] | ||||
|         if self.title: | ||||
|             cmdline += ["--name", self.title] | ||||
|         if self.icon: | ||||
|             cmdline += ["--window-icon", self.icon] | ||||
|         for f in self.filters: | ||||
|             if type(f) == str: | ||||
|                 cmdline += ["--file-filter", f] | ||||
|             else: | ||||
|                 cmdline += [ | ||||
|                     "--file-filter", | ||||
|                     "{name} | {flt}".format(name=f[0], flt=" ".join(f[1:])) | ||||
|                 ] | ||||
|         return cmdline | ||||
| 
 | ||||
| 
 | ||||
| CHOOSERS = { | ||||
|     "gnome": ZenityFileChooser, | ||||
|     "kde": KDialogFileChooser, | ||||
|     "yad": YADFileChooser | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| class LinuxFileChooser(FileChooser): | ||||
|     '''FileChooser implementation for GNu/Linux. Accepts one additional | ||||
|     keyword argument, *desktop_override*, which, if set, overrides the | ||||
|     back-end that will be used. Set it to "gnome" for Zenity, to "kde" | ||||
|     for KDialog and to "yad" for YAD (Yet Another Dialog). | ||||
|     If set to None or not set, a default one will be picked based on | ||||
|     the running desktop environment and installed back-ends. | ||||
|     ''' | ||||
| 
 | ||||
|     desktop = None | ||||
|     if (str(os.environ.get("XDG_CURRENT_DESKTOP")).lower() == "kde" | ||||
|             and which("kdialog")): | ||||
|         desktop = "kde" | ||||
|     elif (str(os.environ.get("DESKTOP_SESSION")).lower() == "trinity" | ||||
|             and which('kdialog')): | ||||
|         desktop = "kde" | ||||
|     elif which("yad"): | ||||
|         desktop = "yad" | ||||
|     elif which("zenity"): | ||||
|         desktop = "gnome" | ||||
| 
 | ||||
|     def _file_selection_dialog(self, desktop_override=desktop, **kwargs): | ||||
|         if not desktop_override: | ||||
|             desktop_override = self.desktop | ||||
|         # This means we couldn't find any back-end | ||||
|         if not desktop_override: | ||||
|             raise OSError("No back-end available. Please install one.") | ||||
| 
 | ||||
|         chooser = CHOOSERS[desktop_override] | ||||
|         c = chooser(**kwargs) | ||||
|         return c.run() | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return LinuxFileChooser() | ||||
							
								
								
									
										19
									
								
								sbapp/plyer/platforms/linux/keystore.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								sbapp/plyer/platforms/linux/keystore.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| try: | ||||
|     import keyring | ||||
| except ImportError: | ||||
|     raise NotImplementedError() | ||||
| 
 | ||||
| from plyer.facades import Keystore | ||||
| 
 | ||||
| 
 | ||||
| class LinuxKeystore(Keystore): | ||||
| 
 | ||||
|     def _set_key(self, servicename, key, value, **kwargs): | ||||
|         keyring.set_password(servicename, key, value) | ||||
| 
 | ||||
|     def _get_key(self, servicename, key, **kwargs): | ||||
|         return keyring.get_password(servicename, key) | ||||
| 
 | ||||
| 
 | ||||
| def instance(): | ||||
|     return LinuxKeystore() | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user