我可以将套接字绑定到android 5.x中的特定网络。 如何绑定DatagramSocket?可能吗? 寻找来源,如果它可以用没有运气的反射来完成。 https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket)Android棒棒糖将套接字绑定到特定网络。 DatagramSocket怎么样?
UPDATE ParcelFileDescriptor.fromDatagramSocket(socket).getFd()可以替换辅助函数getFileDescriptor。也有结合直接向中FileDescriptor的API 23 https://developer.android.com/reference/android/net/Network.html#bindSocket%28java.io.FileDescriptor%29
更新新功能:刚才看到在API层面一些灰色额外的新功能22 https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.DatagramSocket)
UPDATE:也可以用反射完成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;
}
您是否尝试用'ParcelFileDescriptor.fromDatagramSocket(socket).getFd()'替换getFileDescriptor()? – surlac 2016-02-18 02:22:55
你说得对。它可以被替换。谢谢。还发现这个存在于23 https://developer.android.com/reference/android/net/Network.html#bindSocket%28java.io.FileDescriptor%29 – 2016-02-19 06:09:32
正确。但是您的createDatagramChannel()仍然需要绑定DatagramSocket到API 21上的网络,因为'bindSocket(DatagramSocket套接字)'在API 22上可用。 – surlac 2016-02-19 18:39:20