Вещание по Wi-Fi Direct
Я рассматриваю возможность транслировать по Wi-Fi прямому соединению между несколькими устройствами Android. Я создал приложение для широковещательной передачи сообщений, чтобы проверить, работает ли оно, но пока я не смог транслировать сообщение. Когда я пытаюсь отправить пакет, я получаю SocketException (сеть недоступна):
03-20 13:23:00.148: E/UdpBroadcaster(4180): sendto failed: ENETUNREACH (Network is unreachable)
03-20 13:23:00.148: E/UdpBroadcaster(4180): java.net.SocketException: sendto failed: ENETUNREACH (Network is unreachable)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:496)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at libcore.io.IoBridge.sendto(IoBridge.java:465)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:182)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at java.net.DatagramSocket.send(DatagramSocket.java:307)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at com.example.android.wifidirect.UdpBroadcaster.sendMessage(UdpBroadcaster.java:59)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at com.example.android.wifidirect.UdpBroadcaster.run(UdpBroadcaster.java:44)
03-20 13:23:00.148: E/UdpBroadcaster(4180): Caused by: libcore.io.ErrnoException: sendto failed: ENETUNREACH (Network is unreachable)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at libcore.io.Posix.sendtoBytes(Native Method)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at libcore.io.Posix.sendto(Posix.java:146)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:177)
03-20 13:23:00.148: E/UdpBroadcaster(4180): at libcore.io.IoBridge.sendto(IoBridge.java:463)
03-20 13:23:00.148: E/UdpBroadcaster(4180): ... 4 more
В этом суть моего кода:
InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255");
int port = 8888;
DatagramSocket socket = new DatagramSocket(port);
socket.setBroadcast(true);
socket.connect(broadcastAddress, port);
String message = "Hello";
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(
buffer, buffer.length, broadcastAddress, port);
try {
socket.send(packet); // <----- Causes a SocketException
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
}
Этот пост предполагает, что трансляция через Wi-Fi Direct должна быть возможна.
Кто-нибудь знает, действительно ли работает трансляция через Wi-Fi Direct на устройствах Android? Если это сработает, что я делаю неправильно?
Я начинаю думать, что устройства не знают, куда направлять широковещательные пакеты. В моем случае он должен работать без необходимости корневого устройства и вручную добавлять маршрут для широковещательных пакетов.
Обновление
После использования функции getBroadcastAddress()
, предложенной Роменом Хиппо, SocketException исчез, и похоже, что трансляция работает по назначению. Однако у меня возникают проблемы с получением трансляции на втором устройстве.
Я использую следующий код для получения трансляции:
DatagramSocket socket = null;
try {
socket = new DatagramSocket(8888);
socket.setBroadcast(true); // Not needed?
socket.setSoTimeout(200);
DatagramPacket packet = null;
while (!mStopping) {
byte[] buffer = new byte[1024];
packet = new DatagramPacket(buffer, buffer.length);
try {
socket.receive(packet);
if (packet.getData().length > 0) {
String receivedString = new String(packet.getData());
Log.i(TAG, "Received string: " + receivedString);
}
} catch (InterruptedIOException e) { /* Ignore */ }
}
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
} finally {
if (socket != null)
socket.close();
}
Я также попытался добавить подстановочный знак в DatagramSocket
, добавив InetAddress.getByName("0.0.0.0")
в качестве аргумента, но не повезло.
Предложения?
Ответы
Ответ 1
Бесстыдно украден из https://code.google.com/p/boxeeremote/wiki/AndroidUDP
Попробуйте подключиться к сети следующим образом:
InetAddress getBroadcastAddress() throws IOException {
WifiManager wifi = mContext.getSystemService(Context.WIFI_SERVICE);
DhcpInfo dhcp = wifi.getDhcpInfo();
// handle null somehow
int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
byte[] quads = new byte[4];
for (int k = 0; k < 4; k++)
quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
return InetAddress.getByAddress(quads);
}
Затем попробуйте отправить пакет таким образом:
DatagramSocket socket = new DatagramSocket(PORT);
socket.setBroadcast(true);
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(),
getBroadcastAddress(), PORT);
socket.send(packet);
// If you want to listen for a response ...
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
Изменить: с той же страницы, чтобы читать, попробуйте это...
WifiManager wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
MulticastLock lock = wifi.createMulticastLock("dk.aboaya.pingpong");
lock.acquire();
serverSocket = new DatagramSocket(19876);
serverSocket.setSoTimeout(15000); //15 sec wait for the client to connect
byte[] data = new byte[UDPBatPositionUpdater.secretWord.length()];
DatagramPacket packet = new DatagramPacket(data, data.length);
serverSocket.receive(packet);
lock.release();
String s = new String(packet.getData());
System.out.println(s);
Помните, что для этого вам необходимо следующее разрешение:
< uses-permission android: name= "android.permission.CHANGE_WIFI_MULTICAST_STATE" / >