Force Android to Use Wifi network with no internet

前端 未结 5 901
猫巷女王i
猫巷女王i 2020-12-24 06:23

I am building an android app that needs to communicate over a WiFi network that will not have any internet access. The problem is that even when the WiFi is connected androi

相关标签:
5条回答
  • 2020-12-24 06:36

    Could you try and set the global setting captive_portal_detection_enabled to 0 (false).

    What's actually happening is that by default, everytime you connect to a wifi, the FW will test against a server (typically google) to see if it's a captive wifi (needs login). So if your wifi is not connected to google, this check will fail. After that, the device knows that wifi has no internet connection and simply will not autoconnect to it.

    Setting this setting to 0, will avoid this check.

    Programatically: Settings.Global.putInt(getContentResolver(), Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED, 0);

    Edit: You may need to use the string "captive_portal_detection_enabled" directly, instead of the constant that's not visible depending on Android version.

    0 讨论(0)
  • 2020-12-24 06:45

    You're in the right path, the solution is indeed with ConnectivityManager.bindProcessToNetwork(network). This information was posted on the Android Developers Blog in this article: Connecting your App to a Wi-Fi Device.

    Looking into your code this barCodeData.getSsid() doesn't look that is getting the SSID of the currently connected wifi network. If that's the case your code will never successfully bind to the network.

    Try replace your if statement

    if (barCodeData.getSsid().contains("ap-name"))
    

    With

    if (getNetworkSsid(context).equals("ap-name"))
    

    Helper method in kotlin to retrieve the SSID of the connected wifi network

    private fun getNetworkSsid(context: Context?): String {
        // WiFiManager must use application context (not activity context) otherwise a memory leak can occur
        val mWifiManager = context?.applicationContext?.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val wifiInfo: WifiInfo? = mWifiManager.connectionInfo
        if (wifiInfo?.supplicantState == SupplicantState.COMPLETED) {
            return wifiInfo.ssid.removeSurrounding("\"")
        }
        return ""
    }
    

    If still doesn't work please follow my complete solution where I used the same method but with some extra checks. I tested it in the Android versions 5.1.1, 6.0, 6.0.1, 7.1.1 and 8.1.0.

    0 讨论(0)
  • 2020-12-24 06:47

    You can check if wifi is connected then proceed else show a dialog to user asking him to connect to a wifi network

    Since the method NetworkInfo.isConnected() is now deprecated in API-23, here is a method which detects if the Wi-Fi adapter is on and also connected to an access point using WifiManager instead:

    private boolean checkWifiOnAndConnected() {
        WifiManager wifiMgr = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    
        if (wifiMgr.isWifiEnabled()) { // Wi-Fi adapter is ON
    
            WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
    
            if( wifiInfo.getNetworkId() == -1 ){
                return false; // Not connected to an access point
            }
            return true; // Connected to an access point
        }
        else {
            return false; // Wi-Fi adapter is OFF
        }
    }
    
    0 讨论(0)
  • 2020-12-24 06:49

    you'd need to disable mobile data in the Settings (not certain, if this can be done programmatically, which might be a possible option) - or take out the USIM;

    else the common behavior is, that it will always fall back to the best available connection (while a connection with internet gateway might be preferred, because it is used by most application).

    also see this answer.

    0 讨论(0)
  • 2020-12-24 06:51

    Solution on Kotlin

    class ConnectWithoutInternetTest constructor(
    private val mContext: Context,
    private val connectivityManager: ConnectivityManager,
    private val wifiManager: WifiManager
    ) {
    
    private val mWifiBroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when (intent.action) {
                WifiManager.NETWORK_STATE_CHANGED_ACTION -> {
                    val info = intent.getParcelableExtra<NetworkInfo>(WifiManager.EXTRA_NETWORK_INFO)
                    val isConnected = info.isConnected
    
                    val ssid: String? = normalizeAndroidWifiSsid(wifiManager.connectionInfo?.ssid)
    
                    if (isConnected) {
                        val builder = NetworkRequest.Builder()
                        builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                        connectivityManager.registerNetworkCallback(
                            builder.build(),
                            object : ConnectivityManager.NetworkCallback() {
                                override fun onAvailable(network: Network) {
                                    super.onAvailable(network)
                                    val networkInfo = connectivityManager.getNetworkInfo(network)
                                    val networkSsid = networkInfo.extraInfo
                                    if (networkSsid == ssid) {
                                        connectivityManager.unregisterNetworkCallback(this)
                                    }
                                }
                            })
                    }
                }
            }
        }
    }
    
    private fun init() {
        val intentFilter = IntentFilter()
        intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)
        mContext.registerReceiver(mWifiBroadcastReceiver, intentFilter)
    }
    
    private fun destroy() {
        mContext.unregisterReceiver(mWifiBroadcastReceiver)
    }
    
    private fun normalizeAndroidWifiSsid(ssid: String?): String? {
        return ssid?.replace("\"", "") ?: ssid
    }
    
    fun connectToWifi(ssidParam: String, password: String?) {
        init()
        val ssid = "\"$ssidParam\""
        val config = wifiManager.configuredNetworks.find { it.SSID == ssid }
        val netId = if (config != null) {
            config.networkId
        } else {
            val wifiConfig = WifiConfiguration()
            wifiConfig.SSID = ssid
            password?.let { wifiConfig.preSharedKey = "\"$password\"" }
            wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
            wifiManager.addNetwork(wifiConfig)
        }
    
        wifiManager.disconnect()
        val successful = wifiManager.enableNetwork(netId, true)
    }
    
    0 讨论(0)
提交回复
热议问题