diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index be0ca0e70caec..b8d95e2f107bc 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -364,6 +364,9 @@
  • Advanced NFC
  • +
  • + WiFi Direct new! +
  • USB diff --git a/docs/html/guide/topics/wireless/wifip2p.jd b/docs/html/guide/topics/wireless/wifip2p.jd new file mode 100644 index 0000000000000..4dd3d26e27aa2 --- /dev/null +++ b/docs/html/guide/topics/wireless/wifip2p.jd @@ -0,0 +1,611 @@ +page.title=Wi-Fi Direct + +@jd:body + + + +

    Wi-Fi Direct allows Android 4.0 (API level 14) or later devices with the appropriate hardware + to connect directly to each other via Wi-Fi without an intermediate access point. + Using these APIs, you can discover and connect to other devices when each device supports Wi-Fi Direct, + then communicate over a speedy connection across distances much longer than a Bluetooth connection. + This is useful for applications that share data among users, such as a multiplayer game or + a photo sharing application.

    + +

    The Wi-Fi Direct APIs consist of the following main parts:

    + + + +

    You often use these three main components of the APIs together. For example, you can + provide a {@link android.net.wifi.p2p.WifiP2pManager.ActionListener} to a call to {@link + android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()}, so that you can be + notified with the {@link android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess + ActionListener.onSuccess()} and {@link android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure + ActionListener.onFailure()} + methods. A {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent is + also broadcast if the {@link android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()} + method discovers that the peers list has changed.

    + +

    API Overview

    + +

    The {@link android.net.wifi.p2p.WifiP2pManager} class provides methods to allow you to interact with + the Wi-Fi hardware on your device to do things like discover and connect to peers. The following actions + are available:

    + +

    Table 1.Wi-Fi Direct Methods

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    MethodDescription
    {@link android.net.wifi.p2p.WifiP2pManager#initialize initialize()}Registers the application with the Wi-Fi framework. This must be called before calling any other Wi-Fi Direct method.
    {@link android.net.wifi.p2p.WifiP2pManager#connect connect()}Starts a peer-to-peer connection with a device with the specified configuration.
    {@link android.net.wifi.p2p.WifiP2pManager#cancelConnect cancelConnect()}Cancels any ongoing peer-to-peer group negotiation.
    {@link android.net.wifi.p2p.WifiP2pManager#requestConnectionInfo requestConnectInfo()}Requests a device's connection information.
    {@link android.net.wifi.p2p.WifiP2pManager#createGroup createGroup()}Creates a peer-to-peer group with the current device as the group owner.
    {@link android.net.wifi.p2p.WifiP2pManager#removeGroup removeGroup()}Removes the current peer-to-peer group.
    {@link android.net.wifi.p2p.WifiP2pManager#requestGroupInfo requestGroupInfo()}Requests peer-to-peer group information.
    {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()}Initiates peer discovery
    {@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()}Requests the current list of discovered peers.
    + + +

    {@link android.net.wifi.p2p.WifiP2pManager} methods let you pass in a listener, + so that the Wi-Fi Direct framework can notify your + activity of the status of a call. The available listener interfaces and the + corresponding {@link android.net.wifi.p2p.WifiP2pManager} method calls that use the listeners + are described in the following table:

    + +

    Table 2. Wi-Fi Direct Listeners

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Listener interfaceAssociated actions
    {@link android.net.wifi.p2p.WifiP2pManager.ActionListener}{@link android.net.wifi.p2p.WifiP2pManager#connect connect()}, {@link + android.net.wifi.p2p.WifiP2pManager#cancelConnect cancelConnect()}, {@link + android.net.wifi.p2p.WifiP2pManager#createGroup createGroup()}, {@link + android.net.wifi.p2p.WifiP2pManager#removeGroup removeGroup()}, and {@link + android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()}
    {@link android.net.wifi.p2p.WifiP2pManager.ChannelListener}{@link android.net.wifi.p2p.WifiP2pManager#initialize initialize()}
    {@link android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener}{@link android.net.wifi.p2p.WifiP2pManager#requestConnectionInfo requestConnectInfo()}
    {@link android.net.wifi.p2p.WifiP2pManager.GroupInfoListener}{@link android.net.wifi.p2p.WifiP2pManager#requestGroupInfo requestGroupInfo()}
    {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener}{@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()}
    + +

    The Wi-Fi Direct APIs define intents that are broadcast when certain Wi-Fi Direct events happen, + such as when a new peer is discovered or when a device's Wi-Fi state changes. You can register + to receive these intents in your application by creating a broadcast + receiver that handles these intents:

    + +

    Table 3. Wi-Fi Direct Intents

    + + + + + + + + + + + + + + + + + + + + + + +
    IntentDescription
    {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION}Broadcast when the state of the device's Wi-Fi connection changes.
    {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION}Broadcast when you call {@link + android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()}. You + usually want to call {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener#requestPeers + requestPeers()} to get an updated list of peers if you handle this intent in your + application.
    {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_CHANGED_ACTION}Broadcast when Wi-Fi Direct is enabled or disabled on the device.
    {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_THIS_DEVICE_CHANGED_ACTION}Broadcast when a device's details have changed, such as the device's name.
    + + + +

    Creating a Broadcast Receiver for Wi-Fi Direct Intents

    + +

    A broadcast receiver allows you to receive intents broadcast by the Android system, + so that your application can respond to events that you are interested in. The basic steps + for creating a broadcast receiver to handle Wi-Fi Direct intents are as follows:

    + +
      +
    1. Create a class that extends the {@link android.content.BroadcastReceiver} class. For the + class' constructor, you most likely want to have parameters for the {@link + android.net.wifi.p2p.WifiP2pManager}, {@link android.net.wifi.p2p.WifiP2pManager.Channel}, and + the activity that this broadcast receiver will be registered in. This allows the broadcast + receiver to send updates to the activity as well as have access to the Wi-Fi hardware and a + communication channel if needed.
    2. + +
    3. In the broadcast receiver, check for the intents that you are interested in + {@link android.content.BroadcastReceiver#onReceive onReceive()}. + Carry out any necessary actions depending on the intent that is + received. For example, if the broadcast receiver receives a {@link + android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent, you can call the + {@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()} method to get a list of + the currently discovered peers.
    4. +
    + +

    The following code shows you how to create a typical broadcast receiver. The broadcast + receiver takes a {@link android.net.wifi.p2p.WifiP2pManager} object and an activity as + arguments and uses these two classes to appropriately carry out the needed actions when the + broadcast receiver receives an intent:

    + +
    +/**
    + * A BroadcastReceiver that notifies of important Wi-Fi p2p events.
    + */
    +public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
    +
    +    private WifiP2pManager manager;
    +    private Channel channel;
    +    private MyWiFiActivity activity;
    +
    +    public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
    +            MyWifiActivity activity) {
    +        super();
    +        this.manager = manager;
    +        this.channel = channel;
    +        this.activity = activity;
    +    }
    +
    +    @Override
    +    public void onReceive(Context context, Intent intent) {
    +        String action = intent.getAction();
    +
    +        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
    +            // Check to see if Wi-Fi is enabled and notify appropriate activity
    +        } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
    +            // Call WifiP2pManager.requestPeers() to get a list of current peers
    +        } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
    +            // Respond to new connection or disconnections
    +        } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
    +            // Respond to this device's wifi state changing
    +        }
    +    }
    +}
    +
    + +

    Creating a Wi-Fi Direct Application

    + +

    Creating a Wi-Fi Direct application involves creating and registering a + broadcast receiver for your application, discovering peers, connecting to a peer, and + transferring data to a peer. The following sections describe how to do this.

    + +

    Initial setup

    +

    Before using the Wi-Fi Direct APIs, you must ensure that your application can access + the hardware and that the device supports the Wi-Fi Direct protocol. If Wi-Fi Direct is supported, + you can obtain an instance of {@link android.net.wifi.p2p.WifiP2pManager}, create and register + your broadcast receiver, and begin using the Wi-Fi Direct APIs.

    +
      +
    1. +

      Request permission to use the Wi-Fi hardware on the device and also declare + your application to have the correct minimum SDK version in the Android manifest:

      +
      +<uses-sdk android:minSdkVersion="14" />
      +<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" />
      +
      +
    2. + +
    3. Check to see if Wi-Fi Direct is on and supported. A good place to check this is in your + broadcast receiver when it receives the {@link + android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_STATE_CHANGED_ACTION} intent. Notify your + activity of the Wi-Fi Direct state and react accordingly: +
      +@Override
      +public void onReceive(Context context, Intent intent) {
      +    ...
      +    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) {
      +            // Wifi Direct is enabled
      +        } else {
      +            // Wi-Fi Direct is not enabled
      +        }
      +    }
      +    ...
      +}
      +
      +
    4. + +
    5. In your activity's {@link android.app.Activity#onCreate onCreate()} method, obtain an instance of {@link + android.net.wifi.p2p.WifiP2pManager} and register your application with the Wi-Fi Direct + framework by calling {@link android.net.wifi.p2p.WifiP2pManager#initialize initialize()}. This + method returns a {@link android.net.wifi.p2p.WifiP2pManager.Channel}, which is used to connect + your application to the Wi-Fi Direct framework. You should also create an instance of your + broadcast receiver with the {@link + android.net.wifi.p2p.WifiP2pManager} and {@link android.net.wifi.p2p.WifiP2pManager.Channel} + objects along with a reference to your activity. This allows your broadcast receiver to notify + your activity of interesting events and update it accordingly. It also lets you manipulate the device's + Wi-Fi state if necessary: +
      +WifiP2pManager mManager;
      +Channel mChannel;
      +BroadcastReceiver mReceiver;
      +...
      +@Override
      +protected void onCreate(Bundle savedInstanceState){
      +    ...
      +    mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
      +    mChannel = mManager.initialize(this, getMainLooper(), null);
      +    Receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
      +    ...
      +}
      +
      +
    6. + +
    7. Create an intent filter and add the same intents that your + broadcast receiver checks for: +
      +IntentFilter mIntentFilter;
      +...
      +@Override
      +protected void onCreate(Bundle savedInstanceState){
      +    ...
      +    mIntentFilter = new IntentFilter();
      +    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
      +    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
      +    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
      +    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
      +    ...
      +}
      +
      +
    8. + +
    9. Register the broadcast receiver in the {@link android.app.Activity#onResume()} method + of your activity and unregister it in the {@link android.app.Activity#onPause()} method of your activity: +
      +/* register the broadcast receiver with the intent values to be matched */
      +@Override
      +protected void onResume() {
      +    super.onResume();
      +    registerReceiver(receiver, intentFilter);
      +}
      +/* unregister the broadcast receiver */
      +@Override
      +protected void onPause() {
      +    super.onPause();
      +    unregisterReceiver(receiver);
      +}
      +
      + +

      When you have obtained a {@link android.net.wifi.p2p.WifiP2pManager.Channel} and + set up a broadcast receiver, your application can make Wi-Fi Direct method calls and receive + Wi-Fi Direct intents.

      +
    10. + +

      You can now implement your application and use the Wi-Fi Direct features by calling the + methods in {@link android.net.wifi.p2p.WifiP2pManager}. The next sections describe how to do common actions + such as discovering and connecting to peers.

      +
    + +

    Discovering peers

    + +

    To discover peers that are available to connect to, call {@link + android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()} to detect + available peers that are in range. The call to this function is asynchronous and a success or + failure is communicated to your application with {@link + android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess onSuccess()} and {@link + android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure onFailure()} if you created a + {@link android.net.wifi.p2p.WifiP2pManager.ActionListener}. The + {@link android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess onSuccess()} method only notifies you + that the discovery process succeeded and does not provide any information about the actual peers + that it discovered, if any:

    +
    +manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
    +    @Override
    +    public void onSuccess() {
    +        ...
    +    }
    +
    +    @Override
    +    public void onFailure(int reasonCode) {
    +        ...
    +    }
    +});
    +
    +
    + +

    If the discovery process succeeds and detects peers, the system broadcasts the {@link + android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent, which you can listen + for in a broadcast receiver to obtain a list of peers. When your application receives the {@link + android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent, you can request a + list of the discovered peers with {@link + android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()}. The following code shows how to set this up:

    +
    +PeerListListener myPeerListListener;
    +...
    +if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
    +
    +    // request available peers from the wifi p2p manager. This is an
    +    // asynchronous call and the calling activity is notified with a
    +    // callback on PeerListListener.onPeersAvailable()
    +    if (manager != null) {
    +        manager.requestPeers(channel, myPeerListListener);
    +    }
    +}
    +
    + +

    The {@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()} method is also + asynchronous and can notify your activity when a list of peers is available with {@link + android.net.wifi.p2p.WifiP2pManager.PeerListListener#onPeersAvailable onPeersAvailable()}, which is defined in the + the {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener} interface. The {@link + android.net.wifi.p2p.WifiP2pManager.PeerListListener#onPeersAvailable onPeersAvailable()} method + provides you with an {@link android.net.wifi.p2p.WifiP2pDeviceList}, which you can iterate + through to find the peer that you want to connect to.

    + +

    Connecting to peers

    + +

    When you have figured out the device that you want to connect to after obtaining a list of + possible peers, call the {@link android.net.wifi.p2p.WifiP2pManager#connect connect()} method to + connect to the device. This method call requires a {@link android.net.wifi.p2p.WifiP2pConfig} + object that contains the information of the device to connect to. + You can be notified of a connection success or failure through the {@link + android.net.wifi.p2p.WifiP2pManager.ActionListener}. The following code + shows you how to create a connection to a desired device:

    +
    +//obtain a peer from the WifiP2pDeviceList
    +WifiP2pDevice device;
    +WifiP2pConfig config = new WifiP2pConfig();
    +config.deviceAddress = device.deviceAddress;
    +manager.connect(channel, config, new ActionListener() {
    +
    +    @Override
    +    public void onSuccess() {
    +        //success logic
    +    }
    +
    +    @Override
    +    public void onFailure(int reason) {
    +        //failure logic
    +    }
    +});
    +
    +
    + + +

    Transferring data

    +

    Once a connection is established, you can transfer data between the devices with + sockets. The basic steps of transferring data are as follows:

    + +
      +
    1. Create a {@link java.net.ServerSocket}. This socket waits for a connection from a client on a specified + port and blocks until it happens, so do this in a background thread.
    2. + +
    3. Create a client {@link java.net.Socket}. The client uses the IP address and port of + the server socket to connect to the server device.
    4. + +
    5. Send data from the client to the server. When the client + socket successfully connects to the server socket, you can send data from the client to the server + with byte streams.
    6. + +
    7. The server socket waits for a client connection (with the {@link java.net.ServerSocket#accept()} method). This + call blocks until a client connects, so call this is another thread. When a connection happens, the server device can receive + the data from the client. Carry out any actions with this data, such as saving it to a file + or presenting it to the user.
    8. +
    + +

    The following example, modified from the Wi-Fi Direct Demo sample, shows you how + to create this client-server socket communication and transfer JPEG images from a client + to a server with a service. For a complete working example, compile and run the Wi-Fi Direct Demo sample.

    +
    +public static class FileServerAsyncTask extends AsyncTask {
    +
    +    private Context context;
    +    private TextView statusText;
    +
    +    public FileServerAsyncTask(Context context, View statusText) {
    +        this.context = context;
    +        this.statusText = (TextView) statusText;
    +    }
    +
    +    @Override
    +    protected String doInBackground(Void... params) {
    +        try {
    +
    +            /**
    +             * Create a server socket and wait for client connections. This
    +             * call blocks until a connection is accepted from a client
    +             */
    +            ServerSocket serverSocket = new ServerSocket(8888);
    +            Socket client = serverSocket.accept();
    +
    +            /**
    +             * If this code is reached, a client has connected and transferred data
    +             * Save the input stream from the client as a JPEG file
    +             */
    +            final File f = new File(Environment.getExternalStorageDirectory() + "/"
    +                    + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
    +                    + ".jpg");
    +
    +            File dirs = new File(f.getParent());
    +            if (!dirs.exists())
    +                dirs.mkdirs();
    +            f.createNewFile();
    +            InputStream inputstream = client.getInputStream();
    +            copyFile(inputstream, new FileOutputStream(f));
    +            serverSocket.close();
    +            return f.getAbsolutePath();
    +        } catch (IOException e) {
    +            Log.e(WiFiDirectActivity.TAG, e.getMessage());
    +            return null;
    +        }
    +    }
    +
    +    /**
    +     * Start activity that can handle the JPEG image
    +     */
    +    @Override
    +    protected void onPostExecute(String result) {
    +        if (result != null) {
    +            statusText.setText("File copied - " + result);
    +            Intent intent = new Intent();
    +            intent.setAction(android.content.Intent.ACTION_VIEW);
    +            intent.setDataAndType(Uri.parse("file://" + result), "image/*");
    +            context.startActivity(intent);
    +        }
    +    }
    +}
    +
    + +

    On the client, connect to the server socket with a client socket and transfer data. This example + transfers a JPEG file on the client device's file system.

    + +
    +Context context = this.getApplicationContext();
    +String host;
    +int port;
    +int len;
    +Socket socket = new Socket();
    +byte buf[]  = new byte[1024];
    +...
    +try {
    +    /**
    +     * Create a client socket with the host,
    +     * port, and timeout information.
    +     */
    +    socket.bind(null);
    +    socket.connect((new InetSocketAddress(host, port)), 500);
    +
    +    /**
    +     * Create a byte stream from a JPEG file and pipe it to the output stream
    +     * of the socket. This data will be retrieved by the server device.
    +     */
    +    OutputStream outputStream = socket.getOutputStream();
    +    ContentResolver cr = context.getContentResolver();
    +    InputStream inputStream = null;
    +    inputStream = cr.openInputStream(Uri.parse("path/to/picture.jpg"));
    +    while ((len = inputStream.read(buf)) != -1) {
    +        outputStream.write(buf, 0, len);
    +    }
    +    outputStream.close();
    +    inputStream.close();
    +} catch (FileNotFoundException e) {
    +    //catch logic
    +} catch (IOException e) {
    +    //catch logic
    +}
    +
    +/**
    + * Clean up any open sockets when done
    + * transferring or if an exception occurred.
    + */
    +finally {
    +    if (socket != null) {
    +        if (socket.isConnected()) {
    +            try {
    +                socket.close();
    +            } catch (IOException e) {
    +                //catch logic
    +            }
    +        }
    +    }
    +}
    +