web-dev-qa-db-ja.com

インターネットなしでWifiネットワークを使用するには、Androidを強制します

AndroidインターネットにアクセスできないWiFiネットワークで通信する必要があるアプリを作成しています。問題は、WiFiが接続されていてもAndroid = Wi-Fiネットワークにインターネットが接続されていない場合、携帯電話/モバイルデータの使用を選択します。

私はこの問題に関する多くの投稿を読みましたが、その多くはデバイスのルート化に関係していますが、実稼働アプリでは不可能です(デバイスのルート化はnotオプションです)。他のソリューション(私のコードのように)は、Sony Z2で完全に動作しますが、テストした他のデバイスでは動作しないbindProcessToNetwork()の使用を推奨します(すべて6.0.1を実行)

private void bindToNetwork() {
    final ConnectivityManager connectivityManager = (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest.Builder builder;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        builder = new NetworkRequest.Builder();
        //set the transport type do WIFI
        builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


                    connectivityManager.bindProcessToNetwork(null);
                    if (barCodeData.getSsid().contains("screenspace")) {
                        connectivityManager.bindProcessToNetwork(network);
                    }

                } else {
                    //This method was deprecated in API level 23
                    ConnectivityManager.setProcessDefaultNetwork(null);
                    if (barCodeData.getSsid().contains("screenspace")) {

                        ConnectivityManager.setProcessDefaultNetwork(network);
                    }
                }

                connectivityManager.unregisterNetworkCallback(this);
            }
        });
    }
}
29
Lonergan6275

グローバル設定captive_portal_detection_enabledを0(false)に設定してみてください。

実際に起こっていることは、デフォルトでは、wifiに接続するたびに、FWはサーバー(通常はgoogle)に対してテストを実行し、キャプティブwifi(ログインが必要)かどうかを確認します。したがって、wifiがGoogleに接続されていない場合、このチェックは失敗します。その後、デバイスはwifiにインターネット接続がないことを認識し、wifiに自動的に接続しません。

この設定を0に設定すると、このチェックが回避されます。

プログラム的に:Settings.Global.putInt(getContentResolver(), Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED, 0);

編集:Androidバージョンによっては表示されない定数の代わりに、文字列 "captive_portal_detection_enabled"を直接使用する必要がある場合があります。

2
lax1089

あなたは正しい道を進んでいます、解決策は確かに ConnectivityManager.bindProcessToNetwork(network) です。この情報は、この記事のAndroid Developers Blog: アプリをWi-Fiデバイスに接続する

コードを見ると、このbarCodeData.getSsid()は、現在接続されているwifiネットワークのSSIDを取得しているようには見えません。その場合、コードはネットワークに正常にバインドされません。

ifステートメントを置き換えてみてください

if (barCodeData.getSsid().contains("screenspace"))

if (getNetworkSsid(context).equals("screenspace"))

kotlinのヘルパーメソッドは、接続されたwifiネットワークのSSIDを取得します

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

それでも動作しない場合は、 my complete solution に従ってください。同じ方法を使用しましたが、いくつかの追加チェックがあります。 Androidバージョン5.1.1、6.0、6.0.1、7.1.1および8.1.0でテストしました。

1
Ryan Amaral

[設定]でモバイルデータを無効にする必要があります(これをプログラムで実行できるかどうかは不明ですが、可能性のあるオプションです)-USIMを削除します。

それ以外の一般的な動作は、常に利用可能な最適な接続にフォールバックすることです(ほとんどのアプリケーションで使用されるため、インターネットゲートウェイとの接続が優先される場合があります)。

こちらもご覧ください answer

1
Martin Zeitler

Wi-Fiが接続されているかどうかを確認してから、Wi-Fiネットワークへの接続をユーザーに求めるダイアログを表示します。

メソッドNetworkInfo.isConnected()はAPI-23で非推奨になったため、Wi-Fiアダプターがオンであり、代わりにWifiManagerを使用してアクセスポイントに接続されているかどうかを検出するメソッドを次に示します。

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
Akshay Sood

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
Vados