8

Hi My ultimate aim is to transfer files using wifi direct api in android between two devices. Once device act as a client another one act as a server as in the wifi direct sdk demo. For this, Creating a socket from the client side by using server port and host address. I want to transfer multiple files. In the receiver side while accepting the client socket connection, I have to create the file with the filename of the file which sent from the client side. But I dont know that filename from the server side.

So how to send file name using socket connection for this wifi direct transfer mode for multiple file transfer.

Creating socket from client side using server port and host address:

fileUris = intent.getExtras().getParcelableArrayList(EXTRA_STREAM);
        String host = intent.getExtras().getString(
                EXTRAS_GROUP_OWNER_ADDRESS);
        Socket socket = new Socket();
        int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);

        try {
            Log.d(WifiDirectActivity.TAG, "Opening client socket - ");
            socket.bind(null);
            socket.connect((new InetSocketAddress(host, port)),
                    SOCKET_TIMEOUT);

            Log.d(WifiDirectActivity.TAG,
                    "Client socket - " + socket.isConnected());
            OutputStream stream = socket.getOutputStream();
            ContentResolver cr = context.getContentResolver();
            InputStream is = null;
            for (int i = 0; i < fileUris.size(); i++) {
                Uri uri = fileUris.get(0);

                try {
                    is = cr.openInputStream(Uri.parse(uri.toString()));
                } catch (FileNotFoundException e) {
                    Log.d(WifiDirectActivity.TAG, e.toString());
                }
                DeviceDetailFragment.copyFile(is, stream);
                Log.d(WifiDirectActivity.TAG, "Client: Data written");
            }

Accepting client socket connection form server side:

    ServerSocket serverSocket = new ServerSocket(8988);
            Log.d(WifiDirectActivity.TAG, "Server: Socket opened");
            Socket client = serverSocket.accept();

            Log.d(WifiDirectActivity.TAG,
                    "Server: connection done with client");

            final File f = new File(
                    Environment.getExternalStorageDirectory() + "/"
                            + context.getPackageName() + "/wifip2pshared-"
                            + "sample");
            File dirs = new File(f.getParent());
            if (!dirs.exists())
                dirs.mkdirs();
            f.createNewFile();

            Log.d(WifiDirectActivity.TAG,
                    "server: copying files " + f.toString());
            InputStream inputstream = client.getInputStream();                          

            copyFile(inputstream, new FileOutputStream(f));
            serverSocket.close();

Really struck on giving file name at the receiver side at file creation. Is there any way to send file name along with that. please Help me on this. Thanks in advance.

M Vignesh
  • 1,586
  • 2
  • 18
  • 55
  • If my way of doing it does suit your need, kindly flag it as the accepted answer, so that it may be a reference for others as well. Thanks. – Sebastiano Mar 06 '14 at 22:13

1 Answers1

2

You could create a bundle object that embeds both the file name and the actual data. Something like this:

    public class WiFiDirectBundle extends Serializable {
        private String fileName;
        private String mimeType;
        private Long fileSize;
        private byte[] fileContent;

        public WiFiDirectBundle() {}

        // adds a file to the bundle, given its URI
        public void setFile(Uri uri) {
            File f = new File(Uri.parse(uri.toString()));

            fileName = f.getName();
            mimeType = MimeTypeMap.getFileExtensionFromUrl(f.getAbsolutePath());
            fileSize = f.length();

            FileInputStream fin = new FileInputStream(f);        
            fileContent = new byte[(int) f.length()];
            fin.read(fileContent);
        }

        // restores the file of the bundle, given its directory (change to whatever
        // fits you better)
        public String restoreFile(String baseDir) {
            File f = new File(baseDir + "/" + fileName);
            try {
                FileOutputStream fos = new FileOutputStream(f);
                if (fileContent != null) {
                    fos.write(fileContent);
                }

                fos.close();
                return f.getAbsolutePath();

            } catch (IOException e) {
                    e.printStackTrace();
            }

            return null;
        }

        public String getFileName() {
            return fileName;
        }

        public String getMimeType() {
            return mimeType;
        }

        public Long getFileSize() {
            return fileSize;
        }
    }

Then, you can pass an instance of a WiFiDirectBundle back and forth by simply using the input and output streams. When you receive an object, you must explicitly cast it to the WiFiDirectBundle class.

I know it's not elegant, but it actually works.

Sebastiano
  • 12,289
  • 6
  • 47
  • 80