我可以将socket绑定到android 5.x中的特定网络。 如何绑定DatagramSocket?可能吗? 如果可以通过反射而没有运气来查看来源。 https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket)
UPDATE ParcelFileDescriptor.fromDatagramSocket(socket).getFd()可以替换辅助函数getFileDescriptor。还有一个新功能,它直接绑定到API 23 https://developer.android.com/reference/android/net/Network.html#bindSocket%28java.io.FileDescriptor%29
中的FileDescriptor更新:刚刚在API级别22中看到了一些灰色的额外新功能。 https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.DatagramSocket)
更新:也可以使用API级别21中的反射来完成
private static int getFileDescriptor(DatagramSocket socket) throws SocketException {
try {
Field implField = DatagramSocket.class.getDeclaredField("impl");
implField.setAccessible(true);
DatagramSocketImpl implValue = (DatagramSocketImpl)implField.get(socket);
Field fdField = DatagramSocketImpl.class.getDeclaredField("fd");
fdField.setAccessible(true);
FileDescriptor fdValue = (FileDescriptor)fdField.get(implValue);
Field descField = FileDescriptor.class.getDeclaredField("descriptor");
descField.setAccessible(true);
return (Integer)descField.get(fdValue);
} catch (NoSuchFieldException e) {
e.printStackTrace();
throw new AssertionError(e);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new AssertionError(e);
}
}
private DatagramChannel createDatagramChannel(Network activeWifiNetwork) throws IOException{
DatagramChannel channel = DatagramChannel.open();
try{
if (activeWifiNetwork == null) {
Log.d(TAG, "No active network to bind to ");
return channel;
}
Class<?> networkUtils = Class.forName("android.net.NetworkUtils");
for (Method m : networkUtils.getDeclaredMethods()) {
if (m.getName().equalsIgnoreCase("bindSocketToNetwork")){
DatagramSocket socket = channel.socket();
socket.getReuseAddress();
int socketFileDescriptor = getFileDescriptor(socket);
int result = (Integer) m.invoke(null, socketFileDescriptor , Integer.valueOf(activeWifiNetwork.toString()));
Log.d(TAG, "Result bind datagram to network is " + result);
if (result != 0){
throw new Exception("Error binding socket to network");
}
break;
}
}
} catch(Exception ex){
ex.printStackTrace();
}
return channel;
}