From 9964cb67caa847f6f57c977128f0610d96e8e502 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Fri, 27 Sep 2024 02:01:15 +0200 Subject: [PATCH 01/26] fixed issue with missing argument. Added function to get connected ssid --- plyer/facades/wifi.py | 9 +++++++++ plyer/platforms/linux/wifi.py | 30 ++++++++++++++++++++++++++++++ plyer/platforms/macosx/wifi.py | 21 ++++++++++++++++++--- plyer/platforms/win/wifi.py | 6 +++--- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/plyer/facades/wifi.py b/plyer/facades/wifi.py index 5f0742f34..0335054f5 100644 --- a/plyer/facades/wifi.py +++ b/plyer/facades/wifi.py @@ -101,6 +101,12 @@ def is_connected(self, interface=None): ''' return self._is_connected(interface=interface) + def connected_ssid(self, interface=None): + ''' + Return returns ssid of connected WiFi interface. + ''' + return self._connected_ssid(interface=interface) + @property def interfaces(self): ''' @@ -165,6 +171,9 @@ def _is_enabled(self): def _is_connected(self, interface=None): raise NotImplementedError() + def _connected_ssid(self, interface=None): + raise NotImplementedError() + def _start_scanning(self, interface=None): raise NotImplementedError() diff --git a/plyer/platforms/linux/wifi.py b/plyer/platforms/linux/wifi.py index 73f09b66c..ebedc09fb 100644 --- a/plyer/platforms/linux/wifi.py +++ b/plyer/platforms/linux/wifi.py @@ -115,6 +115,21 @@ def _is_connected(self, interface=None): return connected + def _connected_ssid(self, interface=None): + if not self._is_enabled(): + self._enable() + + ssid = None + ssid_proc = Popen(['nmcli', '-t', '-f', 'ACTIVE,SSID', 'connection'], stdout=PIPE) + ssid_lines = ssid_proc.communicate()[0].decode('utf-8').splitlines() + for ssid_line in ssid_lines: + active, ssid_value = ssid_line.split(':') + if active == 'yes': + ssid = ssid_value + break + + return ssid + def _start_scanning(self, interface=None): ''' Start scanning for available Wi-Fi networks @@ -359,6 +374,21 @@ def _is_connected(self, interface=None): return connected + def _connected_ssid(self, interface=None): + if not self._is_enabled(): + self._enable() + + ssid = None + ssid_proc = Popen(['nmcli', '-t', '-f', 'ACTIVE,SSID', 'connection'], stdout=PIPE) + ssid_lines = ssid_proc.communicate()[0].decode('utf-8').splitlines() + for ssid_line in ssid_lines: + active, ssid_value = ssid_line.split(':') + if active == 'yes': + ssid = ssid_value + break + + return ssid + def _start_scanning(self, interface=None): ''' Returns all the network information. diff --git a/plyer/platforms/macosx/wifi.py b/plyer/platforms/macosx/wifi.py index 32c02ab60..749235b93 100644 --- a/plyer/platforms/macosx/wifi.py +++ b/plyer/platforms/macosx/wifi.py @@ -23,6 +23,21 @@ def _is_enabled(self): ''' return CWWiFiClient.sharedWiFiClient().interface().powerOn() + def _is_connected(self, interface=None): + ''' + Return whether a specified interface is connected to a WiFi network. + ''' + if not self._is_enabled(): + self._enable() + + return CWInterface.interface().ssid() is not None + + def _connected_ssid(self, interface=None): + if not self._is_enabled(): + self._enable() + + return CWInterface.interface().ssid() + def _get_network_info(self, name): ''' Returns all the network information. @@ -83,7 +98,7 @@ def _get_network_info(self, name): 'venueGroup': venueGroup, 'venueType': venueType} - def _start_scanning(self): + def _start_scanning(self, interface=None): ''' Starts scanning for available Wi-Fi networks. ''' @@ -105,7 +120,7 @@ def _get_available_wifi(self): ''' return self.names.keys() - def _connect(self, network, parameters): + def _connect(self, network, parameters, interface=None): ''' Expects 2 parameters: - name/ssid of the network. @@ -119,7 +134,7 @@ def _connect(self, network, parameters): None) return - def _disconnect(self): + def _disconnect(self, interface=None): ''' Disconnect from network. ''' diff --git a/plyer/platforms/win/wifi.py b/plyer/platforms/win/wifi.py index 68efb2ffe..1a798eca4 100644 --- a/plyer/platforms/win/wifi.py +++ b/plyer/platforms/win/wifi.py @@ -31,7 +31,7 @@ def _get_network_info(self, name): ''' return wifi_lib.get_network_info(name) - def _start_scanning(self): + def _start_scanning(self, interface=None): ''' Starts scanning for available Wi-Fi networks and returns the available, devices. @@ -47,7 +47,7 @@ def _get_available_wifi(self): ''' return wifi_lib.get_available_wifi() - def _connect(self, network, parameters): + def _connect(self, network, parameters, interface=None): ''' Expects 2 parameters: - name/ssid of the network. @@ -109,7 +109,7 @@ def _connect(self, network, parameters): wifi_lib.connect(network, parameters) return - def _disconnect(self): + def _disconnect(self, interface=None): ''' Disconnect from network. ''' From 59050f997a9642b615a7270ee2a5aac3e6eceb0b Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Fri, 27 Sep 2024 02:03:33 +0200 Subject: [PATCH 02/26] updated --- plyer/platforms/macosx/wifi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plyer/platforms/macosx/wifi.py b/plyer/platforms/macosx/wifi.py index 749235b93..167bb3ad1 100644 --- a/plyer/platforms/macosx/wifi.py +++ b/plyer/platforms/macosx/wifi.py @@ -36,7 +36,7 @@ def _connected_ssid(self, interface=None): if not self._is_enabled(): self._enable() - return CWInterface.interface().ssid() + return CWInterface.interface().ssid().UTF8String() def _get_network_info(self, name): ''' From 31809b7ed77a15f4aa829746986a1863f000694b Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Sun, 6 Oct 2024 21:22:21 +0200 Subject: [PATCH 03/26] updated --- plyer/platforms/macosx/wifi.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plyer/platforms/macosx/wifi.py b/plyer/platforms/macosx/wifi.py index 167bb3ad1..5a327ee10 100644 --- a/plyer/platforms/macosx/wifi.py +++ b/plyer/platforms/macosx/wifi.py @@ -108,9 +108,13 @@ def _start_scanning(self, interface=None): scan = c.scanForNetworksWithName_error_(None, None) cnt = scan.allObjects().count() for i in range(cnt): - self.names[ - scan.allObjects().objectAtIndex_(i).ssid.UTF8String() - ] = scan.allObjects().objectAtIndex_(i) + if scan.allObjects().objectAtIndex_(i).ssid is not None: + try: + self.names[ + scan.allObjects().objectAtIndex_(i).ssid.UTF8String() + ] = scan.allObjects().objectAtIndex_(i) + except Exception: + pass else: raise Exception("Wifi not enabled.") From 1b0443b7e5f0e8f4856310435773d52657e75740 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 7 Oct 2024 20:53:45 +0200 Subject: [PATCH 04/26] fixed issue with wifi on linux --- plyer/platforms/linux/wifi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plyer/platforms/linux/wifi.py b/plyer/platforms/linux/wifi.py index ebedc09fb..b5ea921b5 100644 --- a/plyer/platforms/linux/wifi.py +++ b/plyer/platforms/linux/wifi.py @@ -120,7 +120,7 @@ def _connected_ssid(self, interface=None): self._enable() ssid = None - ssid_proc = Popen(['nmcli', '-t', '-f', 'ACTIVE,SSID', 'connection'], stdout=PIPE) + ssid_proc = Popen(['nmcli', '-t', '-f', 'ACTIVE,NAME', 'connection'], stdout=PIPE) ssid_lines = ssid_proc.communicate()[0].decode('utf-8').splitlines() for ssid_line in ssid_lines: active, ssid_value = ssid_line.split(':') @@ -379,7 +379,7 @@ def _connected_ssid(self, interface=None): self._enable() ssid = None - ssid_proc = Popen(['nmcli', '-t', '-f', 'ACTIVE,SSID', 'connection'], stdout=PIPE) + ssid_proc = Popen(['nmcli', '-t', '-f', 'ACTIVE,NAME', 'connection'], stdout=PIPE) ssid_lines = ssid_proc.communicate()[0].decode('utf-8').splitlines() for ssid_line in ssid_lines: active, ssid_value = ssid_line.split(':') From 66132ba6fe9c541b588333adbb2c792d6fa0a177 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 13 Nov 2024 01:44:37 +0100 Subject: [PATCH 05/26] added gps for macos --- plyer/platforms/macosx/gps.py | 150 ++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 plyer/platforms/macosx/gps.py diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py new file mode 100644 index 000000000..4e0862c97 --- /dev/null +++ b/plyer/platforms/macosx/gps.py @@ -0,0 +1,150 @@ +from pyobjus.dylib_manager import load_framework +from threading import Thread +from multiprocessing import ( + Process, + Pipe, +) +from pyobjus import ( + autoclass, + protocol, +) + +load_framework('/System/Library/Frameworks/CoreLocation.framework') +load_framework('/System/Library/Frameworks/Foundation.framework') +CLLocationManager = autoclass('CLLocationManager') +NSRunLoop = autoclass('NSRunLoop') + + +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() + + +class LocationManager: + def _run_location_manager(connection, **kwargs): + LocationManager(connection).start(**kwargs) + + def __init__(self, pipe) -> None: + self.pipe = pipe + self._location_manager = CLLocationManager.alloc().init() + + def start(self, **kwargs): + self._location_manager.setDelegate_(self) + self._location_manager.requestWhenInUseAuthorization() + self._location_manager.startUpdatingLocation() + NSRunLoop.currentRunLoop().run() + + def stop(self): + self._location_manager.stopUpdatingLocation() + + @protocol('CLLocationManagerDelegate') + def locationManager_didChangeAuthorizationStatus_(self, manager, status): + s_status = '' + provider_status = '' + provider = 'standard-macos-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.pipe.send({'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.pipe.send({'on_location': {'lat': lat, 'lon': lon, 'speed': speed, 'course': course, 'altitude': altitude, 'acc': acc}}) + + +class OSXGPS(GPS): + def _configure(self): + self._connection_1, self._connection_2 = Pipe() + + def _start(self, **kwargs): + self._process = Process(target=LocationManager._run_location_manager, args=[self._connection_2]) + self._thread = Thread(target=self._run_thread_pipe_checker) + self._process.start() + self._thread.start() + + def _stop(self, **kwargs): + self._process.kill() + + def _run_thread_pipe_checker(self): + while self._process.is_alive(): + if self._connection_1.poll(.1): + callback = self._connection_1.recv() + if 'on_status' in callback and self.on_status: + self.on_status(*callback['on_status']) + elif 'on_location': + self.on_location(**callback['on_location']) + + +def instance(): + return OSXGPS() From bc89636347186c3b0cf6def69cf6ced32ba7bce0 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 13 Nov 2024 01:50:43 +0100 Subject: [PATCH 06/26] fixed issue --- plyer/platforms/macosx/gps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 4e0862c97..b72ab6991 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -142,7 +142,7 @@ def _run_thread_pipe_checker(self): callback = self._connection_1.recv() if 'on_status' in callback and self.on_status: self.on_status(*callback['on_status']) - elif 'on_location': + elif 'on_location' in callback: self.on_location(**callback['on_location']) From 81aebf9a20a2ffd9ef480c7edc32d8973947da0e Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 13 Nov 2024 01:54:51 +0100 Subject: [PATCH 07/26] updated --- plyer/platforms/macosx/gps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index b72ab6991..778875a55 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -126,10 +126,10 @@ def locationManager_didUpdateLocations_(self, manager, locations): class OSXGPS(GPS): def _configure(self): self._connection_1, self._connection_2 = Pipe() - - def _start(self, **kwargs): self._process = Process(target=LocationManager._run_location_manager, args=[self._connection_2]) self._thread = Thread(target=self._run_thread_pipe_checker) + + def _start(self, **kwargs): self._process.start() self._thread.start() From be2f6461b90c3ad308f348ae3a6680b098a0a153 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 13 Nov 2024 01:57:53 +0100 Subject: [PATCH 08/26] updated --- plyer/platforms/macosx/gps.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 778875a55..6bd253456 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -134,7 +134,8 @@ def _start(self, **kwargs): self._thread.start() def _stop(self, **kwargs): - self._process.kill() + if hasattr(self, '_process'): + self._process.kill() def _run_thread_pipe_checker(self): while self._process.is_alive(): From 99065a1c3152d9b3f5a9b9e72e742f252d2606e5 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 13 Nov 2024 02:10:39 +0100 Subject: [PATCH 09/26] updated --- plyer/platforms/macosx/gps.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 6bd253456..51743f37c 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -1,4 +1,5 @@ from pyobjus.dylib_manager import load_framework +from pickle import UnpicklingError from threading import Thread from multiprocessing import ( Process, @@ -134,17 +135,20 @@ def _start(self, **kwargs): self._thread.start() def _stop(self, **kwargs): - if hasattr(self, '_process'): + if self._process is not None: self._process.kill() def _run_thread_pipe_checker(self): while self._process.is_alive(): if self._connection_1.poll(.1): - callback = self._connection_1.recv() - if 'on_status' in callback and self.on_status: - self.on_status(*callback['on_status']) - elif 'on_location' in callback: - self.on_location(**callback['on_location']) + try: + callback = self._connection_1.recv() + if 'on_status' in callback and self.on_status: + self.on_status(*callback['on_status']) + elif 'on_location' in callback: + self.on_location(**callback['on_location']) + except (EOFError, UnpicklingError): + pass def instance(): From 7d78abdfce2ab188f8d4ec155f768f9344ffb7a0 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 13 Nov 2024 02:12:08 +0100 Subject: [PATCH 10/26] updated --- plyer/platforms/macosx/gps.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 51743f37c..97638dded 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -81,9 +81,6 @@ def start(self, **kwargs): self._location_manager.startUpdatingLocation() NSRunLoop.currentRunLoop().run() - def stop(self): - self._location_manager.stopUpdatingLocation() - @protocol('CLLocationManagerDelegate') def locationManager_didChangeAuthorizationStatus_(self, manager, status): s_status = '' From f0a3a620ad9c2484410262b7e635eff34f1daead Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 13 Nov 2024 19:43:06 +0100 Subject: [PATCH 11/26] updated --- plyer/platforms/macosx/gps.py | 189 +++++++++++++--------------------- 1 file changed, 70 insertions(+), 119 deletions(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 97638dded..3ede85346 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -1,108 +1,82 @@ from pyobjus.dylib_manager import load_framework -from pickle import UnpicklingError -from threading import Thread -from multiprocessing import ( - Process, - Pipe, -) -from pyobjus import ( - autoclass, - protocol, -) +from pyobjus import autoclass, protocol +from plyer.facades import GPS +import threading +import time + load_framework('/System/Library/Frameworks/CoreLocation.framework') load_framework('/System/Library/Frameworks/Foundation.framework') -CLLocationManager = autoclass('CLLocationManager') -NSRunLoop = autoclass('NSRunLoop') - - -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) +CLLocationManager = autoclass('CLLocationManager') +NSRunLoop = autoclass('NSRunLoop') +NSObject = autoclass('NSObject') +NSDate = autoclass('NSDate') - def stop(self): - ''' - Stop the GPS location updates. - ''' - self._stop() - # private +class OSXGPS(GPS): + def __del__(self): + self._run_loop_thread_allow = False def _configure(self): - raise NotImplementedError() - - def _start(self, **kwargs): - raise NotImplementedError() - - def _stop(self): - raise NotImplementedError() + if not hasattr(self, '_run_loop_thread'): + self._run_loop_thread_allow = True + self._is_running = False + self._run_loop_thread = threading.Thread(target=self._run_loop) + self._run_loop_thread.daemon = True + self._run_loop_thread.start() -class LocationManager: - def _run_location_manager(connection, **kwargs): - LocationManager(connection).start(**kwargs) - - def __init__(self, pipe) -> None: - self.pipe = pipe + def _run_loop(self): self._location_manager = CLLocationManager.alloc().init() - - def start(self, **kwargs): self._location_manager.setDelegate_(self) + self._location_manager.requestWhenInUseAuthorization() + self._run_loop = NSRunLoop.currentRunLoop() + + while self._run_loop_thread_allow: + if self._is_running: + next_date = NSDate.dateWithTimeIntervalSinceNow_(0.01) + self._run_loop.runMode_beforeDate_('NSDefaultRunLoopMode', next_date) + time.sleep(0.1) + + def _start(self, **kwargs): self._location_manager.startUpdatingLocation() - NSRunLoop.currentRunLoop().run() + self._is_running = True + + def _stop(self, **kwargs): + self._location_manager.stopUpdatingLocation() + self._is_running = False @protocol('CLLocationManagerDelegate') def locationManager_didChangeAuthorizationStatus_(self, manager, status): - s_status = '' - provider_status = '' - provider = 'standard-macos-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.pipe.send({'on_status': (provider_status, '{}: {}'.format(provider, s_status))}) + if self.on_status: + s_status = '' + provider_status = '' + provider = 'standard-macos-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': provider_status, + 'status_message': '{}: {}'.format(provider, s_status) + } + ) @protocol('CLLocationManagerDelegate') def locationManager_didUpdateLocations_(self, manager, locations): @@ -110,42 +84,19 @@ def locationManager_didUpdateLocations_(self, manager, locations): 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.pipe.send({'on_location': {'lat': lat, 'lon': lon, 'speed': speed, 'course': course, 'altitude': altitude, 'acc': acc}}) - - -class OSXGPS(GPS): - def _configure(self): - self._connection_1, self._connection_2 = Pipe() - self._process = Process(target=LocationManager._run_location_manager, args=[self._connection_2]) - self._thread = Thread(target=self._run_thread_pipe_checker) - - def _start(self, **kwargs): - self._process.start() - self._thread.start() - - def _stop(self, **kwargs): - if self._process is not None: - self._process.kill() - - def _run_thread_pipe_checker(self): - while self._process.is_alive(): - if self._connection_1.poll(.1): - try: - callback = self._connection_1.recv() - if 'on_status' in callback and self.on_status: - self.on_status(*callback['on_status']) - elif 'on_location' in callback: - self.on_location(**callback['on_location']) - except (EOFError, UnpicklingError): - pass + self.on_location( + **{ + 'lat': lat, + 'lon': lon, + 'altitude': location.altitude, + 'speed': location.speed, + 'course': location.course, + 'acc': acc + } + ) def instance(): From 1dc9724cccec02136fe37e700772185eaba41f77 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 13 Nov 2024 21:43:34 +0100 Subject: [PATCH 12/26] updated --- plyer/platforms/macosx/gps.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 3ede85346..95b760563 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -31,6 +31,7 @@ def _configure(self): def _run_loop(self): self._location_manager = CLLocationManager.alloc().init() self._location_manager.setDelegate_(self) + self._location_manager.desiredAccuracy = -1.0 self._location_manager.requestWhenInUseAuthorization() self._run_loop = NSRunLoop.currentRunLoop() @@ -42,6 +43,9 @@ def _run_loop(self): time.sleep(0.1) def _start(self, **kwargs): + min_distance = kwargs.get('minDistance') + self._location_manager.distanceFilter = min_distance + self._location_manager.startUpdatingLocation() self._is_running = True From 4eb88a4b65b23d875938b566ad0aaf874c497946 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Sat, 23 Nov 2024 20:53:35 +0100 Subject: [PATCH 13/26] updated --- README.md | 4 ++-- plyer/platforms/macosx/gps.py | 21 ++++++++------------- setup.py | 6 +++--- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 0afa8a518..59abb7504 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ implement the API in the easiest way, depending on the current platform. | Platform | Android | iOS | Windows | macOS | Linux | | ------------------------------ |:-------:|:---:|:-------:|:-----:|:-----:| -| Accelerometer | ✔ | ✔ | | ✔ | ✔ | +| Accelerometer | ✔ | ✔ | | ✔ | ✔ | | Audio recording | ✔ | | ✔ | ✔ | | | Barometer | ✔ | ✔ | | | | | Battery | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -51,7 +51,7 @@ implement the API in the easiest way, depending on the current platform. | Devicename | ✔ | | ✔ | ✔ | ✔ | | Email (open mail client) | ✔ | ✔ | ✔ | ✔ | ✔ | | Flash | ✔ | ✔ | | | | -| GPS | ✔ | ✔ | | | | +| GPS | ✔ | ✔ | | ✔ | | | Gravity | ✔ | ✔ | | | | | Gyroscope | ✔ | ✔ | | | | | Humidity | ✔ | | | | | diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 95b760563..6a85d0ae1 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -1,9 +1,10 @@ -from pyobjus.dylib_manager import load_framework -from pyobjus import autoclass, protocol -from plyer.facades import GPS import threading import time +from pyobjus import autoclass, protocol +from pyobjus.dylib_manager import load_framework + +from plyer.facades import GPS load_framework('/System/Library/Frameworks/CoreLocation.framework') load_framework('/System/Library/Frameworks/Foundation.framework') @@ -49,7 +50,7 @@ def _start(self, **kwargs): self._location_manager.startUpdatingLocation() self._is_running = True - def _stop(self, **kwargs): + def _stop(self): self._location_manager.stopUpdatingLocation() self._is_running = False @@ -74,13 +75,7 @@ def locationManager_didChangeAuthorizationStatus_(self, manager, status): elif status == 4: provider_status = 'provider-enabled' s_status = 'authorizedWhenInUse' - - self.on_status( - **{ - 'provider_status': provider_status, - 'status_message': '{}: {}'.format(provider, s_status) - } - ) + self.on_status(provider_status, f'{provider}: {s_status}') @protocol('CLLocationManagerDelegate') def locationManager_didUpdateLocations_(self, manager, locations): @@ -98,8 +93,8 @@ def locationManager_didUpdateLocations_(self, manager, locations): 'altitude': location.altitude, 'speed': location.speed, 'course': location.course, - 'acc': acc - } + 'acc': acc, + }, ) diff --git a/setup.py b/setup.py index d2d17e69b..74eb131ac 100644 --- a/setup.py +++ b/setup.py @@ -26,9 +26,9 @@ 'ios': ['pyobjus'], 'macosx': ['pyobjus'], 'android': ['pyjnius'], - 'dev': ['flake8'] - } - } + 'dev': ['flake8'], + }, + }, ) except ImportError: From 94fc154e9280c6891fa280b9fc921a1244dc7158 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Sat, 23 Nov 2024 21:51:55 +0100 Subject: [PATCH 14/26] updated --- plyer/platforms/macosx/gps.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 6a85d0ae1..887a3d59c 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -34,7 +34,7 @@ def _run_loop(self): self._location_manager.setDelegate_(self) self._location_manager.desiredAccuracy = -1.0 - self._location_manager.requestWhenInUseAuthorization() + self._location_manager.requestAlwaysAuthorization() self._run_loop = NSRunLoop.currentRunLoop() while self._run_loop_thread_allow: @@ -47,6 +47,9 @@ def _start(self, **kwargs): min_distance = kwargs.get('minDistance') self._location_manager.distanceFilter = min_distance + if self._location_manager.authorizationStatus == 2: + self.on_status('provider-disabled', 'standard-macos-provider: denied') + self._location_manager.startUpdatingLocation() self._is_running = True @@ -81,8 +84,13 @@ def locationManager_didChangeAuthorizationStatus_(self, manager, status): def locationManager_didUpdateLocations_(self, manager, locations): location = manager.location - description = location.description().UTF8String() + try: + description = location.description().UTF8String() + except Exception: + 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]) From 36ada237fce041253be75541d5acbfa977cd5cdd Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 10 Mar 2025 19:26:38 +0100 Subject: [PATCH 15/26] fixed issue --- plyer/platforms/macosx/gps.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 887a3d59c..687b30ab9 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -78,7 +78,8 @@ def locationManager_didChangeAuthorizationStatus_(self, manager, status): elif status == 4: provider_status = 'provider-enabled' s_status = 'authorizedWhenInUse' - self.on_status(provider_status, f'{provider}: {s_status}') + + self.on_status(provider_status, f'{provider}: {s_status}') @protocol('CLLocationManagerDelegate') def locationManager_didUpdateLocations_(self, manager, locations): From dd8cf8a7868aaad368d90d52478556327b82c700 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 10 Mar 2025 19:28:59 +0100 Subject: [PATCH 16/26] fixed issue with on_status callback --- plyer/platforms/macosx/gps.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 687b30ab9..488dab622 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -48,7 +48,8 @@ def _start(self, **kwargs): self._location_manager.distanceFilter = min_distance if self._location_manager.authorizationStatus == 2: - self.on_status('provider-disabled', 'standard-macos-provider: denied') + if self.on_status: + self.on_status('provider-disabled', 'standard-macos-provider: denied') self._location_manager.startUpdatingLocation() self._is_running = True From 54f1dd88d02315465bb58245b692e35053404508 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 24 Mar 2025 17:34:24 +0100 Subject: [PATCH 17/26] updated --- plyer/platforms/macosx/gps.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 488dab622..7119b9db8 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -2,12 +2,12 @@ import time from pyobjus import autoclass, protocol -from pyobjus.dylib_manager import load_framework +from pyobjus.dylib_manager import INCLUDE, load_framework from plyer.facades import GPS -load_framework('/System/Library/Frameworks/CoreLocation.framework') -load_framework('/System/Library/Frameworks/Foundation.framework') +load_framework(INCLUDE.CoreLocation) +load_framework(INCLUDE.Foundation) CLLocationManager = autoclass('CLLocationManager') From d62417328d09b8410573a275a5ff543b8b08085e Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 24 Mar 2025 17:36:36 +0100 Subject: [PATCH 18/26] Implemented getting the real name of the device --- plyer/platforms/ios/devicename.py | 29 ++++++++++++++++++++++++++++ plyer/platforms/macosx/devicename.py | 12 +++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 plyer/platforms/ios/devicename.py diff --git a/plyer/platforms/ios/devicename.py b/plyer/platforms/ios/devicename.py new file mode 100644 index 000000000..02c45c47a --- /dev/null +++ b/plyer/platforms/ios/devicename.py @@ -0,0 +1,29 @@ +''' +Module of macOS API for plyer.devicename. +''' + +from pyobjus import autoclass +from pyobjus.dylib_manager import load_framework + +from plyer.facades import DeviceName + +load_framework('/System/Library/Frameworks/UIKit.framework') + + +class IosDeviceName(DeviceName): + ''' + Implementation of IOS DeviceName API. + ''' + + def _get_device_name(self): + UIDevice = autoclass('UIDevice') + device = UIDevice.currentDevice() + device_name = device.name.UTF8String() + return device_name + + +def instance(): + ''' + Instance for facade proxy. + ''' + return IosDeviceName() diff --git a/plyer/platforms/macosx/devicename.py b/plyer/platforms/macosx/devicename.py index 6652425e3..61f70ee85 100644 --- a/plyer/platforms/macosx/devicename.py +++ b/plyer/platforms/macosx/devicename.py @@ -2,9 +2,13 @@ Module of MacOSX API for plyer.devicename. ''' -import socket +from pyobjus import autoclass +from pyobjus.dylib_manager import INCLUDE, load_framework + from plyer.facades import DeviceName +load_framework(INCLUDE.Foundation) + class OSXDeviceName(DeviceName): ''' @@ -12,8 +16,10 @@ class OSXDeviceName(DeviceName): ''' def _get_device_name(self): - hostname = socket.gethostname() - return hostname + NSHost = autoclass('NSHost') + current_host = NSHost.currentHost() + name = current_host.localizedName.UTF8String() + return name def instance(): From 3669f1827e9cd9b5356fef6278cc259678ceaff9 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 24 Mar 2025 20:26:00 +0100 Subject: [PATCH 19/26] get real device name? --- plyer/platforms/android/devicename.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plyer/platforms/android/devicename.py b/plyer/platforms/android/devicename.py index 75855cc75..49297bed4 100644 --- a/plyer/platforms/android/devicename.py +++ b/plyer/platforms/android/devicename.py @@ -23,7 +23,10 @@ def _get_device_name(self): Thereby making this method more backward compatible. """ - return Build.MODEL + PythonActivity = autoclass('org.kivy.android.PythonActivity') + context = PythonActivity.mActivity + SettingsSecure = autoclass('android.provider.Settings$Secure') + return SettingsSecure.getString(context.getContentResolver(), "device_name") def instance(): From e028f323074e3e3041d602bd85b442b7229078cd Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 24 Mar 2025 20:55:04 +0100 Subject: [PATCH 20/26] updated --- plyer/platforms/android/devicename.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plyer/platforms/android/devicename.py b/plyer/platforms/android/devicename.py index 49297bed4..64b950a3c 100644 --- a/plyer/platforms/android/devicename.py +++ b/plyer/platforms/android/devicename.py @@ -5,8 +5,6 @@ from jnius import autoclass from plyer.facades import DeviceName -Build = autoclass('android.os.Build') - class AndroidDeviceName(DeviceName): ''' @@ -23,10 +21,16 @@ def _get_device_name(self): Thereby making this method more backward compatible. """ + + Build = autoclass('android.os.Build') PythonActivity = autoclass('org.kivy.android.PythonActivity') - context = PythonActivity.mActivity SettingsSecure = autoclass('android.provider.Settings$Secure') - return SettingsSecure.getString(context.getContentResolver(), "device_name") + + context = PythonActivity.mActivity + name = SettingsSecure.getString(context.getContentResolver(), "device_name") + + if not name: + name = Build.MODEL def instance(): From 520bdde58d1018af4f975c29a21b5618f2b5ec30 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 24 Mar 2025 21:10:53 +0100 Subject: [PATCH 21/26] fixed issue --- plyer/platforms/android/devicename.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plyer/platforms/android/devicename.py b/plyer/platforms/android/devicename.py index 64b950a3c..e522ca304 100644 --- a/plyer/platforms/android/devicename.py +++ b/plyer/platforms/android/devicename.py @@ -32,6 +32,8 @@ def _get_device_name(self): if not name: name = Build.MODEL + return name + def instance(): ''' From c6c150d534bba3904dde761cadeb36ca755c6079 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Mon, 24 Mar 2025 21:21:08 +0100 Subject: [PATCH 22/26] fixed? --- plyer/platforms/android/devicename.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plyer/platforms/android/devicename.py b/plyer/platforms/android/devicename.py index e522ca304..1a6d243e4 100644 --- a/plyer/platforms/android/devicename.py +++ b/plyer/platforms/android/devicename.py @@ -24,10 +24,10 @@ def _get_device_name(self): Build = autoclass('android.os.Build') PythonActivity = autoclass('org.kivy.android.PythonActivity') - SettingsSecure = autoclass('android.provider.Settings$Secure') + SettingsGlobal = autoclass('android.provider.Settings$Global') context = PythonActivity.mActivity - name = SettingsSecure.getString(context.getContentResolver(), "device_name") + name = SettingsGlobal.getString(context.getContentResolver(), SettingsGlobal.DEVICE_NAME) if not name: name = Build.MODEL From 40c7a47f7a5661d3c1c3be9909b6c17448c26a3d Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 30 Jul 2025 01:15:44 +0200 Subject: [PATCH 23/26] added getting screen orientation --- plyer/facades/orientation.py | 9 ++++++++ plyer/platforms/android/orientation.py | 16 +++++++++++++ plyer/platforms/linux/orientation.py | 31 ++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/plyer/facades/orientation.py b/plyer/facades/orientation.py index 077de5538..57b4529e0 100644 --- a/plyer/facades/orientation.py +++ b/plyer/facades/orientation.py @@ -40,6 +40,12 @@ class Orientation: Orientation facade. ''' + def get_orientation(self) -> str: + ''' + Return current screen rotation (landscape, landscape-reversed, portrait, portrait-reversed, unknown) + ''' + return self._get_landscape() + def set_landscape(self, reverse=False): ''' Rotate the app to a landscape orientation. @@ -71,6 +77,9 @@ def set_sensor(self, mode='any'): # private + def _get_landscape(self, **kwargs): + raise NotImplementedError() + def _set_landscape(self, **kwargs): raise NotImplementedError() diff --git a/plyer/platforms/android/orientation.py b/plyer/platforms/android/orientation.py index 5f10958f9..1f8332442 100644 --- a/plyer/platforms/android/orientation.py +++ b/plyer/platforms/android/orientation.py @@ -3,6 +3,7 @@ from plyer.facades import Orientation ActivityInfo = autoclass('android.content.pm.ActivityInfo') +Surface = autoclass('android.view.Surface') class AndroidOrientation(Orientation): @@ -38,6 +39,21 @@ def _set_sensor(self, **kwargs): activity.setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) + def _get_orientation(self): + rotation = activity.getWindowManager().getDefaultDisplay().getRotation() + + if rotation == Surface.ROTATION_0: + return 'portrait' + if rotation == Surface.ROTATION_90: + return 'landscape' + if rotation == Surface.ROTATION_180: + return 'portrait-reversed' + if rotation == Surface.ROTATION_270: + return 'landscape-reversed' + + return 'unknown' + + def instance(): return AndroidOrientation() diff --git a/plyer/platforms/linux/orientation.py b/plyer/platforms/linux/orientation.py index e60fa42b8..61aad29dd 100644 --- a/plyer/platforms/linux/orientation.py +++ b/plyer/platforms/linux/orientation.py @@ -5,7 +5,7 @@ class LinuxOrientation(Orientation): def _set_landscape(self, **kwargs): - self.rotate = 'normal' + self.rotate = 'inverted' if kwargs['reverse'] else 'normal' self.screen = sb.check_output( "xrandr -q | grep ' connected' | head -n 1 | cut -d ' ' -f1", shell=True @@ -14,7 +14,7 @@ def _set_landscape(self, **kwargs): sb.call(["xrandr", "--output", self.screen, "--rotate", self.rotate]) def _set_portrait(self, **kwargs): - self.rotate = 'left' + self.rotate = 'right' if kwargs['reverse'] else 'left' self.screen = sb.check_output( "xrandr -q | grep ' connected' | head -n 1 | cut -d ' ' -f1", shell=True @@ -22,6 +22,33 @@ def _set_portrait(self, **kwargs): self.screen = self.screen.decode('utf-8').split('\n')[0] sb.call(["xrandr", "--output", self.screen, "--rotate", self.rotate]) + def _get_orientation(self, **kwargs): + self.screen = sb.check_output( + "xrandr -q | grep ' connected' | head -n 1 | cut -d ' ' -f1", + shell=True + ) + self.screen = self.screen.decode('utf-8').split('\n')[0] + + try: + orientation = sb.check_output( + f"xrandr -q --verbose | grep {self.screen} | sed 's/primary //' | awk '{{print $5}}'", + shell=True + ).decode('utf-8').strip() + except Exception: + return 'unknown' + + if orientation == 'normal': + return 'landscape' + + if orientation == 'inverted': + return 'landscape-reversed' + + if orientation == 'left': + return 'portrait' + + if orientation == 'right': + return 'portrait-reversed' + def instance(): return LinuxOrientation() From c5ff87221634b7249e77180c7c8eb5710d27ca6c Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 30 Jul 2025 16:18:43 +0200 Subject: [PATCH 24/26] added encryption --- plyer/platforms/android/keystore.py | 69 +++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/plyer/platforms/android/keystore.py b/plyer/platforms/android/keystore.py index 0339948c2..4cc62ec2d 100644 --- a/plyer/platforms/android/keystore.py +++ b/plyer/platforms/android/keystore.py @@ -1,10 +1,21 @@ +import base64 +import json + +from jnius import autoclass + from plyer.facades import Keystore from plyer.platforms.android import activity class AndroidKeystore(Keystore): - def _set_key(self, servicename, key, value, **kwargs): + cipher_text, iv = self.encrypt_value(value, servicename) + + value = json.dumps({ + 'cipher': base64.b64encode(cipher_text).decode(), + 'iv': base64.b64encode(iv).decode() + }) + mode = kwargs.get("mode", 0) settings = activity.getSharedPreferences(servicename, mode) editor = settings.edit() @@ -14,12 +25,62 @@ def _set_key(self, servicename, key, value, **kwargs): 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 + if ret == default: + return None + + blob = json.loads(ret) + return self.decrypt_value(servicename, blob) + + def encrypt_value(self, value, servicename): + Cipher = autoclass('javax.crypto.Cipher') + secret_key = self.get_secret_key(servicename) + + cipher = Cipher.getInstance("AES/GCM/NoPadding") + cipher.init(Cipher.ENCRYPT_MODE, secret_key) + + ciphertext = cipher.doFinal(value.encode("utf-8")) + iv = cipher.getIV() + return ciphertext, iv + + def decrypt_value(self, servicename, data): + GCMParameterSpec = autoclass('javax.crypto.spec.GCMParameterSpec') + Cipher = autoclass('javax.crypto.Cipher') + String = autoclass('java.lang.String') + + secret_key = self.get_secret_key(servicename) + cipher = Cipher.getInstance("AES/GCM/NoPadding") + + iv = base64.b64decode(data['iv']) + ct = base64.b64decode(data['cipher']) + + spec = GCMParameterSpec(128, iv) + cipher.init(Cipher.DECRYPT_MODE, secret_key, spec) + plaintext_bytes = cipher.doFinal(ct) + return str(String(plaintext_bytes, "UTF-8")) + + @staticmethod + def get_secret_key(servicename): + KeyProperties = autoclass('android.security.keystore.KeyProperties') + KeyGenerator = autoclass('javax.crypto.KeyGenerator') + KeyGenParameterSpec = autoclass('android.security.keystore.KeyGenParameterSpec$Builder') + KeyStore = autoclass('java.security.KeyStore') + + key_store = KeyStore.getInstance("AndroidKeyStore") + key_store.load(None) + + if not key_store.containsAlias(servicename): + builder = KeyGenParameterSpec(servicename, + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + builder.setBlockModes(KeyProperties.BLOCK_MODE_GCM) + builder.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + key_gen = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") + key_gen.init(builder.build()) + key_gen.generateKey() + return key_store.getKey(servicename, None) def instance(): return AndroidKeystore() From 1468c9521796c88871a92eef844113b904d78fcc Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 8 Oct 2025 11:44:24 +0200 Subject: [PATCH 25/26] updated --- plyer/platforms/android/orientation.py | 19 ++++++++----------- plyer/platforms/linux/orientation.py | 18 +++++++----------- plyer/platforms/macosx/gps.py | 3 +++ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/plyer/platforms/android/orientation.py b/plyer/platforms/android/orientation.py index 1f8332442..1624e319b 100644 --- a/plyer/platforms/android/orientation.py +++ b/plyer/platforms/android/orientation.py @@ -40,19 +40,16 @@ def _set_sensor(self, **kwargs): ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) def _get_orientation(self): - rotation = activity.getWindowManager().getDefaultDisplay().getRotation() - - if rotation == Surface.ROTATION_0: - return 'portrait' - if rotation == Surface.ROTATION_90: - return 'landscape' - if rotation == Surface.ROTATION_180: - return 'portrait-reversed' - if rotation == Surface.ROTATION_270: - return 'landscape-reversed' + orientations = { + Surface.ROTATION_0: 'portrait', + Surface.ROTATION_90: 'landscape', + Surface.ROTATION_180: 'portrait-reversed', + Surface.ROTATION_270: 'landscape-reversed', + } - return 'unknown' + rotation = activity.getWindowManager().getDefaultDisplay().getRotation() + return orientations.get(rotation, 'unknown') def instance(): diff --git a/plyer/platforms/linux/orientation.py b/plyer/platforms/linux/orientation.py index 61aad29dd..80127d336 100644 --- a/plyer/platforms/linux/orientation.py +++ b/plyer/platforms/linux/orientation.py @@ -37,17 +37,13 @@ def _get_orientation(self, **kwargs): except Exception: return 'unknown' - if orientation == 'normal': - return 'landscape' - - if orientation == 'inverted': - return 'landscape-reversed' - - if orientation == 'left': - return 'portrait' - - if orientation == 'right': - return 'portrait-reversed' + orientations = { + 'normal': 'landscape', + 'inverted': 'landscape-reversed', + 'left': 'portrait', + 'right': 'portrait-reversed' + } + return orientations.get(orientation, 'unknown') def instance(): diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index 7119b9db8..ffedc2cd4 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -44,6 +44,9 @@ def _run_loop(self): time.sleep(0.1) def _start(self, **kwargs): + if not hasattr(self, '_location_manager'): + self._configure() + min_distance = kwargs.get('minDistance') self._location_manager.distanceFilter = min_distance From e06c16918e53e333aaa15634079e1a90f0739121 Mon Sep 17 00:00:00 2001 From: Gvozdev Leonid Date: Wed, 8 Oct 2025 14:54:31 +0200 Subject: [PATCH 26/26] fixed issue --- plyer/platforms/macosx/gps.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plyer/platforms/macosx/gps.py b/plyer/platforms/macosx/gps.py index ffedc2cd4..264c8cf9e 100644 --- a/plyer/platforms/macosx/gps.py +++ b/plyer/platforms/macosx/gps.py @@ -45,7 +45,8 @@ def _run_loop(self): def _start(self, **kwargs): if not hasattr(self, '_location_manager'): - self._configure() + self.on_status('provider-disabled', 'standard-macos-provider: denied') + return min_distance = kwargs.get('minDistance') self._location_manager.distanceFilter = min_distance @@ -58,7 +59,8 @@ def _start(self, **kwargs): self._is_running = True def _stop(self): - self._location_manager.stopUpdatingLocation() + if hasattr(self, '_location_manager'): + self._location_manager.stopUpdatingLocation() self._is_running = False @protocol('CLLocationManagerDelegate')