Improve WifiManager support in sl4a.
Add APIs to wifi manager facade.
Add ConnectivityManager support
Improve README
Change-Id: I8d888f54e5a3d5ba01ed7fb930d095db032c5dcf
diff --git a/Common/src/com/googlecode/android_scripting/facade/ConnectivityManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/ConnectivityManagerFacade.java
new file mode 100644
index 0000000..b453b7a
--- /dev/null
+++ b/Common/src/com/googlecode/android_scripting/facade/ConnectivityManagerFacade.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.googlecode.android_scripting.facade;
+
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+import com.googlecode.android_scripting.Log;
+import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
+import com.googlecode.android_scripting.rpc.Rpc;
+
+/**
+ * Access ConnectivityManager functions.
+ */
+public class ConnectivityManagerFacade extends RpcReceiver {
+ private final Service mService;
+ private final ConnectivityManager mCon;
+
+ public ConnectivityManagerFacade(FacadeManager manager) {
+ super(manager);
+ mService = manager.getService();
+ mCon = (ConnectivityManager) mService.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+
+ class ConnectivityReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ Log.d("Connectivity state changed.");
+ }
+ }
+ }
+
+ @Rpc(description = "Check whether the active network is connected to the Internet.")
+ public Boolean networkIsConnected() {
+ NetworkInfo current = mCon.getActiveNetworkInfo();
+ if (current == null) {
+ Log.d("No network is active at the moment.");
+ return false;
+ }
+ return current.isConnected();
+ }
+
+ @Override
+ public void shutdown() {
+ }
+}
diff --git a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiManagerFacade.java
index 7c52fb2..d1ef771 100644
--- a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiManagerFacade.java
@@ -5,10 +5,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager.WifiLock;
import android.os.Bundle;
@@ -21,6 +23,7 @@
import com.googlecode.android_scripting.rpc.RpcParameter;
import java.net.ConnectException;
+import java.util.HashMap;
import java.util.List;
/**
@@ -33,19 +36,33 @@
private final static String mEventType = "WiFiManager";
private final Service mService;
private final WifiManager mWifi;
- private final IntentFilter mIntentFilter;
- private final WifiScanReceiver mReceiver;
+ private final EventFacade mEventFacade;
+
+ private final IntentFilter mScanFilter;
+ private final IntentFilter mStateChangeFilter;
+ private final WifiScanReceiver mScanFinishedReceiver;
private final WifiActionListener mWifiActionListener;
+ private final WifiStateChangeReceiver mStateChangeReceiver;
+
private WifiLock mLock;
+ private boolean mIsConnected;
public WifiManagerFacade(FacadeManager manager) {
super(manager);
mService = manager.getService();
mWifi = (WifiManager) mService.getSystemService(Context.WIFI_SERVICE);
mLock = null;
- mIntentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
- mReceiver = new WifiScanReceiver(manager.getReceiver(EventFacade.class));
- mWifiActionListener = new WifiActionListener(manager.getReceiver(EventFacade.class));
+ mEventFacade = manager.getReceiver(EventFacade.class);
+
+ mScanFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+ mStateChangeFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mStateChangeFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+ mStateChangeFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
+ mStateChangeFilter.setPriority(999);
+
+ mScanFinishedReceiver = new WifiScanReceiver(mEventFacade);
+ mWifiActionListener = new WifiActionListener(mEventFacade);
+ mStateChangeReceiver = new WifiStateChangeReceiver();
}
private void makeLock(int wifiMode) {
@@ -56,7 +73,7 @@
}
/**
- * Handle Brodacst receiver for Scan Result
+ * Handle Broadcast receiver for Scan Result
* @parm eventFacade
* Object of EventFacade
*/
@@ -71,11 +88,12 @@
@Override
public void onReceive(Context c, Intent intent) {
- Log.d("WifiScanReceiver "+ mEventType);
+ Log.d("Wifi connection scan finished, results available.");
mResults.putLong("Timestamp", System.currentTimeMillis()/1000);
mResults.putString("Type", "onWifiScanReceive");
- mEventFacade.postEvent(mEventType, mResults.clone());
+ mEventFacade.postEvent("WifiScanFinished", mResults.clone());
mResults.clear();
+ mService.unregisterReceiver(mScanFinishedReceiver);
}
}
@@ -87,6 +105,7 @@
mEventFacade = eventFacade;
mResults = new Bundle();
}
+
@Override
public void onSuccess() {
Log.d("WifiActionListener "+ mEventType);
@@ -102,104 +121,92 @@
mEventFacade.postEvent(mEventType, mResults.clone());
mResults.clear();
}
-
}
- @Rpc(description = "Returns the list of access points found during the most recent Wifi scan.")
- public List<ScanResult> wifiGetScanResults() {
- mService.unregisterReceiver(mReceiver);
- return mWifi.getScanResults();
- }
-
- @Rpc(description = "Acquires a full Wifi lock.")
- public void wifiLockAcquireFull() {
- makeLock(WifiManager.WIFI_MODE_FULL);
- }
-
- @Rpc(description = "Acquires a scan only Wifi lock.")
- public void wifiLockAcquireScanOnly() {
- makeLock(WifiManager.WIFI_MODE_SCAN_ONLY);
- }
-
- @Rpc(description = "Releases a previously acquired Wifi lock.")
- public void wifiLockRelease() {
- if (mLock != null) {
- mLock.release();
- mLock = null;
+ public class WifiStateChangeReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ Log.d("Wifi network state changed.");
+ if (intent.hasExtra(WifiManager.EXTRA_WIFI_INFO)) {
+ WifiInfo wInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
+ Bundle msg = new Bundle();
+ String ssid = wInfo.getSSID();
+ if (ssid.charAt(0)=='"' && ssid.charAt(ssid.length()-1)=='"') {
+ msg.putString("ssid", ssid.substring(1, ssid.length()-1));
+ } else {
+ msg.putString("ssid", ssid);
+ }
+ msg.putString("bssid", wInfo.getBSSID());
+ mEventFacade.postEvent("WifiNetworkConnected", msg);
+ }
+ NetworkInfo nInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ WifiInfo wInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
+ Log.d("NetworkInfo " + nInfo);
+ Log.d("WifiInfo " + wInfo);
+ } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
+ Log.d("Supplicant connection state changed.");
+ mIsConnected = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false);
+ Bundle msg = new Bundle();
+ msg.putBoolean("Connected", mIsConnected);
+ mEventFacade.postEvent("SupplicantConnectionChanged", msg);
+ }
}
}
- @Rpc(description = "Starts a scan for Wifi access points.", returns = "True if the scan was initiated successfully.")
- public Boolean wifiStartScan() {
- mService.registerReceiver(mReceiver, mIntentFilter);
- return mWifi.startScan();
+ private WifiConfiguration wifiConfigurationFromScanResult(ScanResult result) {
+ if (result == null) return null;
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"" + result.SSID + "\"";
+ if (result.capabilities.contains("WEP")) {
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); //?
+ config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
+ }
+ if (result.capabilities.contains("PSK")) {
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ }
+ if (result.capabilities.contains("EAP")) {
+ //this is probably wrong, as we don't have a way to enter the enterprise config
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ }
+ if (result.capabilities.length() == 5 && result.capabilities.contains("ESS")) {
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ }
+ config.BSSID = result.BSSID;
+ config.scanResultCache = new HashMap<String, ScanResult>();
+ if (config.scanResultCache == null)
+ return null;
+ config.scanResultCache.put(result.BSSID, result);
+ return config;
+ }
+
+ private boolean matchScanResult(ScanResult result, String id) {
+ if (result.BSSID.equals(id) || result.SSID.equals(id)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Rpc(description = "Add a network.")
+ public Integer wifiAddNetwork(@RpcParameter(name = "wifiId") String wifiId) {
+ ScanResult target = null;
+ for (ScanResult r : mWifi.getScanResults()) {
+ if (matchScanResult(r, wifiId)) {
+ target = r;
+ break;
+ }
+ }
+ return mWifi.addNetwork(wifiConfigurationFromScanResult(target));
}
@Rpc(description = "Checks Wifi state.", returns = "True if Wifi is enabled.")
- public Boolean checkWifiState() {
+ public Boolean wifiCheckState() {
return mWifi.getWifiState() == WifiManager.WIFI_STATE_ENABLED;
}
- @Rpc(description = "Toggle Wifi on and off.", returns = "True if Wifi is enabled.")
- public Boolean toggleWifiState(@RpcParameter(name = "enabled") @RpcOptional Boolean enabled) {
- if (enabled == null) {
- enabled = !checkWifiState();
- }
- mWifi.setWifiEnabled(enabled);
- return enabled;
- }
-
- @Rpc(description = "Disconnects from the currently active access point.", returns = "True if the operation succeeded.")
- public Boolean wifiDisconnect() {
- return mWifi.disconnect();
- }
-
- @Rpc(description = "Returns information about the currently active access point.")
- public WifiInfo wifiGetConnectionInfo() {
- return mWifi.getConnectionInfo();
- }
-
- @Rpc(description = "Reassociates with the currently active access point.", returns = "True if the operation succeeded.")
- public Boolean wifiReassociate() {
- return mWifi.reassociate();
- }
-
- @Rpc(description = "Reconnects to the currently active access point.", returns = "True if the operation succeeded.")
- public Boolean wifiReconnect() {
- return mWifi.reconnect();
- }
-
- /**
- * Connects to a wifi network with priority
- *
- * @param wifiSSID
- * SSID of the wifi network
- * @param wifiPassword
- * password for the wifi network
- */
- @Rpc(description = "Connects a wifi network as priority by pasing ssid")
- public void wifiPriorityConnect(@RpcParameter(name = "wifiSSID") String wifiSSID,
- @RpcParameter(name = "wifiPassword") String wifiPassword) {
- WifiConfiguration wifiConfig = new WifiConfiguration();
- wifiConfig.SSID = "\"" + wifiSSID + "\"";
- if(wifiPassword == null)
- wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- else
- wifiConfig.preSharedKey = "\"" + wifiPassword + "\"";
- mWifi.connect(wifiConfig, mWifiActionListener);
- }
-
- /**
- * Forget to a wifi network with priority
- *
- * @param networkID
- * Id of wifi network
- */
- @Rpc(description = "Forget a wifi network with priority")
- public void wifiForgetNetwork(@RpcParameter(name = "wifiSSID") Integer newtorkId ) {
- mWifi.forget(newtorkId, mWifiActionListener);
- }
-
/**
* Connects to a WPA protected wifi network
*
@@ -210,7 +217,8 @@
* @return true on success
* @throws ConnectException
*/
- @Rpc(description = "Connects a wifi network by ssid", returns = "True if the operation succeeded.")
+ @Rpc(description = "Connects a wifi network by ssid",
+ returns = "True if the operation succeeded.")
public Boolean wifiConnectWPA(@RpcParameter(name = "wifiSSID") String wifiSSID,
@RpcParameter(name = "wifiPassword") String wifiPassword) throws ConnectException {
WifiConfiguration wifiConfig = new WifiConfiguration();
@@ -244,8 +252,129 @@
return status;
}
+ @Rpc(description = "Disconnects from the currently active access point.",
+ returns = "True if the operation succeeded.")
+ public Boolean wifiDisconnect() {
+ return mWifi.disconnect();
+ }
+
+ @Rpc(description = "Enable a configured network. Initiate a connection if disableOthers is true",
+ returns = "True if the operation succeeded.")
+ public Boolean wifiEnableNetwork(@RpcParameter(name = "netId") Integer netId,
+ @RpcParameter(name = "disableOthers") Boolean disableOthers) {
+ return mWifi.enableNetwork(netId, disableOthers);
+ }
+ /**
+ * Forget a wifi network with priority
+ *
+ * @param networkID
+ * Id of wifi network
+ */
+ @Rpc(description = "Forget a wifi network with priority")
+ public void wifiForgetNetwork(@RpcParameter(name = "wifiSSID") Integer newtorkId ) {
+ mWifi.forget(newtorkId, mWifiActionListener);
+ }
+
+ @Rpc(description = "Return a list of all the configured wifi networks.")
+ public List<WifiConfiguration> wifiGetConfiguredNetworks() {
+ return mWifi.getConfiguredNetworks();
+ }
+
+ @Rpc(description = "Returns information about the currently active access point.")
+ public WifiInfo wifiGetConnectionInfo() {
+ return mWifi.getConnectionInfo();
+ }
+
+ @Rpc(description = "Returns the list of access points found during the most recent Wifi scan.")
+ public List<ScanResult> wifiGetScanResults() {
+ return mWifi.getScanResults();
+ }
+
+ @Rpc(description = "Acquires a full Wifi lock.")
+ public void wifiLockAcquireFull() {
+ makeLock(WifiManager.WIFI_MODE_FULL);
+ }
+
+ @Rpc(description = "Acquires a scan only Wifi lock.")
+ public void wifiLockAcquireScanOnly() {
+ makeLock(WifiManager.WIFI_MODE_SCAN_ONLY);
+ }
+
+ @Rpc(description = "Releases a previously acquired Wifi lock.")
+ public void wifiLockRelease() {
+ if (mLock != null) {
+ mLock.release();
+ mLock = null;
+ }
+ }
+
+ /**
+ * Connects to a wifi network with priority
+ *
+ * @param wifiSSID
+ * SSID of the wifi network
+ * @param wifiPassword
+ * password for the wifi network
+ */
+ @Rpc(description = "Connects a wifi network as priority by pasing ssid")
+ public void wifiPriorityConnect(@RpcParameter(name = "wifiSSID") String wifiSSID,
+ @RpcParameter(name = "wifiPassword") String wifiPassword) {
+ WifiConfiguration wifiConfig = new WifiConfiguration();
+ wifiConfig.SSID = "\"" + wifiSSID + "\"";
+ if(wifiPassword == null)
+ wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ else
+ wifiConfig.preSharedKey = "\"" + wifiPassword + "\"";
+ mWifi.connect(wifiConfig, mWifiActionListener);
+ }
+
+ @Rpc(description = "Reassociates with the currently active access point.",
+ returns = "True if the operation succeeded.")
+ public Boolean wifiReassociate() {
+ return mWifi.reassociate();
+ }
+
+ @Rpc(description = "Reconnects to the currently active access point.",
+ returns = "True if the operation succeeded.")
+ public Boolean wifiReconnect() {
+ return mWifi.reconnect();
+ }
+
+ @Rpc(description = "Remove a configured network.",
+ returns = "True if the operation succeeded.")
+ public Boolean wifiRemoveNetwork(@RpcParameter(name = "netId") Integer netId) {
+ return mWifi.removeNetwork(netId);
+ }
+
+ @Rpc(description = "Starts a scan for Wifi access points.",
+ returns = "True if the scan was initiated successfully.")
+ public Boolean wifiStartScan() {
+ mService.registerReceiver(mScanFinishedReceiver, mScanFilter);
+ return mWifi.startScan();
+ }
+
+ @Rpc(description = "Start receiving wifi state change related broadcasts.")
+ public void wifiStartTrackingStateChange() {
+ mService.registerReceiver(mStateChangeReceiver, mStateChangeFilter);
+ }
+
+ @Rpc(description = "Stop receiving wifi state change related broadcasts.")
+ public void wifiStopTrackingStateChange() {
+ mService.unregisterReceiver(mStateChangeReceiver);
+ }
+
+ @Rpc(description = "Toggle Wifi on and off.", returns = "True if Wifi is enabled.")
+ public Boolean wifiToggleState(@RpcParameter(name = "enabled") @RpcOptional Boolean enabled) {
+ if (enabled == null) {
+ enabled = !wifiCheckState();
+ }
+ mWifi.setWifiEnabled(enabled);
+ return enabled;
+ }
+
@Override
public void shutdown() {
wifiLockRelease();
+ mService.unregisterReceiver(mStateChangeReceiver);
}
}
diff --git a/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java b/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
index 818c4b2..62421a0 100644
--- a/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
+++ b/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
@@ -41,6 +41,7 @@
import android.location.Location;
import android.net.wifi.RttManager.Capabilities;
import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.os.ParcelUuid;
@@ -171,6 +172,9 @@
if (data instanceof Capabilities) {
return buildRttCapabilities((Capabilities) data);
}
+ if (data instanceof WifiConfiguration) {
+ return buildWifiConfiguration((WifiConfiguration) data);
+ }
if (data instanceof byte[]) {
return Base64Codec.encodeBase64((byte[]) data);
}
@@ -432,6 +436,30 @@
return cap;
}
+ private static Object buildWifiConfiguration(WifiConfiguration data) throws JSONException {
+ JSONObject config = new JSONObject();
+ config.put("networkId", data.networkId);
+ // Trim the double quotes if exist
+ if (data.SSID.charAt(0)=='"' && data.SSID.charAt(data.SSID.length()-1)=='"') {
+ config.put("ssid", data.SSID.substring(1, data.SSID.length()-1));
+ } else {
+ config.put("ssid", data.SSID);
+ }
+ config.put("bssid", data.BSSID);
+ config.put("priority", data.priority);
+ config.put("hiddenSSID", data.hiddenSSID);
+ if (data.status==WifiConfiguration.Status.CURRENT) {
+ config.put("status", "CURRENT");
+ } else if (data.status==WifiConfiguration.Status.DISABLED) {
+ config.put("status", "DISABLED");
+ } else if (data.status==WifiConfiguration.Status.ENABLED) {
+ config.put("status", "ENABLED");
+ } else {
+ config.put("status", "UNKNOWN");
+ }
+ return config;
+ }
+
private static JSONObject buildJsonCellLocation(CellLocation cellLocation)
throws JSONException {
JSONObject result = new JSONObject();
diff --git a/README b/README
index 41f9585..16f45fd 100644
--- a/README
+++ b/README
@@ -1,9 +1,10 @@
-This directory contains projects related to the Scripting Layer For Android.
-ScriptingLayerForAndroid/ contains the main SL4A project.
+This directory contains the source code and project files of Scripting Layer For Android.
+ScriptingLayerForAndroid/ is the main project (the one that builds the apk).
-To build, modify the BRANCH_ROOT and other paths if necessary in build_all.sh
-Plug in your device and run build_all.sh
+The code that call API components are in Common/src/com/googlecode/android_scripting/facade. Most likely you only need to add/edit files in this directory.
-To run, add android.py to your $PYTHONPATH
+To build, you can either build the entire android tree or use the included build_all.sh. The script will build sl4a.apk and install it on your device.
+
+To run, follow the internal sl4a setup doc.
Note: the sl4a build is dependent on prebuilt libraries in your repo branch. So your local repo needs to be able to build first.
diff --git a/ScriptingLayer/src/com/googlecode/android_scripting/facade/FacadeConfiguration.java b/ScriptingLayer/src/com/googlecode/android_scripting/facade/FacadeConfiguration.java
index 1c26226..236c870 100644
--- a/ScriptingLayer/src/com/googlecode/android_scripting/facade/FacadeConfiguration.java
+++ b/ScriptingLayer/src/com/googlecode/android_scripting/facade/FacadeConfiguration.java
@@ -110,6 +110,7 @@
sFacadeClassList.add(BluetoothLeScanFacade.class);
sFacadeClassList.add(BluetoothGattFacade.class);
sFacadeClassList.add(BluetoothLeAdvertiseFacade.class);
+ sFacadeClassList.add(ConnectivityManagerFacade.class);
sFacadeClassList.add(DisplayFacade.class);
sFacadeClassList.add(TelecommManagerFacade.class);
sFacadeClassList.add(WifiPasspointManagerFacade.class);