package org.andengine.util;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Enumeration;
import org.andengine.util.adt.array.ArrayUtils;
import org.andengine.util.exception.AndEngineException;
import org.andengine.util.exception.MethodNotFoundException;
import org.andengine.util.system.SystemUtils;
import android.annotation.TargetApi;
import android.content.Context;
import android.net.DhcpInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.Build;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 16:54:01 - 20.03.2011
*/
public final class WifiUtils {
// ===========================================================
// Constants
// ===========================================================
private static final String IP_DEFAULT = "0.0.0.0";
private static final String[] HOTSPOT_NETWORKINTERFACE_NAMES = { "wl0.1", "wlan0" };
private static final String MULTICASTLOCK_NAME_DEFAULT = "AndEngineMulticastLock";
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
private WifiUtils() {
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public static WifiManager getWifiManager(final Context pContext) {
return (WifiManager) pContext.getSystemService(Context.WIFI_SERVICE);
}
public static boolean isWifiEnabled(final Context pContext) {
return WifiUtils.getWifiManager(pContext).isWifiEnabled();
}
private static void setWifiEnabled(final Context pContext, final boolean pEnabled) {
WifiUtils.getWifiManager(pContext).setWifiEnabled(pEnabled);
}
public static String getWifiSSID(final Context pContext) {
return WifiUtils.getWifiManager(pContext).getConnectionInfo().getSSID();
}
public static String getWifiSSID(final Context pContext, final boolean pStripQuotes) {
final String wifiSSID = WifiUtils.getWifiSSID(pContext);
if (pStripQuotes) {
return WifiUtils.stripQuotes(wifiSSID);
} else {
return wifiSSID;
}
}
public static byte[] getWifiIPv4AddressRaw(final Context pContext) {
return IPUtils.ipv4AddressToIPAddress(WifiUtils.getWifiManager(pContext).getConnectionInfo().getIpAddress());
}
public static String getWifiIPv4Address(final Context pContext) throws WifiUtilsException {
try {
return IPUtils.ipAddressToString(WifiUtils.getWifiIPv4AddressRaw(pContext));
} catch (final UnknownHostException e) {
throw new WifiUtilsException("Unexpected error!", e);
}
}
public static boolean isWifiIPAddressValid(final Context pContext) {
return WifiUtils.getWifiManager(pContext).getConnectionInfo().getIpAddress() != 0;
}
/**
* The check currently performed is not sufficient, as some carriers disabled this feature manually!
*/
public static boolean isWifiHotspotSupported(final Context pContext) {
if (SystemUtils.isAndroidVersionOrLower(Build.VERSION_CODES.ECLAIR_MR1)) {
return false;
} else {
final WifiManager wifiManager = WifiUtils.getWifiManager(pContext);
try {
final Method WifiManager_isWifiApEnabled = wifiManager.getClass().getMethod("isWifiApEnabled");
return WifiManager_isWifiApEnabled != null;
} catch (final Throwable t) {
return false;
}
}
}
public static boolean isWifiHotspotEnabled(final Context pContext) throws WifiUtilsException {
final WifiManager wifiManager = WifiUtils.getWifiManager(pContext);
try {
final Method WifiManager_isWifiApEnabled = wifiManager.getClass().getMethod("isWifiApEnabled");
if (WifiManager_isWifiApEnabled == null) {
throw new WifiUtilsException(new MethodNotFoundException(WifiManager.class.getSimpleName() + ".isWifiApEnabled()"));
} else {
final boolean result = (Boolean) WifiManager_isWifiApEnabled.invoke(wifiManager);
return result;
}
} catch (final Throwable t) {
throw new WifiUtilsException(t);
}
}
public static boolean isWifiHotspotEnabled(final Context pContext, final boolean pDefault) {
try {
return WifiUtils.isWifiHotspotEnabled(pContext);
} catch (final WifiUtilsException e) {
return pDefault;
}
}
public static boolean setWifiHostpotEnabled(final Context pContext, final boolean pEnabled) throws WifiUtilsException {
return WifiUtils.setWifiHostpotEnabled(pContext, null, pEnabled);
}
public static boolean setWifiHostpotEnabled(final Context pContext, final WifiConfiguration pWifiConfiguration, final boolean pEnabled) throws WifiUtilsException {
final WifiManager wifiManager = WifiUtils.getWifiManager(pContext);
try {
if (pEnabled) {
WifiUtils.setWifiEnabled(pContext, false);
}
final Method WifiManager_setWifiApEnabled = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
if (WifiManager_setWifiApEnabled == null) {
throw new WifiUtilsException(new MethodNotFoundException(WifiManager.class.getSimpleName() + ".setWifiApEnabled(" + WifiConfiguration.class.getSimpleName() + ", " + boolean.class.getSimpleName() + ")"));
} else {
final boolean result = (Boolean) WifiManager_setWifiApEnabled.invoke(wifiManager, pWifiConfiguration, pEnabled);
return result;
}
} catch (final Throwable t) {
throw new WifiUtilsException(t);
}
}
public static WifiConfiguration getWifiHotspotConfiguration(final Context pContext) throws WifiUtilsException {
final WifiManager wifiManager = WifiUtils.getWifiManager(pContext);
try {
final Method WifiManager_getWifiApState = wifiManager.getClass().getMethod("getWifiApConfiguration");
if (WifiManager_getWifiApState == null) {
throw new WifiUtilsException(new MethodNotFoundException(WifiManager.class.getSimpleName() + ".getWifiApConfiguration()"));
} else {
return (WifiConfiguration)WifiManager_getWifiApState.invoke(wifiManager);
}
} catch (final Throwable t) {
throw new WifiUtilsException(t);
}
}
public static String getWifiHotspotSSID(final Context pContext) throws WifiUtilsException {
return WifiUtils.getWifiHotspotConfiguration(pContext).SSID;
}
public static String getWifiHotspotSSID(final Context pContext, final boolean pStripQuotes) throws WifiUtilsException {
final String wifiHotspotSSID = WifiUtils.getWifiHotspotSSID(pContext);
if (pStripQuotes) {
return WifiUtils.stripQuotes(wifiHotspotSSID);
} else {
return wifiHotspotSSID;
}
}
public static WifiHotspotState getWifiHotspotState(final Context pContext) throws WifiUtilsException {
final WifiManager wifiManager = WifiUtils.getWifiManager(pContext);
try {
final Method WifiManager_getWifiApState = wifiManager.getClass().getMethod("getWifiApState");
if (WifiManager_getWifiApState == null) {
throw new WifiUtilsException(new MethodNotFoundException(WifiManager.class.getSimpleName() + ".getWifiApState()"));
} else {
final int result = (Integer) WifiManager_getWifiApState.invoke(wifiManager);
return WifiHotspotState.fromWifiApState(result);
}
} catch (final Throwable t) {
throw new WifiUtilsException(t);
}
}
public static boolean isWifiHotspotRunning(final Context pContext) throws WifiUtilsException {
return WifiUtils.getWifiHotspotState(pContext) == WifiHotspotState.ENABLED;
}
/**
* @return prefers to return an IPv4 address if found, otherwise an IPv6 address.
* @throws WifiUtilsException
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public static byte[] getWifiHotspotIPAddressRaw() throws WifiUtilsException {
try {
byte[] ipv6Address = null;
final Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
while (networkInterfaceEnumeration.hasMoreElements()) {
final NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
if (SystemUtils.isAndroidVersionOrLower(Build.VERSION_CODES.FROYO) || !networkInterface.isLoopback()) {
final String networkInterfaceName = networkInterface.getName();
if (ArrayUtils.contains(WifiUtils.HOTSPOT_NETWORKINTERFACE_NAMES, networkInterfaceName)) {
final Enumeration<InetAddress> inetAddressEnumeration = networkInterface.getInetAddresses();
while (inetAddressEnumeration.hasMoreElements()) {
final InetAddress inetAddress = inetAddressEnumeration.nextElement();
if (!inetAddress.isLoopbackAddress()) {
final byte[] ipAddress = inetAddress.getAddress();
if (ipAddress.length == IPUtils.IPV4_LENGTH) {
return ipAddress;
} else {
ipv6Address = ipAddress;
}
}
}
}
}
}
if (ipv6Address != null) {
return ipv6Address;
} else {
throw new WifiUtilsException("No IP bound to '" + Arrays.toString(WifiUtils.HOTSPOT_NETWORKINTERFACE_NAMES) + "'!");
}
} catch (final SocketException e) {
throw new WifiUtilsException("Unexpected error!", e);
}
}
public static String getWifiHotspotIPAddress() throws WifiUtilsException {
try {
return IPUtils.ipAddressToString(WifiUtils.getWifiHotspotIPAddressRaw());
} catch (final UnknownHostException e) {
throw new WifiUtilsException("Unexpected error!", e);
}
}
public static boolean isWifiHotspotIPAddressValid() throws WifiUtilsException { // TODO!
return !WifiUtils.IP_DEFAULT.equals(WifiUtils.getWifiHotspotIPAddress());
}
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public static byte[] getEmulatorIPAddressRaw() throws WifiUtilsException {
try {
byte[] ipv6Address = null;
final Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
while (networkInterfaceEnumeration.hasMoreElements()) {
final NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
if (SystemUtils.isAndroidVersionOrLower(Build.VERSION_CODES.FROYO) || !networkInterface.isLoopback()) {
final Enumeration<InetAddress> inetAddressEnumeration = networkInterface.getInetAddresses();
while (inetAddressEnumeration.hasMoreElements()) {
final InetAddress inetAddress = inetAddressEnumeration.nextElement();
if (!inetAddress.isLoopbackAddress()) {
final byte[] ipAddress = inetAddress.getAddress();
if (ipAddress.length == IPUtils.IPV4_LENGTH) {
return ipAddress;
} else {
ipv6Address = ipAddress;
}
}
}
}
}
if (ipv6Address != null) {
return ipv6Address;
} else {
throw new WifiUtilsException("No IP found that is not bound to localhost!");
}
} catch (final SocketException e) {
throw new WifiUtilsException("Unexpected error!", e);
}
}
public static String getEmulatorIPAddress() throws WifiUtilsException {
try {
return IPUtils.ipAddressToString(WifiUtils.getEmulatorIPAddressRaw());
} catch (final UnknownHostException e) {
throw new WifiUtilsException("Unexpected error!", e);
}
}
public static boolean getEmulatorIPAddressValid() throws WifiUtilsException { // TODO!
return !WifiUtils.IP_DEFAULT.equals(WifiUtils.getEmulatorIPAddress());
}
public static boolean isMulticastEnabled(final Context pContext) throws WifiUtilsException {
final WifiManager wifiManager = WifiUtils.getWifiManager(pContext);
try {
final Method WifiManager_isMulticastEnabled = wifiManager.getClass().getMethod("isMulticastEnabled");
if (WifiManager_isMulticastEnabled == null) {
throw new WifiUtilsException(new MethodNotFoundException(WifiManager.class.getSimpleName() + ".isMulticastEnabled()"));
} else {
final boolean result = (Boolean) WifiManager_isMulticastEnabled.invoke(wifiManager);
return result;
}
} catch (final Throwable t) {
throw new WifiUtilsException(t);
}
}
public static boolean isMulticastEnabled(final Context pContext, final boolean pDefault) {
try {
return WifiUtils.isMulticastEnabled(pContext);
} catch (final WifiUtilsException e) {
return pDefault;
}
}
public static MulticastLock aquireMulticastLock(final Context pContext) {
return WifiUtils.aquireMulticastLock(pContext, WifiUtils.MULTICASTLOCK_NAME_DEFAULT);
}
public static MulticastLock aquireMulticastLock(final Context pContext, final String pMulticastLockName) {
final WifiManager wifiManager = WifiUtils.getWifiManager(pContext);
final MulticastLock multicastLock = wifiManager.createMulticastLock(pMulticastLockName);
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
return multicastLock;
}
public static void releaseMulticastLock(final MulticastLock pMulticastLock) {
if (pMulticastLock.isHeld()) {
pMulticastLock.release();
}
}
public static byte[] getBroadcastIPAddressRaw(final Context pContext) throws WifiUtilsException {
final WifiManager wifiManager = WifiUtils.getWifiManager(pContext);
final DhcpInfo dhcp = wifiManager.getDhcpInfo();
// TODO handle null somehow...
final int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
final byte[] broadcastIP = new byte[IPUtils.IPV4_LENGTH];
for (int k = 0; k < IPUtils.IPV4_LENGTH; k++) {
broadcastIP[k] = (byte) ((broadcast >> (k * 8)) & 0xFF);
}
return broadcastIP;
}
private static String stripQuotes(final String pString) {
if (pString == null) {
return pString;
} else {
final int stringLength = pString.length();
if (stringLength >= 2) {
if (pString.startsWith("\"") && pString.endsWith("\"") ) {
return pString.substring(1, stringLength - 1);
} else {
return pString;
}
} else {
return pString;
}
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public static enum WifiHotspotState {
// ===========================================================
// Elements
// ===========================================================
DISABLING,
DISABLED,
ENABLING,
ENABLED,
FAILED;
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
public static WifiHotspotState fromWifiApState(final int pWifiApState) throws WifiUtilsException {
if (SystemUtils.isAndroidVersionOrHigher(Build.VERSION_CODES.ICE_CREAM_SANDWICH)) {
switch (pWifiApState) {
case 10:
return DISABLING;
case 11:
return DISABLED;
case 12:
return ENABLING;
case 13:
return ENABLED;
case 14:
return FAILED;
default:
throw new WifiUtilsException("TODO...");
}
} else {
switch (pWifiApState) {
case 0:
return DISABLING;
case 1:
return DISABLED;
case 2:
return ENABLING;
case 3:
return ENABLED;
case 4:
return FAILED;
default:
if (pWifiApState >= 10) {
return WifiHotspotState.fromWifiApState(pWifiApState - 10);
} else {
throw new WifiUtilsException("TODO...");
}
}
}
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
public static class WifiUtilsException extends AndEngineException {
// ===========================================================
// Constants
// ===========================================================
private static final long serialVersionUID = 1108697754015225179L;
// ===========================================================
// Constructors
// ===========================================================
public WifiUtilsException() {
}
public WifiUtilsException(final Throwable pThrowable) {
super(pThrowable);
}
private WifiUtilsException(final String pMessage) {
super(pMessage);
}
private WifiUtilsException(final String pMessage, final Throwable pThrowable) {
super(pMessage, pThrowable);
}
}
}