All CategoriesAndroid App Development

How to Transfer Files Using Wi-Fi Pair Connection in Android

In Android, devices that support API level 14 or above, can easily create Wi-Fi pair connection or peer-to-peer connections and share the data or files among the devices.
This feature is very useful for such applications which have to transfer files among users like photo sharing applications, etc.
As compared to Bluetooth, it provides a fast connection between devices with a much higher range of up to 100 m distance.
It can transfer data up to the speed of 2.5 to 3.0 Mbps. By using WPA2 encryption protection, which is also secured.

Real Time Applications

There are many applications that use a direct Wi-Fi pair connection without using any other networks to transfer files, like Share It, Zapya, Xender, etc.
Classes, Methods & Intents

  1. Classes

WifiP2pManager: This is a class which is used to interact with the Wi-Fi hardware on our device which helps in connecting and discovering the peers.

  1. Methods

WifiP2pManager class provides some methods for peer–to–peer connection.

  • initialize(): This method registers the application within a Wi-Fi framework, and it is called before calling any other Wi-Fi P2p methods.
  • connect(): This method is used to start a Wi-Fi pair connection with a device having a specific
  • discoverPeers(): This method is used to detect all the available peers that are in the range.
  • cancelConnect(): This method is used to cancel all the connected Wi-Fi pair connections.
  • removeGroup(): This method is used to remove the current peer–to–peer group.

3. Intents
When using the Wi-Fi pair connection, we need to listen for broadcast intents and handle the events occurred.
WIFI_P2P_STATE_CHANGED_ACTION: It indicates a change in the Wi-Fi P2P status
WIFI_P2P_PEERS _CHANGED_ACTION: It indicates a change in the list of available peers
WIFI_P2P_CONNECTION _CHANGED_ACTION: It indicates the state of Wi-Fi P2P connectivity is changed
WIFI_P2P_THIS_DEVICE _CHANGED_ACTION: It indicates the device details are changed

Example with code

Here, we are going to create an example which transfers files by creating a Wi-Fi pair connection in Android.

  • Create an Application WiFiShareFilesExampleAndroid in Android Studio

Add the permissions in the AndroidManifest.xml file.

AndroidManifest.xml

To use the Wi-Fi pair connection, we have to add some necessary permissions in this file.

Add the code here

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Let’s do it programmatically by creating some Java files and XML files in our project.

Layout Files

activity_main.xml

This is our main layout file. Here, we add two fragments inside LinearLayout.

Add the code here

LinearLayout
    android:layout_width="match_parent"
    android:id="@+id/linearLayout"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:layout_alignParentTop="true"
    android:layout_weight="0.9">
    <fragment
        class="com.example.shriyanshu.wifisharefilesexampleandroid.DeviceListFragment"
        android:id="@+id/fragment_list"
        android:layout_width="match_parent"
        android:layout_height="@dimen/phone_list_height"
        tools:layout="@layout/device_list">
    </fragment>
    <fragment
        class="com.example.shriyanshu.wifisharefilesexampleandroid.DeviceDetailFragment"
        android:id="@+id/fragment_detail"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout="@layout/device_detail">
    </fragment>
</LinearLayout>

device_detail.xml

Create this XML file to add the layout for device details.

Add the code here

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btn_connect"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:text="@string/connect_peer_button"
            android:background="@color/colorPrimary"
            android:layout_margin="5dp"
            android:textColor="#ffffff"/>
        <Button
            android:id="@+id/btn_disconnect"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:text="@string/disconnect_peer_button"
            android:background="@color/colorPrimary"
            android:layout_margin="5dp"
            android:textColor="#ffffff"/>
        <Button
            android:id="@+id/btn_start_client"
            android:layout_width="130dp"
            android:layout_height="wrap_content"
            android:text="@string/get_file_button"
            android:visibility="gone"
            android:background="@color/colorPrimary"
            android:layout_margin="5dp"
            android:textColor="#ffffff"/>
    </LinearLayout>
    <TextView
        android:id="@+id/tv_deviceAddress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv_deviceInfo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv_groupOwner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv_groupIp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
    android:layout_width="match_parent"
    android:id="@+id/ll_statusBar"
    android:orientation="vertical"
    android:layout_gravity="bottom"
    android:layout_height="wrap_content"
    android:layout_marginBottom="5dp"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:id="@+id/tv_statusText">
    </TextView>
</LinearLayout>

device_list.xml

Create this XML file to add the layout for device lists.

Add the code here

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:text="@string/label_me" />
<View
    android:layout_width="fill_parent"
    android:layout_height="1dp"
    android:gravity="center_vertical"
    android:background="@android:color/holo_blue_light" />
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:padding="3dip">
    <ImageView
        android:id="@+id/iv_Icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_marginRight="2dp"
        android:src="@mipmap/ic_launcher" />
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="fill_parent">
        <TextView
            android:id="@+id/tv_myName"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="center_vertical" />
        <TextView
            android:id="@+id/tv_myStatus"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:maxLines="1"
            android:ellipsize="marquee" />
    </LinearLayout>
</LinearLayout>
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:text="@string/label_peers" />
<View
    android:layout_width="fill_parent"
    android:layout_height="1dp"
    android:gravity="center_vertical"
    android:background="@android:color/holo_blue_light" />
<ListView
    android:id="@id/android:list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:drawSelectorOnTop="false" />
<TextView
    android:id="@id/android:empty"
    android:layout_width="match_parent"
    android:layout_gravity="center"
    android:layout_height="match_parent"
    android:text="@string/empty_message" />

row_devices.xml

Create this XML file and add the code here.

ImageView
    android:id="@+id/iv_Icon"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_marginRight="2dip"
    android:src="@mipmap/ic_launcher" />
<LinearLayout
    android:orientation="vertical"
    android:layout_width="0dip"
    android:layout_weight="1"
    android:layout_height="fill_parent">
    <TextView
        android:id="@+id/tv_deviceName"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:gravity="center_vertical" />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:id="@+id/tv_deviceDetails"
        android:maxLines="1"
        android:ellipsize="marquee" />
</LinearLayout>

menu_main.xml

Create this XML file inside res/menu folder. Here we add the two action items.

 Add the code here

<item android:id="@+id/action_directEnable"
    android:title="@string/enable_p2p_button"
    android:orderInCategory="100"
    app:showAsAction="never"/>
<item android:id="@+id/action_directDiscover"
    android:title="@string/discover_peers_button"
    android:orderInCategory="100"
    app:showAsAction="never"/>

Java Files

WifiDirectBroadcastReceiver.java

Create this class and extends with BroadcastReceiver. Here, this class notifies important Wi-Fi P2p events. The events are discussed above.

Initialize

private WifiP2pManager manager;
private Channel channel;
private MainActivity activity;

Add the Code in onReceive() Method:

String action = intent.getAction();
    if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
        int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
        if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
            activity.setIsWifiP2pEnabled(true);
        } else {
            activity.setIsWifiP2pEnabled(false);
            activity.resetData();
        }
    } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
        if (manager != null) {
            manager.requestPeers(channel, (PeerListListener) activity.getFragmentManager()
                    .findFragmentById(R.id.fragment_list));
        }
    } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
        if (manager == null) {
            return;
        }
        NetworkInfo networkInfo = (NetworkInfo) intent
                .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
        if (networkInfo.isConnected()) {
            DeviceDetailFragment fragment = (DeviceDetailFragment) activity
                    .getFragmentManager().findFragmentById(R.id.fragment_detail);
            manager.requestConnectionInfo(channel, fragment);
        } else {
                        activity.resetData();
        }
    } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
        DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
                .findFragmentById(R.id.fragment_list);
        fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
                WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));
    }
}

MainActivity.java

This is our Main Activity. Here, it adds the necessary intent values by creating an intent-filter, registers the broadcast receiver, obtains the instance of WifiP2pManager class, registers the application by using initialize() method, also discover peers and connects with the available devices.

Initialize

private WifiP2pManager manager;
private boolean isWifiP2pEnabled = false;
private boolean retryChannel = false;
private final IntentFilter intentFilter = new IntentFilter();
private Channel channel;
private BroadcastReceiver receiver = null;
  • Add the code in onCreate(…){..}:

intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
  • Now, register the receiver in onResume() method
receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
registerReceiver(receiver, intentFilter);
  • Add the code for discover peers

final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
        .findFragmentById(R.id.fragment_list);
fragment.onInitiateDiscovery();
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        Toast.makeText(MainActivity.this, "Discovery Initiated",
                Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onFailure(int reasonCode) {
        Toast.makeText(MainActivity.this, "Discovery Failed : " + reasonCode,
                Toast.LENGTH_SHORT).show();
    }
});

Now call connect() method for connecting with an available peer.

@Override
public void connect(WifiP2pConfig config) {
    manager.connect(channel, config, new ActionListener() {
        @Override
        public void onSuccess() {
        }
        @Override
        public void onFailure(int reason) {
            Toast.makeText(MainActivity.this, "Connect failed. Retry.",
                    Toast.LENGTH_SHORT).show();
        }
    });
}

DeviceDetailFragment.java

Create this fragment class. Here, it manages with a particular peer and “allows the interaction with the device” means when a connection is established successfully, we can transfer the data to the device by setting up a network connection.
Add the code here by creating a server socket that accepts the connection and writes the data.

public static class FileServerAsyncTask extends AsyncTask<String, String, String> {
      private Context mFilecontext;
      private long ReceivedFileLength;
      private int PORT;
     @Override
        protected String doInBackground(String... params) {
            try {
            CommonMethods.e("File Async task port", "File Async task port-> " + PORT);
            ServerSocket serverSocket = new ServerSocket(PORT);
            Socket client = serverSocket.accept();
            WiFiClientIp = client.getInetAddress().getHostAddress();
            ObjectInputStream ois = new ObjectInputStream(
                  client.getInputStream());
            WiFiTransferModal obj = null;
            String InetAddress;
            try {
               obj = (WiFiTransferModal) ois.readObject();
               InetAddress = obj.getInetAddress();
               if (InetAddress != null
                     && InetAddress
                           .equalsIgnoreCase(FileTransferService.inetaddress)) {
                  CommonMethods.e("File Async Group Client Ip", "port-> "
                        + WiFiClientIp);
                  SharedPreferencesHandler.setStringValues(mFilecontext,
                        "WiFiClientIp", WiFiClientIp);
                  CommonMethods
                        .e("File Async Group Client Ip from SHAREDPrefrence",
                              "port-> "
                                    + SharedPreferencesHandler
                                          .getStringValues(
                                                mFilecontext,
                                                "WiFiClientIp"));
                  SharedPreferencesHandler.setStringValues(mFilecontext,
                        "ServerBoolean", "true");
                  ois.close();
                  serverSocket.close();
                  return "Demo";
               }
            } catch (ClassNotFoundException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
            }
                        };
            handler.post(r);
             final File f = new File(
                  Environment.getExternalStorageDirectory() + "/"
                        + FolderName + "/"
                        + obj.getFileName());
            File dirs = new File(f.getParent());
            if (!dirs.exists())
               dirs.mkdirs();
            f.createNewFile();
            this.ReceivedFileLength = obj.getFileLength();
            InputStream inputstream = client.getInputStream();
            copyRecievedFile(inputstream, new FileOutputStream(f),
                  ReceivedFileLength);
            ois.close();
            serverSocket.close();
            this.Extension = obj.getFileName();
            this.EncryptedFile = f;
            return f.getAbsolutePath();
         } catch (IOException e) {
                return null;
            }
        }
        @Override
        protected void onPostExecute(String result) {
            if (result != null) {
     		   Intent intent = new Intent();
                    intent.setAction(android.content.Intent.ACTION_VIEW);
                    intent.setDataAndType(Uri.parse("file://" + result), "image/*");
                    mFilecontext.startActivity(intent);
               }
	}

Conclusion

This was a simple example of how to transfer files using a Wi-Fi pair connection in Android. As I discussed above, there are many real-time applications that use the same feature like “Share It” to transfer the files. In this post we also saw important methods and classes that are used to discover peers and connect with them. So, we can also use Wi-Fi direct API’s in our application and customize the application according to the need. This is one of the most important and popular features in Android development.

Download Source Code: GitHub

Output

Before Discover

 

Perform Discover

 

Finding Peers

 

Peer Available

 

Connecting


Connected to Device 1

Connected to Device 2

Status after Sending the Data Successfully.

Keep visiting www.acadgild.com for more updates on the Android Training .

One Comment

  1. hi
    Caused by: java.lang.ClassCastException: com.developementapps.wifiexample.DeviceDetailFragment cannot be cast to com.developementapps.wifiexample.DeviceListFragment
    at com.developementapps.wifiexample.WiFiDirectActivity.resetData(WiFiDirectActivity.java:76)
    at com.developementapps.wifiexample.WiFiDirectBroadcastReceiver.onReceive(WiFiDirectBroadcastReceiver.java:68)
    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:997)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Articles

Close