Monday, March 13, 2017

Android - Share multiple files with Wi-Fi Direct

If you already read my previous blog that shows how can we find and connect near available device in Wi-fi Direct environment. In this blog, i'm going to explain how can share multiple files with Wi-Fi Direct.

To achieve this we going to use service.

1. ProgressSenderService is using for send files at the sender side.
2. ProgressReceiverService is using from receive files at the receiver side.


1. Add the services in your project manifest.


   <service android:name=".ProgressReceiverService"/>
   <service android:name=".ProgressSenderService"/>

2. Get address of receiver device.

We can get the address of another device by using the connect() of WifiP2pManager that explains blog steps 5 and 7.


3. Start receiver service.

On file receiver side register and start ProgressReceiverService

Intent receiveIntent = new Intent(activity, ProgressReceiverService.class);
            receiveIntent.setAction(ProgressReceiverService.ACTION_RECEIVE);
            activity.startService(receiveIntent);

            LocalBroadcastManager.getInstance(activity).registerReceiver(mainReceiver, new IntentFilter(ProgressReceiverService.ACTION_RECEIVE));

4. Start sender service.

On file sender side register and start ProgressSenderService with put a bundle that contains full path list of files and receiver address.

Intent receiveIntent = new Intent(activity, ProgressSenderService.class);
                receiveIntent.setAction(ProgressSenderService.ACTION_SEND_FILE);

         
                Bundle b = new Bundle();
                b.putStringArrayList("files", ArrayList<FileFullPathString>);

                receiveIntent.putExtra("files_bundle", b);
                receiveIntent.putExtra("address", p2pInfo.groupOwnerAddress.getHostAddress());
                activity.startService(receiveIntent);

                LocalBroadcastManager.getInstance(activity).registerReceiver(mainReceiver, new IntentFilter(ProgressSenderService.ACTION_SEND_FILE));

5. Sender service.


import android.app.IntentService;
import android.content.Intent;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;

/**
 * A service that process each file transfer request i.e Intent by opening a
 * socket connection with the WiFi Direct Group Owner and writing the file
 */
public class ProgressSenderService extends IntentService {
    private static final int SOCKET_TIMEOUT = 5000;
    public static final String ACTION_SEND_FILE = "com.demo.wifidirect.SEND_FILE";

    public ProgressSenderService(String name) {
        super(name);
    }

    public ProgressSenderService() {
        super("ProgressSenderService");
    }

    /*
     * (non-Javadoc)
     * @see android.app.IntentService#onHandleIntent(android.content.Intent)
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent.getAction().equals(ACTION_SEND_FILE)) {

            ArrayList<String> files = intent.getBundleExtra("files_bundle").getStringArrayList("files");
            String mAddress = intent.getStringExtra("address");

            Socket socket = new Socket();

            try {          
                socket.bind(null);

                socket.connect(new InetSocketAddress(mAddress, 8988), SOCKET_TIMEOUT);
         
                BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
                DataOutputStream dos = new DataOutputStream(bos);

                dos.writeInt(files.size());

                for (int index = 0; index < files.size(); index++) {
                    ShareFile file = new ShareFile(files.get(index));

                    Log.d("5", file.getPath());
                    long length = file.length();
                    dos.writeLong(length);
                    Log.d("6", "length: " + length);
                    String name = file.getName();

                    dos.writeUTF(name);
                    FileInputStream fis = new FileInputStream(file);
                    BufferedInputStream bis = new BufferedInputStream(fis);

                    transfer(bis, bos, length, index);

                    bis.close();

                    Thread.sleep(1000);
                    Log.d("7", "Client: Data written");
                }

                dos.close();
            } catch (IOException e) {
                Log.e("8", e.getMessage());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                allFileSentNotify();
                if (socket != null) {
                    if (socket.isConnected()) {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
            Log.d("9", "Client: stop service");
        }
    }

    private void transfer(BufferedInputStream bis, BufferedOutputStream bos, long length, int index) throws IOException {
        int theByte;

        int count = 0;
        long totalSent = 0;
        byte[] buffer = new byte[1024];
        while ((theByte = bis.read(buffer)) > 0) {
            try {
                bos.write(buffer, 0, theByte);
            } catch (IOException e) {
                e.printStackTrace();
            }
            bos.flush();

            totalSent += theByte;

            if (count == 50) {
                count = 0;
                     Log.d(TAG, "progress: " + length+"  "+index);
            }
            count++;
        }
    }
}


6. Receiver service.


import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class ProgressReceiverService extends IntentService {
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */

    private static final String TAG = ProgressReceiverService.class.getName();
    public static final String ACTION_RECEIVE = "action_receive";

    private List<String> mFileName = new ArrayList<>();

    public ProgressReceiverService(String name) {
        super(name);
    }

    private void createDir() {
        new File(android.os.Environment.getExternalStorageDirectory() + "/shareFiles").mkdirs();  
    }

    public ProgressReceiverService() {
        super("ProgressReceiverService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
   
        if (ACTION_RECEIVE.equals(intent.getAction())) {
   
            createDir();


            try {

                /**
                 * Create a server socket and wait for client connections. This
                 * call blocks until a connection is accepted from a client
                 */
                Log.d(TAG, "server create");
                ServerSocket serverSocket = new ServerSocket();
                serverSocket.setReuseAddress(true);
                serverSocket.bind(new InetSocketAddress(8988));
                Socket client = serverSocket.accept();
                Log.d(TAG, "client accept");

                BufferedInputStream bis = new BufferedInputStream(client.getInputStream());
                DataInputStream dis = new DataInputStream(bis);

           
Log.d(TAG, "Receiving "+dis.readInt()+" files");
           

                long totalSent;

                for (int index = 0; index < filesCount; index++) {
                         long fileLength = dis.readLong();
                         long fileSize = fileLength;
                         totalSent = 0;
                          Log.d(TAG, "length: " + fileLength);
                           String fileName = dis.readUTF();
                          Log.d(TAG, "name: " + fileName);

                          FileOutputStream fos = new FileOutputStream(getFile(fileName));
                          int theByte;
                          byte[] buffer = new byte[1024];

                          int count = 0;
                        while (fileLength > 0 && (theByte = dis.read(buffer, 0, (int) Math.min(buffer.length, fileLength))) != -1) {
                                 fos.write(buffer, 0, theByte);
                                 fileLength -= theByte;
                                 totalSent += theByte;

                                 if (count == 50) {
                                      count = 0;
       Log.d(TAG, "progress: " + totalSent+" "+fileSize+" "+index+" "+fileName);
                                }
                             count++;
                    }

                    fos.close();
                    Log.d(TAG, "get file: " + fileName);
                    mFileName.add(fileName);

                    new MediaScannerWrapper(getApplicationContext(), dirPath + "/" + fileName, "image/*").scan();
                }
                dis.close();
                serverSocket.close();
                Log.d(TAG, "saved file and close server");
            } catch (IOException e) {
                Log.e(TAG, e.getMessage() + "");
            }

            stopSelf();
        }
    }

    private File getFile(String fileName) {
        return new File(dirPath + "/" + fileName);
    }

    private class MediaScannerWrapper implements MediaScannerConnection.MediaScannerConnectionClient {
        private MediaScannerConnection mConnection;
        private String mPath;
        private String mMimeType;

        public MediaScannerWrapper(Context context, String filePath, String mime) {
            mPath = filePath;
            mMimeType = mime;
            mConnection = new MediaScannerConnection(context, this);
        }

        public void scan() {
            mConnection.connect();
        }

        @Override
        public void onMediaScannerConnected() {
            mConnection.scanFile(mPath, mMimeType);
        }

        @Override
        public void onScanCompleted(String path, Uri uri) {
            //Empty method
        }
    }
}

Model: ShareFile

import java.io.File;
import java.io.Serializable;

/**
 * class use basic method of File and provide file progress fields
 */
public class ShareFile extends File implements Serializable {
    private String url;

    private int progress;

    private String receivedDate;
    private String fileSize;

    private String customName = "Waiting..";


    public ShareFile(String fileUrl) {
        super(fileUrl);
        url = fileUrl;
    }

    public String getUrl() {
        return url;
    }

    public int getProgress() {
        return progress;
    }

    public String getFileSize() {
        return fileSize;
    }

    public void setProgress(int progress) {
        this.progress = progress;
    }

    public void setFileSize(String fileSize) {
        this.fileSize = fileSize;
    }

    public String getReceivedDate() {
        return receivedDate;
    }

    public void setReceivedData(String receivedDate) {
        this.receivedDate = receivedDate;
    }

    public String getCustomName() {
        return customName;
    }

    public void setCustomName(String customName) {
        this.customName = customName;
    }

}

Share:

Get it on Google Play

React Native - Start Development with Typescript

React Native is a popular framework for building mobile apps for both Android and iOS. It allows developers to write JavaScript code that ca...