Ответ 1
EDIT: Итак, дальнейшие исследования для заинтересованных, похоже, это функция, добавленная в версиях Samsung Touchwiz на основе 4.3. Внутри параметр имеет значение "wifi_watchdog_connectivity_check". Я все еще использую приведенный ниже код, чтобы узнать, могу ли я проверить, включен ли этот параметр, но в противном случае я должен был бы принять его.
Итак, что я обнаружил, так это то, что после попытки соединения, и ОС отключается от сети, конфигурация Wi-Fi находится в состоянии "отключено". Поэтому после возникновения проблемы вы можете точно убедиться, что это произошло, проверив состояние конфигурации с WifiManager
.
WifiManager m = (WifiManger) getSystemService(Context.WIFI_SERVICE);
List<WifiConfiguration> networks = m.getConfiguredNetworks();
String mySsid = "My Network";
mySsid = "\"" + mySsid + "\"";
boolean isDisabled = false;
for (WifiConfiguration config : networks) {
if (mySsid.equals(config.SSID)) {
if (config.status = WifiConfiguration.Status.DISABLED) {
isDisabled = true;
break;
}
}
}
//If isDisabled is true, the network was disabled by the OS
Затем вы можете попытаться разрешить имя параметра из приложения системных настроек:
/** Gets the resources of another installed application */
private static Resources getExternalResources(Context ctx, String namespace) {
PackageManager pm = ctx.getPackageManager();
try {
return (pm == null) ? null : pm.getResourcesForApplication(namespace);
} catch (PackageManager.NameNotFoundException ex) {
return null;
}
}
/** Gets a resource ID from another installed application */
private static int getExternalIdentifier(Context ctx, String namespace,
String key, String type) {
Resources res = getExternalResources(ctx, namespace);
return (res == null) ? 0 : res.getIdentifier(key, type, namespace);
}
/** Gets a String resource from another installed application */
public static String getExternalString(Context ctx, String namespace,
String key, String defVal) {
int resId = getExternalIdentifier(ctx, namespace, key, "string");
if (resId != 0) {
Resources res = getExternalResources(ctx, namespace);
return res.getString(resId);
} else {
return defVal;
}
}
Затем используйте его, чтобы получить строку:
String autoNetworkSwitch = getExternalString(this, "com.android.settings",
"wifi_watchdog_connectivity_check", "Unknown");
Это вернет локализованную строку для текущего языка пользователя, если строка существует.
Для всех, кто интересуется результатами этого, выясняется, что этот вариант на самом деле является базовым набором Android, но, похоже, он более агрессивен на этих устройствах Samsung. Параметр - скрытая настройка, найденная в android.provider.Settings.java
:
/**
* Setting to turn off poor network avoidance on Wi-Fi. Feature is enabled by default and
* the setting needs to be set to 0 to disable it.
* @hide
*/
public static final String WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED =
"wifi_watchdog_poor_network_test_enabled";
Что находится в Settings$Secure
для API == 15 || API == 16
, или Settings$Global
для API >= 17
. Это не параметр, который может быть включен или отключен сторонними приложениями; однако его можно обнаружить и предупредить. Мое решение таково:
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1;
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
/**
* Checks whether the "Avoid poor networks" setting (named "Auto network switch" on
* some Samsung devices) is enabled, which can in some instances interfere with Wi-Fi.
*
* @return true if the "Avoid poor networks" or "Auto network switch" setting is enabled
*/
public static boolean isPoorNetworkAvoidanceEnabled (Context ctx) {
final int SETTING_UNKNOWN = -1;
final int SETTING_ENABLED = 1;
final String AVOID_POOR = "wifi_watchdog_poor_network_test_enabled";
final String WATCHDOG_CLASS = "android.net.wifi.WifiWatchdogStateMachine";
final String DEFAULT_ENABLED = "DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED";
final ContentResolver cr = ctx.getContentResolver();
int result;
if (SDK_INT >= JELLY_BEAN_MR1) {
//Setting was moved from Secure to Global as of JB MR1
result = Settings.Global.getInt(cr, AVOID_POOR, SETTING_UNKNOWN);
} else if (SDK_INT >= ICE_CREAM_SANDWICH_MR1) {
result = Settings.Secure.getInt(cr, AVOID_POOR, SETTING_UNKNOWN);
} else {
//Poor network avoidance not introduced until ICS MR1
//See android.provider.Settings.java
return false;
}
//Exit here if the setting value is known
if (result != SETTING_UNKNOWN) {
return (result == SETTING_ENABLED);
}
//Setting does not exist in database, so it has never been changed.
//It will be initialized to the default value.
if (SDK_INT >= JELLY_BEAN_MR1) {
//As of JB MR1, a constant was added to WifiWatchdogStateMachine to determine
//the default behavior of the Avoid Poor Networks setting.
try {
//In the case of any failures here, take the safe route and assume the
//setting is disabled to avoid disrupting the user with false information
Class wifiWatchdog = Class.forName(WATCHDOG_CLASS);
Field defValue = wifiWatchdog.getField(DEFAULT_ENABLED);
if (!defValue.isAccessible()) defValue.setAccessible(true);
return defValue.getBoolean(null);
} catch (IllegalAccessException ex) {
return false;
} catch (NoSuchFieldException ex) {
return false;
} catch (ClassNotFoundException ex) {
return false;
} catch (IllegalArgumentException ex) {
return false;
}
} else {
//Prior to JB MR1, the default for the Avoid Poor Networks setting was
//to enable it unless explicitly disabled
return true;
}
}
В целях хорошей оценки вы можете направлять своих пользователей в Advanced Wi-Fi Settings с помощью Intent
:
/**
* Ensure that an Activity is available to receive the given Intent
*/
public static boolean activityExists (Context ctx, Intent intent) {
final PackageManager mgr = ctx.getPackageManager();
final ResolveInfo info = mgr.resolveActivity(i, PackageManager.MATCH_DEFAULT_ONLY);
return (info != null);
}
public static void showAdvancedWifiIfAvailable (Context ctx) {
final Intent i = new Intent(Settings.ACTION_WIFI_IP_SETTINGS);
if (activityExists(ctx, i)) {
ctx.startActivity(i);
}
}
Интересные мелочи: этот Intent
вызывает тот же Activity
, что и в настройках > Wi-Fi > Дополнительно, но покажет его с другим заголовком (настройки IP, vs Advanced Wi-Fi).