2013-12-12 10 views
12

私たちのアプリでは、直接の通信に独自のワイヤレスアクセスポイント(インターネットに接続されていない)をブロードキャストするデバイスへのWiFi接続の開始を処理します。WiFi接続でサムスンの「自動ネットワークスイッチ」を無効にする

すべてのテストデバイスでうまく動作します。しかし、特定のSamsungデバイス(Galaxy S4、Galaxy Note 3)では、Samsungが "不安定な"ネットワークを探すために追加した "Auto Network Switch"と呼ばれるWi-Fi設定の設定があります。自動的に切断され、モバイルデータに戻ります。残念ながら、私たちのデバイスはインターネット接続がないので、サムスンは不安定なネットワークとして報告し、すぐに切断します。

これらのデバイスのいずれかをテストに使用することはできません。他の誰かがこの問題を認識しているか、プログラムでこの設定を無効にする方法や回避する方法がわかっていますか?

我々は、接続に使用するコードは次のとおりです。

/** 
* Attempt to connect to an open wifi network with the given SSID 
* @param ssid the SSID of the unsecured wireless network to connect to 
*/ 
public static void connectToOpenNetwork (String ssid) { 
    WifiManager mgr = getManager(); 
    WifiConfiguration configuration = getOpenWifiConfiguration(ssid); 
    mgr.addNetwork(configuration); 
    mgr.saveConfiguration(); 

    int res = findOpenNetworkId(ssid); 
    if (res != INVALID_NETWORK_ID) { 
     mgr.enableNetwork(res, true); 
     mgr.reconnect(); 
    } else { 
     Log.e(TAG, "Received request to connect to network " + ssid + " but the network was not found in the configurations."); 
    } 
} 

/** 
* Get a WifiConfiguration object configured for an unsecured wireless network with the 
* given SSID. 
* @param ssid the SSID of the network to configure 
* @return a WifiConfiguration object that can be passed to 
* {@link WifiManager#addNetwork(android.net.wifi.WifiConfiguration)} 
*/ 
private static WifiConfiguration getOpenWifiConfiguration (String ssid) { 
    WifiConfiguration config = new WifiConfiguration(); 

    config.SSID = "\"" + ssid + "\""; 
    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 

    return config; 
} 
+1

まだ試していないのであれば、サムスン自身のフォーラムでもっとうまくいくかもしれません。http://developer.samsung.com/forum/en – CommonsWare

+0

リンクありがとうございます。 :) – kcoppock

答えて

20

EDIT:だから、興味のある人のためのさらなる研究、4.3に基づいてサムスンTouchWizがバージョンで追加された機能のようです。内部的には、この設定の名前は "wifi_watchdog_connectivity_check"です。私はまだを確認することができるかどうかを確認するために以下のコードを使用します。設定が有効かどうかにかかわらず、そうでなければ私はそれがオンであると仮定しなければなりません。

私が発見したことは、接続を試みて、OSがネットワークから切り離された後、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の設定であることが判明したが、それはこれらのサムスンのデバイス上でより積極的であるように思われます。

/** 
* 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"; 

API >= 17ためAPI == 15 || API == 16、またはSettings$GlobalためSettings$Secureである:設定はandroid.provider.Settings.javaで見つけ隠された設定です。これはサードパーティのアプリケーションによって有効または無効にできる設定ではありません。ただし、に検出され、警告されます。私の解決策これです:良い測定のために

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; 
    } 
} 

、あなたがしてIntentによって高度のWi-Fi設定にユーザーに指示することができます

/** 
* 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設定、高度なWi-Fi)で表示されます。

+0

設定> Wi-Fi>詳細を開くことなく、ネイティブアプリケーションからWi-Fi通知を強制的にオフにする必要がありますか? – Puneet

+0

@プネーネは、答えに記載されているように、これはできません。 – kcoppock

+0

補足として、 'wifi_watchdog_on'も関連しているかもしれません。 –

関連する問題