移动数据开启时通过wifi(无互联网)发送数据

问题描述 投票:0回答:2

我正在开发通过 wifi (由设备生成)连接到硬件设备并通过套接字连接向其发送数据的应用程序。 问题是,当激活移动数据(3G/4G)时,android会尝试通过它发送数据,而不是通过设备生成的wifi发送数据,因为wifi没有互联网连接。 我正在考虑使用 ConnectivityManager#setNetworkPreference() 但它已在 api 21 中被弃用。

如何设置使用设备生成的wifi而不是移动数据接口发送数据?

android sockets wifi network-interface
2个回答
16
投票

经过大量研究和时间尝试理解这一切后,我发现这在 Android 5.0 (Lollipop) 之前的版本中是不可能的,操作系统一次仅保持一个网络接口,并且应用程序没有控制这个。

因此,为了在大于或等于 Lollipop 的版本上执行此操作,我执行了以下操作:

  1. 在进行套接字连接之前,检查 android 是否大于或等于 Lollipop,如果不是,您只需执行正常操作即可;
  2. 如果版本等于或大于 Lollipop,您需要执行以下操作:

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        final ConnectivityManager manager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkRequest.Builder builder;
        builder = new NetworkRequest.Builder();
        //set the transport type do WIFI
        builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        manager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    manager.bindProcessToNetwork(network);
                } else {
                    //This method was deprecated in API level 23
                    ConnectivityManager.setProcessDefaultNetwork(network);
                }
                try {
                    //do a callback or something else to alert your code that it's ok to send the message through socket now
                } catch (Exception e) {
                    e.printStackTrace();
                }
                manager.unregisterNetworkCallback(this);
            }
        });
    }
    
  3. 完成后,您应该停止与此绑定流程:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        ConnectivityManager manager = (ConnectivityManager) InovePlugApplication.getContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        manager.bindProcessToNetwork(null);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        ConnectivityManager.setProcessDefaultNetwork(null);
    }
    

这个答案帮助我了解了如何做到这一点https://stackoverflow.com/a/29837637/2550932.


0
投票

setProcessDefaultNetwork 切换回 wifi 后,网络将切换回移动设备,无法通过这种方式发送大数据,因为通过这种方式创建的所有套接字都将停止工作。我现在还没有找到完美的方法,这里仅供参考。

1.如果您可以获得root访问权限,请在连接wifi之前执行此操作:

Process process = runtime.exec("su");
DataOutputStream dataOutputStream = new DataOutputStream(process.getOutputStream());
dataOutputStream.writeBytes("settings put global captive_portal_server 127.0.0.1\n");
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
int status = process.waitFor();

发送数据后删除它:

dataOutputStream.writeBytes("settings delete global captive_portal_server\n");

2.如果您可以获得WRITE_SECURE_SETTINGS权限:

Settings.Global.putString(getContentResolver(),"captive_portal_server","127.0.0.1");

或者:

Settings.Global.putInt(getContentResolver(),"captive_portal_detection_enabled",0);
© www.soinside.com 2019 - 2024. All rights reserved.