Search code examples
androidsocketswifi-directwifimanagerwifip2p

Android Wi-Fi Direct P2P send data from server to client


I have an Android app where I'd like to send data between 2 or more devices using Android's WiFi Direct P2P feature. My app is created based off Google's WiFi Direct Demo. The problem is, I wan to send data from the my server (group owner) to the client. The demo does not show how to do this. What I have tried is the following, but keep getting a "java.net.UnknownHostException: Host is unresolved" error.

What I currently do is:

In the WifiP2pManager.ConnectionInfoListener interface, I implement the onConnectionInfoAvailalbe like below:

public void onConnectionInfoAvailable(WifiP2pInfo info) {

    if(mInitiatedConnection || mInitiatedDiscover) {
        if (mPeerSelectionDialog != null && mPeerSelectionDialog.isShowing()) {
            mPeerSelectionDialog.dismiss();
            mPeerSelectionDialog = null;
        }

        if (info.groupFormed && info.isGroupOwner) {
            Uri[] uris = getSelectedFiles();
            //send data to clients
            new ServerAsyncTask(getActivity(),info,uris).execute();
        } else if (info.groupFormed) {
          //Ping Server with IP address
            new PingServerAsyncTask(getActivity(),info).execute();

            //Wait for Server to Send data
            new FileServerAsyncTask(getActivity(),mManager,mChannel).execute();
        }

Below are my implementations for the three threads: FileServerAsyncTask (irrelevant code removed)

public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
    /**
     * @param context
     */
    public FileServerAsyncTask(Context context, WifiP2pManager m, WifiP2pManager.Channel c) {
//intialize
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            ServerSocket serverSocket = new ServerSocket(8988);
            Log.d(MultiImageSelectorFragment.TAG, "Server: Socket opened");
            Socket client = serverSocket.accept();
            Log.d(MultiImageSelectorFragment.TAG, "Server: connection done");
            final File f = new File(Environment.getExternalStorageDirectory() + "/"
                    + context.getPackageName() + "/wifip2pshared/" + System.currentTimeMillis()
                    + ".jpg");

            File dirs = new File(f.getParent());
            if (!dirs.exists())
                dirs.mkdirs();
            f.createNewFile();

            Log.d(MultiImageSelectorFragment.TAG, "server: copying files " + f.toString());
            InputStream inputstream = client.getInputStream();
            copyFile(inputstream, new FileOutputStream(f));
            serverSocket.close();
            return f.getAbsolutePath();
        } catch (IOException e) {
            Log.e(MultiImageSelectorFragment.TAG, e.getMessage());
            return null;
        }
    }

    /*
     * (non-Javadoc)
     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
     */
    @Override
    protected void onPostExecute(String result) {
      //Do stuff with data..

    }

ServerAsyncTask(empty code/initalizers removed as it's not relevant)

public static class ServerAsyncTask extends AsyncTask<Void, Void, String> {

    public ServerAsyncTask(Context context, WifiP2pInfo info, Uri[] uris) {

    }

    @Override
    protected String doInBackground(Void... params) {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(8988);
            Log.d(MultiImageSelectorFragment.TAG, "Server: Socket opened");
            boolean serverIsRunning = true;

            while(serverIsRunning) {
                Socket client = serverSocket.accept();
                        String addr = client.getInetAddress().toString();
                sendPictures(addr);
            }
            serverSocket.close();

            return null;
        } catch (IOException e) {
            Log.e(MultiImageSelectorFragment.TAG, e.getMessage());
            return null;
        }finally {

        }
    }

    private void sendPictures(String remoteAddress) {
        Uri uri = mURIs[0];
        Log.d(MultiImageSelectorFragment.TAG, "Intent----------- ");
        Intent serviceIntent = new Intent(context, FileTransferService.class);
        serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
        serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, uri.toString());
        //serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS, mInfo.groupOwnerAddress.getHostAddress());
        serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS, remoteAddress);
        serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8988);
        context.startService(serviceIntent);
    }     

}

PingServerAsyncTask (empty code/initalizers removed as it's not relevant)

public static class PingServerAsyncTask extends AsyncTask<Void, Void, String> {


    public PingServerAsyncTask(Context context, WifiP2pInfo m) {

    }

    @Override
    protected String doInBackground(Void... params) {


            String host = mInfo.groupOwnerAddress.getHostAddress();
            Socket socket = new Socket();
            int port = 8988;
            int SOCKET_TIMEOUT = 5000;
            try {
                Log.d(MultiImageSelectorFragment.TAG, "Opening client socket - ");
                socket.bind(null);

                socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
                Toast.makeText(context, "server:"+host + "me:"+socket.getLocalAddress(), Toast.LENGTH_LONG).show();
                Log.d(MultiImageSelectorFragment.TAG, "Client socket - " + socket.isConnected());

            } catch (Exception e) {
                Log.e(MultiImageSelectorFragment.TAG, e.getMessage());

            } finally {
                if (socket != null) {
                    if (socket.isConnected()) {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            // Give up
                            e.printStackTrace();
                        }
                    }
                }
            }
        return null;
    }




}

The idea behind the code is: Group Owner (Server)

  1. Open server thread and wait for clients to ping
  2. (*)When the client "pings" the server now knows the client's IP address (client.getInetAddress().toString(); inside ServerAsyncTas) so it can send the data to the client. So server sends data to the client that pinged, and waits for another client to connect

Not Group Owner (client)

  1. On connection "ping" the group owner (since we know the group owner address) as per PingServerAsyncTask.
  2. After Ping start the FileServerAsyncTask and wait for server to send data over.

The problem is that when the server tries to send the data in step marked (*), I get a java.net.UnknownHostException: Host is unresolved: exception. I can't figure out why I get that exception? The IP address I use is the one I just got from the client pinging the server, so it should be correct? Not sure what the issue is?

(Note: I didn't include FileTransferService.class implementation since it's an exact copy of the one from the Google WifiDirect demo so is available in the link from the first paragraph)


Solution

  • You should use the socket input and output streams to communicate between client and server.

    After connection at server side:

    dataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
    dataInputStream = new DataInputStream(clientSocket.getInputStream());
    

    To send text message:

    dataOutputStream.writeUTF(message);
    dataOutputStream.flush();
    

    I've answered similar question here: Peer to peer data sharing using Wi-Fi direct

    Let me know if that didn't help. Goodluck.