首页 文章

Android运行时执行与NetworkRequest

提问于
浏览
7

我在我的Android应用程序中运行命令行参数,如:

ProcessBuilder pb = new ProcessBuilder(cmds);
Process process = pb.start();
process.waitFor();

cmds 是要运行的参数列表 . 我的命令通过http连接探测远程URL . 我的设备连接到无法访问互联网的WiFi网络,但确实托管了我想要探测的网址 . 我的设备也有一个可以访问互联网的蜂窝连接,但不能访问URL . 我的设备运行的是Android 6.0 Marshmallow .

通常在Lollipop或更高版本中,Android默认使用连接到互联网的网络 . 要访问没有互联网的WiFi网络,您需要使用 NetworkRequest ,例如:https://stackoverflow.com/a/27958106/1847734 .

如何将获得的 Network 传递给上面的 Process ,以便连接通过我的WiFi网络,而不是我的蜂窝网络?

我是否需要使用ConnectivityManager#bindProcessToNetwork?如何使用此方法加入设置网络的过程?似乎没有选择给予这个过程 .

1 回答

  • 6

    从Lollipop Network 开始是 Parcelable 所以您可以将其写入字节数组然后回读 . 让我们从写作部分开始吧 .

    final Parcel parcel = Parcel.obtain();
    try {
      // Create a byte array from Network.
      parcel.writeParcelable(network, 0);
      final byte[] data = parcel.marshall();
    
      // Start a process.
      ProcessBuilder pb = new ProcessBuilder(cmds);
      Process process = pb.start();
    
      // Send serialized Network to the process.
      final DataOutputStream out = new DataOutputStream(process.getOutputStream());
      out.write(data.length);
      out.write(data);
    
      // Wait until the process terminates.
      process.waitFor();
    } finally {
      parcel.recycle();
    }
    

    和阅读部分 .

    // Read data from the input stream.
    final DataInputStream in = new DataInputStream(System.in);
    final int length = in.readInt();
    final byte[] data = new byte[length];
    in.readFully(data);
    
    final Parcel parcel = Parcel.obtain();
    try {
      // Restore Network from a byte array.
      parcel.unmarshall(data, 0, data.length);
      final Network network = parcel.readParcelable(null);
    
      // Use the Network object to bind the process to it.
      connectivityManager.bindProcessToNetwork(network);
    } finally {
      parcel.recycle();
    }
    

    此代码仅适用于Android 6.0 . 如果你想让它在Lollipop上工作,你应该使用ConnectivityManager.setProcessDefaultNetwork(Network)而不是 ConnectivityManager.bindProcessToNetwork(Network) . 此代码在Android 5.0之前无法在设备上运行 .

    UPDATE

    对于非Android进程,您可以创建套接字,使用Network.bindSocket(Socket)将其绑定到nework,并将套接字描述符传递给子进程 .

    如果以前的方法不适合您,您可以从 multinetwork.h 调用NDK函数 android_setsocknetwork ,或者甚至尝试执行Android将进程绑定到给定网络时执行的操作 . 你可能感兴趣的一切都发生在netd client . NetdClientfwmarkd here发送一条消息,传递网络ID . 发送实际消息here . 但我建议使用这种方法作为解决问题的最后机会 .

相关问题