issues with one to many mobile device file transfer in android using wifi direct

1.5k views Asked by At

I am trying to create an app where one android app can transfer files ( text , video , photo ) to other multiple android devices.initially i thought to use wifi direct in android to share files across multiple devices.

but the problem i am facing with WiFi direct is , its inconsistency in maintaining connection and finding other devices.

1) sometimes app has to wait around 5 mins or more minutes and after that its able to connect.

2) many times after accepting invitation through a dialog from other device, it takes lot of time in changing connection to connected state and till then device is not able to get the IP address of other device.

after experiencing the inconsistency, i thought to drop the idea of using wifi direct. does anyone has a better suggestion to FASTER transfer multiple files from one mobile device to another devices without access points.

2

There are 2 answers

7
unrealsoul007 On BEST ANSWER

Hotspot uses hidden methods which are invoked using Reflection. Essentially, hotspot is an access point to which other people can connect as they connect to normal wifi networks.

As told above it is an access point, hence they are two major functions one needs to support

  1. Creating a hotspot
  2. Connecting to one.

1. Creating a hotspot

/**
     * Start AccessPoint mode with the specified
     * configuration. If the radio is already running in
     * AP mode, update the new configuration
     * Note that starting in access point mode disables station
     * mode operation
     * @param wifiConfig SSID, security and channel details as part of WifiConfiguration
     * @return {@code true} if the operation succeeds, {@code false} otherwise
     */
    public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
        try {
            if (enabled) { // disable WiFi in any case
                mWifiManager.setWifiEnabled(false);
            }

            Method method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
            return (Boolean) method.invoke(mWifiManager, wifiConfig, enabled);
        } catch (Exception e) {
            Log.e(this.getClass().toString(), "", e);
            return false;
        }
    }

Setting up a hotspot with password (WPA2 in the following example)

WifiConfiguration wifiCon = new WifiConfiguration();
wifiCon.SSID = "ssid";
wifiCon.preSharedKey = "password";
wifiCon.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
wifiCon.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wifiCon.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wifiCon.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
try
{
    Method setWifiApMethod = wm.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
    boolean apstatus=(Boolean) setWifiApMethod.invoke(wm, wifiCon,true);
} 
catch (Exception e) 
{
    Log.e(this.getClass().toString(), "", e);
}

2. Connecting to a hotspot

public Boolean connectToHotspot(WifiManager wifiManager, String ssid) 
    {
        this.wifiManager = wifiManager;
        WifiConfiguration wc = new WifiConfiguration();
        wc.SSID = "\"" +encodeSSID(ssid) +"\"";
        wc.preSharedKey  = "\"" + generatePassword(new StringBuffer(ssid).reverse().toString())  +  "\"";
        wifiManager.addNetwork(wc);
        List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
        for( WifiConfiguration i : list ) {
            if(i!=null && i.SSID != null && i.SSID.equals(wc.SSID)) 
            {
                 wifiManager.disconnect();
                 boolean status = wifiManager.enableNetwork(i.networkId, true);
                 wifiManager.reconnect();               
                 return status;
            }
         }
        return false;
    }

Coming to think of it, you may also need list of devices connected to hotspot

/**
     * Gets a list of the clients connected to the Hotspot, reachable timeout is 300
     * @param onlyReachables {@code false} if the list should contain unreachable (probably disconnected) clients, {@code true} otherwise
     * @param finishListener, Interface called when the scan method finishes
     */
    public void getClientList(boolean onlyReachables, FinishScanListener finishListener) {
        getClientList(onlyReachables, 300, finishListener );
    }
/**
 * Gets a list of the clients connected to the Hotspot 
 * @param onlyReachables {@code false} if the list should contain unreachable (probably disconnected) clients, {@code true} otherwise
 * @param reachableTimeout Reachable Timout in miliseconds
 * @param finishListener, Interface called when the scan method finishes 
 */

public void getClientList(final boolean onlyReachables, final int reachableTimeout, final FinishScanListener finishListener) {

Runnable runnable = new Runnable() {
    public void run() {

        BufferedReader br = null;
        final ArrayList<String> resultIPAddr = new ArrayList<String>();

        try {
            br = new BufferedReader(new FileReader("/proc/net/arp"));
            String line;
            while ((line = br.readLine()) != null) {
                String[] splitted = line.split(" +");

                if ((splitted != null) && (splitted.length >= 4)) {
                    // Basic sanity check
                    String mac = splitted[3];

                    if (mac.matches("..:..:..:..:..:..")) {
                        boolean isReachable = InetAddress.getByName(splitted[0]).isReachable(reachableTimeout);

                        if (!onlyReachables || isReachable) {
                            resultIPAddr.add(splitted[0]);
                        }
                    }
                }
            }
        } catch (Exception e) {
            Log.e(this.getClass().toString(), e.toString());
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                Log.e(this.getClass().toString(), e.getMessage());
            }
        }

        // Get a handler that can be used to post to the main thread
        Handler mainHandler = new Handler(context.getMainLooper());
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                finishListener.onFinishScan(result);
            }
        };
        mainHandler.post(myRunnable);
    }
};

Thread mythread = new Thread(runnable);
mythread.start();
}

Also you may need to scan for nearby Wifi networks to get the network to connect to.

//This can be done by getting WifiManager's instance from the System.

WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiManager.getScanResults();

// The above is an async call and will results are available System will broadcast `SCAN_RESULTS_AVAILABLE` intent and you need to set a `BroadCastReceiver` for it.

// And get the results like this 

List<ScanResult> results = wifiManager.getScanResults();

Hope these are all the pointers you need..!!

1
Sahil Bahl On

Wifi direct as a technology is ideal for peer to peer communication.However talking about wifi direct for android , it works well only for a single connection that is only 1-1 use case .It is possible to create a one to many where every device connects to the group owner (Soft AP).But even if u build a one to one and try extend to multi use case you will have problems with certain devices that do no connect perfectly.Devices getting stuck in invited state. Checkout some of the problems listed under problems after downloading this application https://play.google.com/store/apps/details?id=com.budius.WiFiShoot&hl=en

If you want to go for multiple connection it is better to use hotspot .One device ends up being the hotspot and other clients connect to the hotspot .It is being used by plenty of application like xender, zapiya.