当在 Android Studio 中连接时,如何分别对 WiFi 和蜂窝数据以编程方式执行网络操作?

How do I perform network operation programmatically on WiFi and cellular data separately when both are connected in Android Studio?

这是用于通过地址 192.168.22.1 上的 wifi 连接到屏幕的代码。 关闭移动数据连接时它工作正常,但如果移动数据打开则不起作用:

public void onConnectClicked(View view){
        Y2Screen screen = new Y2Screen("http://192.168.22.1");
        final TextView message=findViewById(R.id.mess);
        try {
            message.setText("Connecting....");
            if (!screen.login("guest", "guest")) {
                message.setText("Connection Failed");
            } else {
                message.setText("Done Loging.");
                //VideoArea va = new VideoArea(0, 0, screen.getWidth(), screen.getHeight());
                PicArea pa=new PicArea(0, 0, screen.getWidth(), screen.getHeight());


                File dir = Environment.getExternalStorageDirectory();
                String path = dir.getAbsolutePath();


                //va.addVideo(path+"/glomo/image.jpeg", 100);
                pa.addPage(path+"/glomo/test3.png","PNG");
                ProgramPlayFile prog = new ProgramPlayFile(1);
                prog.getAreas().add(pa);
                String listId = screen.writePlaylist(new ProgramPlayFile[]{prog});
                screen.play(listId);

            }
        } catch (Y2Exception e) {
            e.printStackTrace();
        }
    }

可能是因为 192.168.22.1 是本地地址,所以只能从本地网络(wifi,...)访问。如果您使用的是移动连接数据,那么您在 public 互联网上,因此您需要将该本地地址 NAT 到 public 地址端口。

您可以使用以下方法检测连接类型:

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();

更多信息请访问 Detect network connection type on Android and about NAT issue: Get the NAT translated IP and port of some local port and How to expose my localhost to the WWW? (port forwarding?)

如果两个连接都处于活动状态,则从 connectivityManager.getAllNetworks() 循环所有网络并选择一个带有 connectivityManager.bindProcessToNetwork(network);

的网络
for (Network network : connectivityManager.getAllNetworks()) {
  NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
  if (networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET || networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
    connectivityManager.bindProcessToNetwork(network);
    break;
  }
}

我找到了一个解决方案并且它有效,我们只需要将网络信道更改为通过 wifi 而不是移动互联网传输。

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            final ConnectivityManager manager = (ConnectivityManager) MainActivity.this
                    .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 {

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    manager.unregisterNetworkCallback(this);
                }
            });
        }