首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Android 10以下,没有互联网,Android将自动断开与WiFi的连接。

在Android 10以下,没有互联网,Android将自动断开与WiFi的连接。
EN

Stack Overflow用户
提问于 2020-06-11 09:00:47
回答 3查看 7.4K关注 0票数 12

工作在安卓应用程序中,我需要通过编程连接没有互联网的WiFi设备。这是一个代码:

代码语言:javascript
复制
    private void connectToWiFi(final String ssid, String password) {

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {

            WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
            final ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkRequest.Builder request = new NetworkRequest.Builder();
            request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
            request.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); // Internet not required

            ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {

                @Override
                public void onAvailable(Network network) {

                    String networkSSID = getNetworkSsid();

                    if (networkSSID.equals(ssid)) {
                        connectivityManager.bindProcessToNetwork(network);
                    }
                }

                @Override
                public void onUnavailable() {
                    super.onUnavailable();
                }

                @Override
                public void onLost(@NonNull Network network) {
                    super.onLost(network);
                }
            };
            connectivityManager.registerNetworkCallback(request.build(), networkCallback);

            WifiConfiguration config = new WifiConfiguration();
            config.SSID = String.format("\"%s\"", ssid);

            int netId = -1;
            List<WifiConfiguration> apList = wifiManager.getConfiguredNetworks();

            for (WifiConfiguration i : apList) {

                if (i.SSID != null && i.SSID.equals("\"" + ssid + "\"")) {
                    netId = i.networkId;
                }
            }

            // Add network in Saves network list if it is not available in list
            if (netId == -1) {

                if (TextUtils.isEmpty(password)) {
                    Log.d(TAG, "====== Connect to open network");
                    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                } else {
                    Log.d(TAG, "====== Connect to secure network");
                    config.preSharedKey = String.format("\"%s\"", password);
                }

                netId = wifiManager.addNetwork(config);
            }

            Log.d(TAG, "Connect to Network : " + netId);
            wifiManager.enableNetwork(netId, true);

        } else {

            // For Android 10 and above
            // WifiNetworkSpecifier code
        }
    }

使用的权限:

代码语言:javascript
复制
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

以上代码适用于提供互联网连接的网络。但是对于没有互联网连接的网络来说,它在大多数情况下都失败了。

当试图连接到没有internet访问权限的WiFi配置时,我们需要将应用程序的进程绑定到该网络,或者配置我们的HTTP客户端以使用该网络的套接字工厂,否则系统将与此WiFi网络断开连接。

根据本准则,bindProcessToNetwork已经被应用了。但是,无论在套接字工厂上使用bindToProcess() /路由通信,系统都是与网络断开连接的。它不允许与没有互联网的WiFi保持联系。令人惊讶的是,在限制网络连接之前,安卓从来没有考虑过IoT设备的用例。

当试图连接到我的应用程序或系统设置应用程序或任何其他应用程序添加的WiFi网络时,系统日志显示:

UID xxxxx does not have permission to update configuration

当应用程序试图连接具有互联网的设备时,即使该网络是由其他应用程序添加的,也不会发生相同的错误。

因此,该应用程序允许连接到以前的配置,尽管“权限不足”,流量是暂时通过这个网络路由。但几秒钟后,网络就断开了,系统试图与其他一些启用互联网的网络重新关联。

在Moto G5 Plus上进行测试,Android8.1.0,但我相信这是一个平台错误,而不是特定于设备。大多数情况下,这个bug是从Android 7或其他地方引入的,因为它以前就在工作。

我也曾报道过这里问题。在这个问题上还提供了示例应用程序。

这个问题有什么解决办法吗?有什么可供选择的付费支持Android吗?

提前谢谢。

EN

回答 3

Stack Overflow用户

发布于 2020-06-19 09:29:10

您提到的问题可能不是因为您在Issuetracker提供的代码。一旦我修复了我的设备(Android 9)中的问题,即使在完全撤消之后,我也无法复制错误。我甚至尝试过设备重新启动,应用程序重新安装,甚至工厂重置。尝尝这个。

  1. 在设置->应用程序和权限时,测试应用程序请求位置权限。给它许可。
  2. Java代码可以是 私有connectivityManager.unregisterNetworkCallback(networkCallback);(最终字符串ssid,字符串密码){ if (connectivityManager != null) { try {connectivityManager connectivityManager.unregisterNetworkCallback(networkCallback);} catch (异常e) {Log.d(标记,"Connectivity Manager已未注册“);} NetworkRequest.Builder请求=新NetworkRequest.Builder();request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);如果(isOnline()==false){isOnline} networkCallback =新的ConnectivityManager.NetworkCallback() {@覆盖公用的onAvailable(网络网络){ String networkSSID = getNetworkSsid();Log.e(标记,“网络可用-”+ networkSSID);if (networkSSID.equals(ssid)) { if(isOnline()==false){ Log.e(标记,"bindProcessToNetwork");}@覆盖公共onLost(@非空网络网络){super.onLost(网络);Log.e(标记“丢失网络连接”);};super.onLost networkCallback);if (!wifiManager.isWifiEnabled(){ wifiManager.setWifiEnabled(true);} WifiConfiguration config =新WifiConfiguration();config.SSID =String.format(“%s\”,ssid);config.status = WifiConfiguration.Status.ENABLED;int netId = -1;List apList = wifiManager.getConfiguredNetworks();Log.d(标记,“列表大小:”+apList.size();for (WifiConfiguration i: apList) ){ if (i.SSID != null &i.SSID.equals(“\”+ ssid +“\”)){ netId = i.networkId;} //在列表if (netId == -1) { if (TextUtils.isEmpty(密码)){Log.e(标记,"====== Connect to open network“)中不可用;} netId = wifiManager.addNetwork(config);}Log.d(标记,“连接到网络:”+ netId);wifiManager.enableNetwork(netId,真);}公共布尔值isOnline() { runtime运行时= Runtime.getRuntime();尝试{ Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");int exitValue = ipProcess.waitFor();返回(exitValue == 0);} catch (IOException e) { e.printStackTrace();} catch (InterruptedException e) { e.printStackTrace();}返回false;}
票数 0
EN

Stack Overflow用户

发布于 2020-06-22 10:24:07

如果您的目标是在特定的网络中使用您的代码,那么您可以转到您的接入点接口,只需将DHCP设置设置为静态,并给设备一个适当的IP。

更多信息可以找到这里

现在,如果您针对的是无法访问其DHCP设置的网络,则可以根据该链接告诉您的设备保持与网络的连接,无论网络是否有互联网连接。

代码语言:javascript
复制
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) {
                if (Build.VERSION.RELEASE.equalsIgnoreCase("6.0")) {
                    if (!Settings.System.canWrite(mActivity)) {
                        Intent goToSettings = new  Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
                        goToSettings.setData(Uri.parse("package:" + 
                        mActivity.getPackageName()));
                        mActivity.startActivity(goToSettings);
                    }
                }
                connectivityManager.bindProcessToNetwork(null);
                if (mSsid.contains("my_iot_device-xxxxxxxxx"))
                    connectivityManager.bindProcessToNetwork(network);
                else {
                    //This method was deprecated in API level 23
                    ConnectivityManager.setProcessDefaultNetwork(null);
                    if (mSsid.contains("my_iot_device-xxxxxxxxx"))
                        ConnectivityManager.setProcessDefaultNetwork(network);
                }
                connectivityManager.unregisterNetworkCallback(this);
            }
        }
    });
}

另外,有时保持无线无线收音机保持清醒是很好的,所以你需要使用WiFiLock来保持它。

代码语言:javascript
复制
//Create a wifi manager instance first
WifiManager mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
//and then create your wifiLock
WifiManager.WifiLock mWifiLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "wifiLock");
if(!mWifiLock.isHeld())
        mWifiLock.acquire();

以后如果你想实现的话

代码语言:javascript
复制
if(mWifiLock.isHeld())
        mWifiLock.release();

这个代码帮助我保持与我的网络的连接,即使它没有互联网接入。

票数 0
EN

Stack Overflow用户

发布于 2022-11-09 23:20:55

取代:

  • connectivityManager.registerNetworkCallback 链接

使用

  • connectivityManager.requestNetwork 链接

requestNetwork上的相关文档来自上面的链接:

只要此请求尚未完成,平台将尝试维护维护与此请求匹配的最佳网络,同时尽可能尝试将请求匹配到更好的网络。

注意,上述文档不包括在registerNetworkCallback**.**中。

Android连接堆栈将拆除未使用的网络。通过requestNetwork对网络的请求数量进行跟踪。因此,就连接堆栈而言,您所请求的Wi网络没有被请求,因此可以被拆除。

这不适用于默认网络,但是只有具有互联网能力的网络才有资格成为默认网络,而在您的情况下不适用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62320720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档