Установите статический IP и шлюз программно в Android 6.x (зефир)
Может кто-нибудь сказать мне, как я могу установить статический IP и шлюз программно в Android 6?
Settings.System
больше не работает, и goolgle говорит, что WIFI_STATIC_IP
был устаревшим на уровне API 17 и вместо этого использует WifiManger
. К сожалению, я ничего не могу найти об этом в классах WifiManger
и WifiConfiguration
.
3 ответа:
Поскольку официального API нет, я должен придумать решение, изменив образцы из следующегокода snipet иэтого ответа . Это решение работает на устройствах от леденца и выше.
@SuppressWarnings("unchecked") public static void setStaticIpConfiguration(WifiManager manager, WifiConfiguration config, InetAddress ipAddress, int prefixLength, InetAddress gateway, InetAddress[] dns) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException, InstantiationException { // First set up IpAssignment to STATIC. Object ipAssignment = getEnumValue("android.net.IpConfiguration$IpAssignment", "STATIC"); callMethod(config, "setIpAssignment", new String[]{"android.net.IpConfiguration$IpAssignment"}, new Object[]{ipAssignment}); // Then set properties in StaticIpConfiguration. Object staticIpConfig = newInstance("android.net.StaticIpConfiguration"); Object linkAddress = newInstance("android.net.LinkAddress", new Class<?>[]{InetAddress.class, int.class}, new Object[]{ipAddress, prefixLength}); setField(staticIpConfig, "ipAddress", linkAddress); setField(staticIpConfig, "gateway", gateway); getField(staticIpConfig, "dnsServers", ArrayList.class).clear(); for (int i = 0; i < dns.length; i++) getField(staticIpConfig, "dnsServers", ArrayList.class).add(dns[i]); callMethod(config, "setStaticIpConfiguration", new String[]{"android.net.StaticIpConfiguration"}, new Object[]{staticIpConfig}); int netId = manager.updateNetwork(config); boolean result = netId != -1; if (result) { boolean isDisconnected = manager.disconnect(); boolean configSaved = manager.saveConfiguration(); boolean isEnabled = manager.enableNetwork(config.networkId, true); boolean isReconnected = manager.reconnect(); } }
Вспомогательные функции,
public static WifiConfiguration getCurrentWiFiConfiguration(Context context) { WifiConfiguration wifiConf = null; ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (networkInfo.isConnected()) { final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); final WifiInfo connectionInfo = wifiManager.getConnectionInfo(); if (connectionInfo != null && !TextUtils.isEmpty(connectionInfo.getSSID())) { List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks(); if (configuredNetworks != null) { for (WifiConfiguration conf : configuredNetworks) { if (conf.networkId == connectionInfo.getNetworkId()) { wifiConf = conf; break; } } } } } return wifiConf; } private static Object newInstance(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { return newInstance(className, new Class<?>[0], new Object[0]); } private static Object newInstance(String className, Class<?>[] parameterClasses, Object[] parameterValues) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException { Class<?> clz = Class.forName(className); Constructor<?> constructor = clz.getConstructor(parameterClasses); return constructor.newInstance(parameterValues); } @SuppressWarnings({"unchecked", "rawtypes"}) private static Object getEnumValue(String enumClassName, String enumValue) throws ClassNotFoundException { Class<Enum> enumClz = (Class<Enum>) Class.forName(enumClassName); return Enum.valueOf(enumClz, enumValue); } private static void setField(Object object, String fieldName, Object value) throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException { Field field = object.getClass().getDeclaredField(fieldName); field.set(object, value); } private static <T> T getField(Object object, String fieldName, Class<T> type) throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException { Field field = object.getClass().getDeclaredField(fieldName); return type.cast(field.get(object)); } private static void callMethod(Object object, String methodName, String[] parameterTypes, Object[] parameterValues) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { Class<?>[] parameterClasses = new Class<?>[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) parameterClasses[i] = Class.forName(parameterTypes[i]); Method method = object.getClass().getDeclaredMethod(methodName, parameterClasses); method.invoke(object, parameterValues); }
Чтобы использовать его,
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); WifiConfiguration wifiConf = WifiHelper.getCurrentWiFiConfiguration(getApplicationContext()); try { setStaticIpConfiguration(wifiManager, wifiConf, InetAddress.getByName("192.168.0.100"), 24, InetAddress.getByName("10.0.0.2"), new InetAddress[]{InetAddress.getByName("10.0.0.3"), InetAddress.getByName("10.0.0.4")}); } catch (Exception e) { e.printStackTrace(); }
Наконец, вам нужно добавить эти разрешения в манифест,
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" />
Я немного покопался в этой проблеме, и мои выводы-это тот код, который раньше работал для Andrdoi 5.x может работать, если приложение настроено на владельца устройства.
Решение:
Решение состоит в том, чтобы добавить устройство в качестве deviceOwner. Это позволит установить статический IP-адрес с помощью 5.хаки, на которые ссылается моги. Хорошим примером того, как это делается, является пример, найденный здесь:
Https://github.com/googlesamples/android-DeviceOwner/
Использование оболочки adb и запуск команды:
dpm set-device-owner com.example.android.deviceowner/.DeviceOwnerReceiver
Сделает его готовым к тому, чтобы ему позволили делать свою работу.
Я успешно добавил и подключился к сетям open и PSK программно в моем приложении (попробовал на устройствах под управлением 5.1, а также 6.0). Однако, когда я пытаюсь сделать это для корпоративной сети, это не работает. Я вижу, что addNetwork () успешно работает (возвращает положительный идентификатор сети), но когда я смотрю в разделе Настройки->Wi-Fi, я не вижу SSID, как для других SSID, которые я добавил. Кто-нибудь знает, почему это произошло? Если я поищу список WiFiConfiguration программно, он найдет SSID. Вот код, который я использую:
wifiConf = new WifiConfiguration(); wifiConf.SSID = "\"dot1x-test\""; wifiConf.BSSID = "c4:e9:84:43:48:e8"; if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { wifiConf.enterpriseConfig.setIdentity("name"); wifiConf.enterpriseConfig.setPassword("testpassword"); wifiConf.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP); wifiConf.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2); } netId = wifiMgr.addNetwork(wifiConf); wifiMgr.disconnect(); wifiMgr.enableNetwork(netId, true); wifiMgr.saveConfiguration(); wifiMgr.reconnect();