androidandroid-wifiwifi-directwifip2pandroid-wireless

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


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.


Solution

  • 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..!!