Source code for enamlnative.android.android_wifi

"""
Copyright (c) 2017-2022, CodeLV.

Distributed under the terms of the MIT License.

The full license is in the file LICENSE, distributed with this software.

Created on Nov 18, 2017


"""
from atom.api import List
from .android_activity import Activity
from .android_content import BroadcastReceiver, IntentFilter, SystemService
from .app import AndroidApplication
from .bridge import JavaBridgeObject, JavaField, JavaMethod


class WifiConfiguration(JavaBridgeObject):
    __nativeclass__ = "android.net.wifi.WifiConfiguration"
    BSSID = JavaField(str)
    FQDN = JavaField(str)
    SSID = JavaField(str)
    hiddenSSID = JavaField(bool)
    networkId = JavaField(int)
    preSharedKey = JavaField(str)
    status = JavaField(int)

    STATUS_CURRENT = 0x0
    STATUS_DISABLED = 0x1
    STATUS_ENABLED = 0x2


[docs]class WifiManager(SystemService): """Access android's WifiManager. Use the static class methods. To Get networks use: WifiManager.get_networks().then(on_results) It will request and enable if wifi allowed. Returns None if access is denied otherwise the list of networks. To check if wifi is enabled use: WifiManager.is_wifi_enabled().then(on_result) Returns None if access is denied otherwise the result To set wifi enabled use: WifiManager.set_wifi_enabled(state=True).then(on_result) Returns None if access is denied otherwise the result """ SERVICE_TYPE = Activity.WIFI_SERVICE __nativeclass__ = "android.new.wifi.WifiManager" PERMISSION_ACCESS_FINE_LOCATION = "android.permission." "ACCESS_FINE_LOCATION" PERMISSION_ACCESS_COARSE_LOCATION = "android.permission." "ACCESS_COARSE_LOCATION" PERMISSION_ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE" PERMISSION_CHANGE_WIFI_STATE = "android.permission.CHANGE_WIFI_STATE" PERMISSIONS_REQUIRED = [ # PERMISSION_ACCESS_FINE_LOCATION, PERMISSION_ACCESS_COARSE_LOCATION, PERMISSION_ACCESS_WIFI_STATE, PERMISSION_CHANGE_WIFI_STATE, ] SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS" getScanResults = JavaMethod(returns="java.util.List") setWifiEnabled = JavaMethod(bool, returns=bool) isWifiEnabled = JavaMethod(returns=bool) startScan = JavaMethod(returns=bool) reassociate = JavaMethod(returns=bool) reconnect = JavaMethod(returns=bool) removeNetwork = JavaMethod(int, returns=bool) addNetwork = JavaMethod("android.net.wifi.WifiConfiguration", returns=int) enableNetwork = JavaMethod(int, bool, returns=bool) disconnect_ = JavaMethod(returns=bool) getConnectionInfo = JavaMethod(returns="android.net.wifi.WifiInfo") getDhcpInfo = JavaMethod(returns="android.net.DhcpInfo") #: List of receivers _receivers = List(BroadcastReceiver) # ------------------------------------------------------------------------- # Public api # -------------------------------------------------------------------------
[docs] @classmethod async def is_wifi_enabled(cls) -> bool: """Check if wifi is currently enabled. Returns -------- result: bool Whether wifi is enabled """ has_perm = await WifiManager.request_permission( WifiManager.PERMISSION_ACCESS_WIFI_STATE ) if not has_perm: raise RuntimeError("Wifi permission denied") mgr = await WifiManager.get() return await mgr.isWifiEnabled()
[docs] @classmethod async def set_wifi_enabled(cls, state: bool = True) -> bool: """Set the wifi enabled state. Returns -------- enabled: bool Whether the operation succeeded. """ allowed = await WifiManager.request_permission( WifiManager.PERMISSION_CHANGE_WIFI_STATE ) if not allowed: raise RuntimeError("Permission to change wifi state is not allowed") mgr = await WifiManager.get() return await mgr.setWifiEnabled(state)
[docs] @classmethod async def get_networks(cls): """Get the wifi networks currently available. Returns -------- result: future A future that resolves with the list of networks available or None if wifi could not be enabled (permission denied, etc...) """ app = AndroidApplication.instance() allowed = await WifiManager.request_permission( *WifiManager.PERMISSIONS_REQUIRED ) if not allowed: raise RuntimeError("Permission to get networks is not allowed") mgr = await WifiManager.get() # Enable if needed enabled = await mgr.setWifiEnabled(True) if not enabled: raise RuntimeError("Could not enable wifi") # Register a receiver so we know when the scan # is complete receiver = BroadcastReceiver() receiver.setReceiver(receiver.getId()) scan_results = app.create_future() def on_scan_ready(f): scan_results.set_result(f.result()) def on_scan_complete(context, intent): # Finally, pull the scan results mgr.getScanResults().add_done_callback(on_scan_ready) # Hook up a callback that's fired when the scan # results are ready receiver.onReceive.connect(on_scan_complete) # Register the receiver intent_filter = IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) activity = app.widget activity.registerReceiver(receiver, intent_filter) try: # Trigger a scan which "should" eventually call on_scan_complete mgr.startScan() return await scan_results finally: activity.unregisterReceiver(receiver)
[docs] @classmethod async def disconnect(cls): """Disconnect from the current network (if connected). Returns -------- result: future A future that resolves to true if the disconnect was successful. Will be set to None if the change network permission is denied. """ allowed = await WifiManager.request_permission( WifiManager.PERMISSION_CHANGE_WIFI_STATE ) if not allowed: raise RuntimeError("Permission to toggle wifi state not allowed") mgr = await WifiManager.get() return await mgr.disconnect()
[docs] @classmethod async def connect(cls, ssid, key=None, **kwargs): """Connect to the given ssid using the key (if given). Returns -------- result: future A future that resolves with the result of the connect """ allowed = await WifiManager.request_permission( *WifiManager.PERMISSIONS_REQUIRED ) if not allowed: raise RuntimeError("Permission to toggle wifi state not allowed") config = WifiConfiguration() config.SSID = f'"{ssid}"' if key is not None: config.preSharedKey = f'"{ssid}"' #: Set any other parameters for k, v in kwargs.items(): setattr(config, k, v) mgr = await WifiManager.get() #: Enable if needed disconnected = await mgr.disconnect_() if not disconnected: raise RuntimeError("Could not disconnect wifi") enabled = await mgr.setWifiEnabled(True) if not enabled: raise RuntimeError("Could not enable wifi") net_id = await mgr.addNetwork(config) if net_id == -1: raise ValueError("Warning: Invalid network configuration") net_enabled = await mgr.enableNetwork(net_id, True) if not net_enabled: raise RuntimeError("Could not enable network") return await mgr.reconnect()
[docs] @classmethod async def get_connection_info(cls): """Get info about current wifi connection (if any). Returns info such as the IP address, BSSID, link speed, signal, etc.. Returns -------- result: future A future that resolves with a dict of the connection info or None if an error occurred (ie permission denied). """ allowed = await WifiManager.request_permission( WifiManager.PERMISSION_ACCESS_WIFI_STATE ) if not allowed: raise RuntimeError("Access wifi state permission not allowed") mgr = await WifiManager.get() return await mgr.getConnectionInfo()
[docs] @classmethod async def get_dhcp_info(cls): """Get info about current DHCP configuration such as DNS servers, IP address, and lease duration. Returns -------- result: future A future that resolves with a dict of the DHCP info or None if an error occured (ie permission denied).s """ allowed = await WifiManager.request_permission( WifiManager.PERMISSION_ACCESS_WIFI_STATE ) if not allowed: raise RuntimeError("Access wifi state permission not allowed") mgr = await WifiManager.get() return await mgr.getDhcpInfo()
[docs] @classmethod async def request_permission(cls, *permissions) -> bool: """Requests permission and returns an future result that returns a boolean indicating if all the given permission were granted or denied. """ app = AndroidApplication.instance() perms = await app.request_permissions(*permissions) for p in permissions: if not perms.get(p, False): return False return True
[docs] def __del__(self): """Remove any receivers before destroying""" app = AndroidApplication.instance() activity = app.widget for r in self._receivers: activity.unregisterReceiver(r) super().__del__()