Home | History | Annotate | Download | only in connectivity
      1 page.title=Wi-Fi Direct
      2 page.tags="wireless","WifiP2pManager"
      3 
      4 @jd:body
      5 
      6   <div id="qv-wrapper">
      7     <div id="qv">
      8       <h2>In this document</h2>
      9 
     10       <ol>
     11         <li><a href="#api">API Overview</a></li>
     12         <li><a href="#creating-br">Creating a Broadcast Receiver for Wi-Fi Direct Intents</a></li>
     13 
     14         <li>
     15           <a href="#creating-app">Creating a Wi-Fi Direct Application</a>
     16 
     17           <ol>
     18             <li><a href="#setup">Initial setup</a></li>
     19 
     20             <li><a href="#discovering">Discovering peers</a></li>
     21 
     22             <li><a href="#connecting">Connecting to peers</a></li>
     23 
     24             <li><a href="#transferring">Transferring data</a></li>
     25           </ol>
     26         </li>
     27       </ol>
     28       <h2>Related Samples</h2>
     29       <ol>
     30         <li><a href="{@docRoot}resources/samples/WiFiDirectDemo/index.html">Wi-Fi Direct Demo</a></li>
     31       </ol>
     32     </div>
     33   </div>
     34 
     35   <p>Wi-Fi Direct allows Android 4.0 (API level 14) or later devices with the appropriate hardware
     36   to connect directly to each other via Wi-Fi without an intermediate access point.
     37   Using these APIs, you can discover and connect to other devices when each device supports Wi-Fi Direct,
     38   then communicate over a speedy connection across distances much longer than a Bluetooth connection.
     39   This is useful for applications that share data among users, such as a multiplayer game or
     40   a photo sharing application.</p>
     41 
     42   <p>The Wi-Fi Direct APIs consist of the following main parts:</p>
     43 
     44   <ul>
     45     <li>Methods that allow you to discover, request, and connect to peers are defined
     46     in the {@link android.net.wifi.p2p.WifiP2pManager} class.</li>
     47 
     48     <li>Listeners that allow you to be notified of the success or failure of {@link
     49     android.net.wifi.p2p.WifiP2pManager} method calls. When calling {@link
     50     android.net.wifi.p2p.WifiP2pManager} methods, each method can receive a specific listener
     51     passed in as a parameter.</li>
     52 
     53     <li>Intents that notify you of specific events detected by the Wi-Fi Direct framework,
     54     such as a dropped connection or a newly discovered peer.</li>
     55   </ul>
     56 
     57   <p>You often use these three main components of the APIs together. For example, you can
     58   provide a {@link android.net.wifi.p2p.WifiP2pManager.ActionListener} to a call to {@link
     59   android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()}, so that you can be
     60   notified with the {@link android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess
     61   ActionListener.onSuccess()} and {@link android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure
     62   ActionListener.onFailure()}
     63   methods. A {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent is
     64   also broadcast if the {@link android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()}
     65   method discovers that the peers list has changed.</p>
     66   
     67   <h2 id="api">API Overview</h2>
     68 
     69 <p>The {@link android.net.wifi.p2p.WifiP2pManager} class provides methods to allow you to interact with
     70   the Wi-Fi hardware on your device to do things like discover and connect to peers. The following actions
     71   are available:</p>
     72 
     73 <p class="table-caption"><strong>Table 1.</strong>Wi-Fi Direct Methods</p>
     74 
     75    <table>
     76         <tr>
     77           <th>Method</th>
     78           <th>Description</th>
     79         </tr>
     80 
     81 	<tr>
     82 	  <td>{@link android.net.wifi.p2p.WifiP2pManager#initialize initialize()}</td>
     83 	  <td>Registers the application with the Wi-Fi framework. This must be called before calling any other Wi-Fi Direct method.</td>
     84 	</tr>
     85 
     86 	<tr>
     87 	  <td>{@link android.net.wifi.p2p.WifiP2pManager#connect connect()}</td>
     88 	  <td>Starts a peer-to-peer connection with a device with the specified configuration.</td>
     89 	</tr>
     90 
     91 	<tr>
     92 	  <td>{@link android.net.wifi.p2p.WifiP2pManager#cancelConnect cancelConnect()}</td>
     93 	  <td>Cancels any ongoing peer-to-peer group negotiation.</td>
     94 	</tr>
     95 
     96 	<tr>
     97 	  <td>{@link android.net.wifi.p2p.WifiP2pManager#requestConnectionInfo requestConnectInfo()}</td>
     98 	  <td>Requests a device's connection information.</td>
     99 	</tr>
    100 
    101 	<tr>
    102 	  <td>{@link android.net.wifi.p2p.WifiP2pManager#createGroup createGroup()}</td>
    103 	  <td>Creates a peer-to-peer group with the current device as the group owner.</td>
    104 	</tr>
    105 
    106 	<tr>
    107 	  <td>{@link android.net.wifi.p2p.WifiP2pManager#removeGroup removeGroup()}</td>
    108 	  <td>Removes the current peer-to-peer group.</td>
    109 	</tr>
    110 
    111 	<tr>
    112 	  <td>{@link android.net.wifi.p2p.WifiP2pManager#requestGroupInfo requestGroupInfo()}</td>
    113 	  <td>Requests peer-to-peer group information.</td>
    114 	</tr>
    115 
    116 	<tr>
    117 	  <td>{@link android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()}</td>
    118 	  <td>Initiates peer discovery </td>
    119 	</tr>
    120 
    121 	<tr>
    122 	  <td>{@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()}</td>
    123 	  <td>Requests the current list of discovered peers.</td>
    124 	</tr>
    125   </table>
    126 
    127 
    128  <p>{@link android.net.wifi.p2p.WifiP2pManager} methods let you pass in a listener,
    129   so that the Wi-Fi Direct framework can notify your
    130   activity of the status of a call. The available listener interfaces and the
    131   corresponding {@link android.net.wifi.p2p.WifiP2pManager} method calls that use the listeners
    132   are described in the following table:</p>
    133 
    134  <p class="table-caption"><strong>Table 2.</strong> Wi-Fi Direct Listeners</p>
    135  
    136  <table>
    137     <tr>
    138       <th>Listener interface</th>
    139       <th>Associated actions</th>
    140     </tr>
    141     <tr>
    142     <td>{@link android.net.wifi.p2p.WifiP2pManager.ActionListener}</td>
    143     <td>{@link android.net.wifi.p2p.WifiP2pManager#connect connect()}, {@link
    144     android.net.wifi.p2p.WifiP2pManager#cancelConnect cancelConnect()}, {@link
    145     android.net.wifi.p2p.WifiP2pManager#createGroup createGroup()}, {@link
    146     android.net.wifi.p2p.WifiP2pManager#removeGroup removeGroup()}, and {@link
    147     android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()}</td>
    148     </tr>
    149 
    150     <tr>
    151       <td>{@link android.net.wifi.p2p.WifiP2pManager.ChannelListener}</td>
    152       <td>{@link android.net.wifi.p2p.WifiP2pManager#initialize initialize()}</td>
    153     </tr>
    154 
    155     <tr>
    156       <td>{@link android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener}</td>
    157       <td>{@link android.net.wifi.p2p.WifiP2pManager#requestConnectionInfo requestConnectInfo()}</td>
    158     </tr>
    159 
    160     <tr>
    161       <td>{@link android.net.wifi.p2p.WifiP2pManager.GroupInfoListener}</td>
    162       <td>{@link android.net.wifi.p2p.WifiP2pManager#requestGroupInfo requestGroupInfo()}</td>
    163     </tr>
    164 
    165     <tr>
    166       <td>{@link android.net.wifi.p2p.WifiP2pManager.PeerListListener}</td>
    167       <td>{@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()}</td>
    168     </tr>
    169   </table>
    170 
    171 <p>The Wi-Fi Direct APIs define intents that are broadcast when certain Wi-Fi Direct events happen,
    172   such as when a new peer is discovered or when a device's Wi-Fi state changes. You can register
    173   to receive these intents in your application by <a href="#creating-br">creating a broadcast
    174   receiver</a> that handles these intents:</p>
    175 
    176 <p class="table-caption"><strong>Table 3.</strong> Wi-Fi Direct Intents</p>
    177 
    178     <table>
    179     <tr>
    180       <th>Intent</th>
    181       <th>Description</th>
    182     </tr>
    183       <tr>
    184         <td>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION}</td>
    185         <td>Broadcast when the state of the device's Wi-Fi connection changes.</td>
    186       </tr>
    187       <tr>
    188         <td>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION}</td>
    189         <td>Broadcast when you call {@link
    190     android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()}. You
    191     usually want to call {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener#requestPeers
    192     requestPeers()} to get an updated list of peers if you handle this intent in your
    193     application.</td>
    194       </tr>
    195       <tr>
    196         <td>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_CHANGED_ACTION}</td>
    197         <td>Broadcast when Wi-Fi Direct is enabled or disabled on the device.</td>
    198       </tr>
    199       <tr>
    200         <td>{@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_THIS_DEVICE_CHANGED_ACTION}</td>
    201         <td>Broadcast when a device's details have changed, such as the device's name.</td>
    202       </tr>
    203     </table>
    204 
    205 
    206 
    207   <h2 id="creating-br">Creating a Broadcast Receiver for Wi-Fi Direct Intents</h2>
    208 
    209   <p>A broadcast receiver allows you to receive intents broadcast by the Android system,
    210   so that your application can respond to events that you are interested in. The basic steps
    211   for creating a broadcast receiver to handle Wi-Fi Direct intents are as follows:</p>
    212 
    213   <ol>
    214     <li>Create a class that extends the {@link android.content.BroadcastReceiver} class. For the
    215     class' constructor, you most likely want to have parameters for the {@link
    216     android.net.wifi.p2p.WifiP2pManager}, {@link android.net.wifi.p2p.WifiP2pManager.Channel}, and
    217     the activity that this broadcast receiver will be registered in. This allows the broadcast
    218     receiver to send updates to the activity as well as have access to the Wi-Fi hardware and a
    219     communication channel if needed.</li>
    220 
    221     <li>In the broadcast receiver, check for the intents that you are interested in
    222     <code>{@link android.content.BroadcastReceiver#onReceive onReceive()}</code>.
    223     Carry out any necessary actions depending on the intent that is
    224     received. For example, if the broadcast receiver receives a {@link
    225     android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent, you can call the
    226     {@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()} method to get a list of
    227     the currently discovered peers.</li>
    228   </ol>
    229 
    230   <p>The following code shows you how to create a typical broadcast receiver. The broadcast
    231   receiver takes a {@link android.net.wifi.p2p.WifiP2pManager} object and an activity as
    232   arguments and uses these two classes to appropriately carry out the needed actions when the
    233   broadcast receiver receives an intent:</p>
    234 
    235 <pre>
    236 /**
    237  * A BroadcastReceiver that notifies of important Wi-Fi p2p events.
    238  */
    239 public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
    240 
    241     private WifiP2pManager mManager;
    242     private Channel mChannel;
    243     private MyWiFiActivity mActivity;
    244 
    245     public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
    246             MyWifiActivity activity) {
    247         super();
    248         this.mManager = manager;
    249         this.mChannel = channel;
    250         this.mActivity = activity;
    251     }
    252 
    253     &#064;Override
    254     public void onReceive(Context context, Intent intent) {
    255         String action = intent.getAction();
    256 
    257         if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
    258             // Check to see if Wi-Fi is enabled and notify appropriate activity
    259         } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
    260             // Call WifiP2pManager.requestPeers() to get a list of current peers
    261         } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
    262             // Respond to new connection or disconnections
    263         } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
    264             // Respond to this device's wifi state changing
    265         }
    266     }
    267 }
    268 </pre>
    269 
    270   <h2 id="creating-app">Creating a Wi-Fi Direct Application</h2>
    271 
    272   <p>Creating a Wi-Fi Direct application involves creating and registering a
    273   broadcast receiver for your application, discovering peers, connecting to a peer, and
    274   transferring data to a peer. The following sections describe how to do this.</p>
    275 
    276   <h3 id="setup">Initial setup</h3>
    277   <p>Before using the Wi-Fi Direct APIs, you must ensure that your application can access
    278   the hardware and that the device supports the Wi-Fi Direct protocol. If Wi-Fi Direct is supported,
    279   you can obtain an instance of {@link android.net.wifi.p2p.WifiP2pManager}, create and register
    280   your broadcast receiver, and begin using the Wi-Fi Direct APIs.</p>
    281   <ol>
    282     <li>
    283       <p>Request permission to use the Wi-Fi hardware on the device and also declare
    284       your application to have the correct minimum SDK version in the Android manifest:</p>
    285       <pre>
    286 &lt;uses-sdk android:minSdkVersion="14" /&gt;
    287 &lt;uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /&gt;
    288 &lt;uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /&gt;
    289 &lt;uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /&gt;
    290 &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
    291 &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
    292 </pre>
    293     </li>
    294 
    295     <li>Check to see if Wi-Fi Direct is on and supported. A good place to check this is in your
    296     broadcast receiver when it receives the {@link
    297     android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_CHANGED_ACTION} intent. Notify your
    298     activity of the Wi-Fi Direct state and react accordingly:
    299 <pre>
    300 &#064;Override
    301 public void onReceive(Context context, Intent intent) {
    302     ...
    303     String action = intent.getAction();
    304     if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
    305         int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
    306         if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
    307             // Wifi Direct is enabled
    308         } else {
    309             // Wi-Fi Direct is not enabled
    310         }
    311     }
    312     ...
    313 }
    314 </pre>
    315     </li>
    316 
    317     <li>In your activity's {@link android.app.Activity#onCreate onCreate()} method, obtain an instance of {@link
    318     android.net.wifi.p2p.WifiP2pManager} and register your application with the Wi-Fi Direct
    319     framework by calling {@link android.net.wifi.p2p.WifiP2pManager#initialize initialize()}. This
    320     method returns a {@link android.net.wifi.p2p.WifiP2pManager.Channel}, which is used to connect
    321     your application to the Wi-Fi Direct framework. You should also create an instance of your
    322     broadcast receiver with the {@link
    323     android.net.wifi.p2p.WifiP2pManager} and {@link android.net.wifi.p2p.WifiP2pManager.Channel}
    324     objects along with a reference to your activity. This allows your broadcast receiver to notify
    325     your activity of interesting events and update it accordingly. It also lets you manipulate the device's
    326     Wi-Fi state if necessary:
    327 <pre>
    328 WifiP2pManager mManager;
    329 Channel mChannel;
    330 BroadcastReceiver mReceiver;
    331 ...
    332 &#064;Override
    333 protected void onCreate(Bundle savedInstanceState){
    334     ...
    335     mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    336     mChannel = mManager.initialize(this, getMainLooper(), null);
    337     mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
    338     ...
    339 }
    340 </pre>
    341     </li>
    342 
    343     <li>Create an intent filter and add the same intents that your
    344     broadcast receiver checks for:
    345       <pre>
    346 IntentFilter mIntentFilter;
    347 ...
    348 &#064;Override
    349 protected void onCreate(Bundle savedInstanceState){
    350     ...
    351     mIntentFilter = new IntentFilter();
    352     mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
    353     mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    354     mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    355     mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
    356     ...
    357 }
    358 </pre>
    359     </li>
    360 
    361     <li>Register the broadcast receiver in the {@link android.app.Activity#onResume()} method
    362     of your activity and unregister it in the {@link android.app.Activity#onPause()} method of your activity:
    363       <pre>
    364 /* register the broadcast receiver with the intent values to be matched */
    365 &#064;Override
    366 protected void onResume() {
    367     super.onResume();
    368     registerReceiver(mReceiver, mIntentFilter);
    369 }
    370 /* unregister the broadcast receiver */
    371 &#064;Override
    372 protected void onPause() {
    373     super.onPause();
    374     unregisterReceiver(mReceiver);
    375 }
    376 </pre>
    377 
    378       <p>When you have obtained a {@link android.net.wifi.p2p.WifiP2pManager.Channel} and
    379       set up a broadcast receiver, your application can make Wi-Fi Direct method calls and receive
    380       Wi-Fi Direct intents.</p>
    381     </li>
    382 
    383     <p>You can now implement your application and use the Wi-Fi Direct features by calling the
    384     methods in {@link android.net.wifi.p2p.WifiP2pManager}. The next sections describe how to do common actions
    385     such as discovering and connecting to peers.</p>
    386   </ol>
    387 
    388   <h3 id="discovering">Discovering peers</h3>
    389 
    390   <p>To discover peers that are available to connect to, call {@link
    391   android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()} to detect
    392   available peers that are in range. The call to this function is asynchronous and a success or
    393   failure is communicated to your application with {@link
    394   android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess onSuccess()} and {@link
    395   android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure onFailure()} if you created a 
    396   {@link android.net.wifi.p2p.WifiP2pManager.ActionListener}. The
    397   {@link android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess onSuccess()} method only notifies you
    398   that the discovery process succeeded and does not provide any information about the actual peers
    399   that it discovered, if any:</p>
    400   <pre>
    401 mManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
    402     &#064;Override
    403     public void onSuccess() {
    404         ...
    405     }
    406 
    407     &#064;Override
    408     public void onFailure(int reasonCode) {
    409         ...
    410     }
    411 });
    412 
    413 </pre>
    414 
    415 <p>If the discovery process succeeds and detects peers, the system broadcasts the {@link
    416   android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent, which you can listen
    417   for in a broadcast receiver to obtain a list of peers. When your application receives the {@link
    418   android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent, you can request a
    419   list of the discovered peers with {@link
    420   android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()}. The following code shows how to set this up:</p>
    421   <pre>
    422 PeerListListener myPeerListListener;
    423 ...
    424 if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
    425 
    426     // request available peers from the wifi p2p manager. This is an
    427     // asynchronous call and the calling activity is notified with a
    428     // callback on PeerListListener.onPeersAvailable()
    429     if (mManager != null) {
    430         mManager.requestPeers(mChannel, myPeerListListener);
    431     }
    432 }
    433 </pre>
    434 
    435   <p>The {@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()} method is also
    436   asynchronous and can notify your activity when a list of peers is available with {@link
    437   android.net.wifi.p2p.WifiP2pManager.PeerListListener#onPeersAvailable onPeersAvailable()}, which is defined in
    438   the {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener} interface. The {@link
    439   android.net.wifi.p2p.WifiP2pManager.PeerListListener#onPeersAvailable onPeersAvailable()} method
    440   provides you with an {@link android.net.wifi.p2p.WifiP2pDeviceList}, which you can iterate
    441   through to find the peer that you want to connect to.</p>
    442 
    443   <h3 id="connecting">Connecting to peers</h3>
    444 
    445   <p>When you have figured out the device that you want to connect to after obtaining a list of
    446   possible peers, call the {@link android.net.wifi.p2p.WifiP2pManager#connect connect()} method to
    447   connect to the device. This method call requires a {@link android.net.wifi.p2p.WifiP2pConfig}
    448   object that contains the information of the device to connect to.
    449   You can be notified of a connection success or failure through the {@link
    450   android.net.wifi.p2p.WifiP2pManager.ActionListener}. The following code
    451   shows you how to create a connection to a desired device:</p>
    452   <pre>
    453 //obtain a peer from the WifiP2pDeviceList
    454 WifiP2pDevice device;
    455 WifiP2pConfig config = new WifiP2pConfig();
    456 config.deviceAddress = device.deviceAddress;
    457 mManager.connect(mChannel, config, new ActionListener() {
    458 
    459     &#064;Override
    460     public void onSuccess() {
    461         //success logic
    462     }
    463 
    464     &#064;Override
    465     public void onFailure(int reason) {
    466         //failure logic
    467     }
    468 });
    469 
    470 </pre>
    471 
    472 
    473   <h3 id="transferring">Transferring data</h3>
    474   <p>Once a connection is established, you can transfer data between the devices with
    475   sockets. The basic steps of transferring data are as follows:</p>
    476 
    477   <ol>
    478     <li>Create a {@link java.net.ServerSocket}. This socket waits for a connection from a client on a specified
    479     port and blocks until it happens, so do this in a background thread.</li>
    480 
    481     <li>Create a client {@link java.net.Socket}. The client uses the IP address and port of
    482     the server socket to connect to the server device.</li>
    483 
    484     <li>Send data from the client to the server. When the client
    485     socket successfully connects to the server socket, you can send data from the client to the server
    486     with byte streams. </li>
    487 
    488     <li>The server socket waits for a client connection (with the {@link java.net.ServerSocket#accept()} method). This
    489     call blocks until a client connects, so call this is another thread. When a connection happens, the server device can receive
    490     the data from the client. Carry out any actions with this data, such as saving it to a file
    491     or presenting it to the user.</li>
    492   </ol>
    493 
    494   <p>The following example, modified from the <a href=
    495   "{@docRoot}resources/samples/WiFiDirectDemo/index.html">Wi-Fi Direct Demo</a> sample, shows you how
    496   to create this client-server socket communication and transfer JPEG images from a client
    497   to a server with a service. For a complete working example, compile and run the <a href=
    498   "{@docRoot}resources/samples/WiFiDirectDemo/index.html">Wi-Fi Direct Demo</a> sample.</p>
    499 <pre>
    500 public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
    501 
    502     private Context context;
    503     private TextView statusText;
    504 
    505     public FileServerAsyncTask(Context context, View statusText) {
    506         this.context = context;
    507         this.statusText = (TextView) statusText;
    508     }
    509 
    510     &#064;Override
    511     protected String doInBackground(Void... params) {
    512         try {
    513 
    514             /**
    515              * Create a server socket and wait for client connections. This
    516              * call blocks until a connection is accepted from a client
    517              */
    518             ServerSocket serverSocket = new ServerSocket(8888);
    519             Socket client = serverSocket.accept();
    520 
    521             /**
    522              * If this code is reached, a client has connected and transferred data
    523              * Save the input stream from the client as a JPEG file
    524              */
    525             final File f = new File(Environment.getExternalStorageDirectory() + "/"
    526                     + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
    527                     + ".jpg");
    528 
    529             File dirs = new File(f.getParent());
    530             if (!dirs.exists())
    531                 dirs.mkdirs();
    532             f.createNewFile();
    533             InputStream inputstream = client.getInputStream();
    534             copyFile(inputstream, new FileOutputStream(f));
    535             serverSocket.close();
    536             return f.getAbsolutePath();
    537         } catch (IOException e) {
    538             Log.e(WiFiDirectActivity.TAG, e.getMessage());
    539             return null;
    540         }
    541     }
    542 
    543     /**
    544      * Start activity that can handle the JPEG image
    545      */
    546     &#064;Override
    547     protected void onPostExecute(String result) {
    548         if (result != null) {
    549             statusText.setText("File copied - " + result);
    550             Intent intent = new Intent();
    551             intent.setAction(android.content.Intent.ACTION_VIEW);
    552             intent.setDataAndType(Uri.parse("file://" + result), "image/*");
    553             context.startActivity(intent);
    554         }
    555     }
    556 }
    557 </pre>
    558 
    559   <p>On the client, connect to the server socket with a client socket and transfer data. This example
    560   transfers a JPEG file on the client device's file system.</p>
    561 
    562 <pre>
    563 Context context = this.getApplicationContext();
    564 String host;
    565 int port;
    566 int len;
    567 Socket socket = new Socket();
    568 byte buf[]  = new byte[1024];
    569 ...
    570 try {
    571     /**
    572      * Create a client socket with the host,
    573      * port, and timeout information.
    574      */
    575     socket.bind(null);
    576     socket.connect((new InetSocketAddress(host, port)), 500);
    577 
    578     /**
    579      * Create a byte stream from a JPEG file and pipe it to the output stream
    580      * of the socket. This data will be retrieved by the server device.
    581      */
    582     OutputStream outputStream = socket.getOutputStream();
    583     ContentResolver cr = context.getContentResolver();
    584     InputStream inputStream = null;
    585     inputStream = cr.openInputStream(Uri.parse("path/to/picture.jpg"));
    586     while ((len = inputStream.read(buf)) != -1) {
    587         outputStream.write(buf, 0, len);
    588     }
    589     outputStream.close();
    590     inputStream.close();
    591 } catch (FileNotFoundException e) {
    592     //catch logic
    593 } catch (IOException e) {
    594     //catch logic
    595 }
    596 
    597 /**
    598  * Clean up any open sockets when done
    599  * transferring or if an exception occurred.
    600  */
    601 finally {
    602     if (socket != null) {
    603         if (socket.isConnected()) {
    604             try {
    605                 socket.close();
    606             } catch (IOException e) {
    607                 //catch logic
    608             }
    609         }
    610     }
    611 }
    612 </pre>
    613