Question

those of you who read my previous questions may already know this: I'm currently trying to get a hold on the whole WiFi Direct stuff. What I've done so far is creating the connection. What I'm trying to do is sending a packet via UDP to the groupOwner (which's IP is of course known) - but it seems to get lost on it's way each time..

Here's a bit of my code, I've got a service for receiving files and an intentservice for submitting them in the background:

FileReceiverService.java

    @Override
    public void run() {
        Log.d(TAG, "Thread starting...");
        try {
            app.log("Opening UDP socket to receive files.");
            DatagramSocket socket = new DatagramSocket(PORT);
            app.log("Socket open!");
            socket.setSoTimeout(5000);
            app.log("Waiting for packet..");
            while (isRunning && !isInterrupted()) {
                DatagramPacket packet = new DatagramPacket(
                        new byte[WiFiPacket.PACKET_SIZE],
                        WiFiPacket.PACKET_SIZE);
                try {
                    socket.receive(packet);
                    app.log("Received " + packet.getLength()
                            + " bytes, trying to parse!");
                    parsePacket(packet);
                } catch (SocketTimeoutException e) {
                } catch (Exception e) {
                    app.log("Something went wrong: " + e.getMessage());
                    e.printStackTrace();
                }
            }
            socket.close();
            app.log("Closing UDP socket");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Where the constant WiFiPacket.PACKET_SIZE is set to 1024*32 (32 KBytes, because I've received "ERRBLABLA MSG too long" errors with higher values).

FileTransferService.java

@Override
protected void onHandleIntent(Intent intent) {
    App app = (App) getApplication();

    Context context = getApplicationContext();
    boolean rightIntent = false;
    WiFiFile file = null;

    if (intent.getAction().equals(ACTION_SEND_TEXT)) {
        rightIntent = true;
        file = WiFiFile.fromText(intent.getExtras().getString(EXTRAS_TEXT));
    } else if (intent.getAction().equals(ACTION_SEND_FILE)) {
        rightIntent = true;
        file = WiFiFile.fromFile(intent.getExtras().getString(
                EXTRAS_FILE_PATH));
    }
    if (rightIntent && file != null) {

        app.getOnWiFiTransmissionChangedListener().onNewOutgoingTransfer(
                file);
        String text = intent.getExtras().getString(EXTRAS_TEXT);
        String host = intent.getExtras().getString(
                EXTRAS_GROUP_OWNER_ADDRESS);
        DatagramSocket socket = null;
        int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
        Log.d(TAG, "Sending packets to " + host + ":" + port);
        try {
            socket = new DatagramSocket();
            int bytesSent = 0;
            for (WiFiPacket p : file) {
                Log.d(TAG, "Preparing another packet..");
                byte[] payload = p.getBytes();
                DatagramPacket packet = new DatagramPacket(payload,
                        payload.length, InetAddress.getByName(host), port);
                Log.d(TAG, "Sending packet..");
                socket.send(packet);
                bytesSent += payload.length;
                Log.d(TAG, "Packet send! Contained " + payload.length
                        + " bytes! All over we've sent about " + bytesSent
                        + " bytes!");
                List<WiFiFile> list = new ArrayList<WiFiFile>();
                list.add(file);
                app.getOnWiFiTransmissionChangedListener()
                        .onTransferProgressChanged(list);
            }

            app.getOnWiFiTransmissionChangedListener()
                    .onFileTransferSuccessful(file);

            Log.d(TAG, "Client: Data written");
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, e.getMessage());
        } finally {
            if (socket != null) {
                if (socket.isConnected()) {
                    socket.close();
                }
            }
        }

    }
}

The code may not be the best, but as for right now the only thing I care about is to receive the damn packet. :)

For your information: I'm splitting instances of the class WiFiFile into WiFiPackets which do not exceed the PACKET_SIZE limit, thus contain some sort of own header information about the file's offset, the total length, the sender (username/inetaddress) and stuff like that. My logging tells me that about 25KBytes were sent, the socket.send does not throw any errors but instead calls my listeners (also the one telling me the transfer is completed). As far as I know, UDP packets can easily be dropped on their way, but I've tried it roughly 10 times and I think the probability of a 25KB packet getting lost EVERYTIME is very small.

Do you see anything I'm missing? I'm staring at my code since hours, trying to figure it out, putting more and more debug/log statements in it, but without any progress.

Thanks!

PS:

IP addresses and port are correct.

PS2:

AndroidManifest.xml

<uses-feature
    android:name="android.hardware.wifi.direct"
    android:required="true" />

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
Était-ce utile?

La solution

Okay, I solved this problem. I sent the messages directly after receiving the callback for a successful group creation, thinking that the group really would be "ready"... Solved this by sending out an initial message in a TimerTask every ~200-500ms, cancelling the Task after receiving ack. Hope this helps some of you, facing the same problem. :)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top