我可以將套接字綁定到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