带有 NetworkRequest 的 Android 运行时 exec
Posted
技术标签:
【中文标题】带有 NetworkRequest 的 Android 运行时 exec【英文标题】:Android runtime exec with NetworkRequest 【发布时间】:2016-03-06 19:06:35 【问题描述】:我正在我的 android 应用程序中运行一个命令行参数,例如:
ProcessBuilder pb = new ProcessBuilder(cmds);
Process process = pb.start();
process.waitFor();
cmds
是要运行的参数列表。我的命令通过 http 连接探测远程 URL。我的设备连接到无法访问互联网的 WiFi 网络,但托管了我要探测的 URL。我的设备还具有可以访问互联网但不能访问 URL 的蜂窝连接。我的设备运行的是 Android 6.0 Marshmallow。
通常在 Lollipop 或更高版本中,Android 默认使用连接到 Internet 的网络。要在没有互联网的情况下访问 WiFi 网络,您需要使用 NetworkRequest
,例如:https://***.com/a/27958106/1847734。
如何将获得的Network
传递给上面的Process
,以便连接通过我的 WiFi 网络,而不是我的蜂窝网络?
我是否需要改用ConnectivityManager#bindProcessToNetwork?如何加入使用此方法设置网络的过程?似乎没有提供该过程的选项。
【问题讨论】:
棘手的问题。如果您在构建和启动进程之前将网络绑定到您的应用程序进程,您会幸运地继承了网络吗? 不幸的是,不,它似乎没有。 @JonG 你是怎么解决这个问题的?您是否按照建议使用了本机实现?我遇到了完全相同的问题,我能够为 API >= 21 绑定“正常”网络请求,但找不到绑定进程的方法(我还需要使用“ping”进行测试) @soey 你们找到解决方案了吗?我尝试在 Java 中设置默认网络,但没有成功。接下来,我用正确的网络在 Java 中创建了 Socket,并将描述符传递给 Native 子进程,但效果不佳。 @Himanshu 抱歉,我没有找到解决方案。我认为这是一个非常具体的问题。我最终忽略了它,例如在这种情况下不执行该过程,这对我的用例来说已经足够了。我想我在某处看到了一个解决方案,他们使用了本机套接字实现(在 C 中),但我在 atm 中找不到它。另外我对使用本机代码不是很有经验。 【参考方案1】:从 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 之前的设备。
更新:
对于非 Android 进程,您可以创建一个套接字,使用 Network.bindSocket(Socket)
将其绑定到网络,并将套接字描述符传递给子进程。
如果前面的方法不适合您,您可以从 multinetwork.h
调用 NDK 函数 android_setsocknetwork
,甚至尝试执行 Android 在将进程绑定到给定网络时所做的事情。您可能感兴趣的一切都发生在netd client。 NetdClient
向fwmarkd
here 发送一条消息,传递一个网络ID。实际消息发送发生在here。但我建议使用这种方法作为解决问题的最后机会。
【讨论】:
我不知道你可以打包一个网络,这很有趣,但是我的进程在命令行上运行一个编译好的二进制文件,所以我不认为我可以在那里通过网络。以上是关于带有 NetworkRequest 的 Android 运行时 exec的主要内容,如果未能解决你的问题,请参考以下文章
带有 showSoftInput 的 Android 显示软键盘不起作用?
我的 Android 小部件被杀死,“不再需要 bellander.andro ....”
如何解决这个错误。 com.google.android.gms.tasks.task executors$zza 无法转换为 android.app.activity。我是 Java 和 Andro
java.lang.RuntimeException: Unable to start activity ComponentInfo{XXX}: Error inflating class andro