Wi-Fi Direct (P2P) consente ai dispositivi con l'hardware appropriato di connettersi direttamente tra loro tramite Wi-Fi senza un punto di accesso intermedio. Utilizzando queste API, puoi scoprire e connetterti ad altri dispositivi quando ciascuno supporta il Wi-Fi P2P, quindi comunicare tramite una connessione veloce su distanze molto più lunghe di una connessione Bluetooth. È utile per le applicazioni che condividono dati tra utenti, ad esempio un gioco multiplayer o un'applicazione di condivisione di foto.
Le API Wi-Fi P2P sono composte dai seguenti componenti principali:
- Metodi che ti consentono di scoprire, richiedere e connetterti ai peer, che sono definiti nella classe
WifiP2pManager
. - Listener che consentono di ricevere una notifica se le chiamate al metodo
WifiP2pManager
sono riuscite o non riuscite. Quando chiami i metodiWifiP2pManager
, ciascun metodo può ricevere un listener specifico trasmesso come parametro. - Intent che notificano eventi specifici rilevati dal framework Wi-Fi P2P, ad esempio un'interruzione della connessione o un peer appena rilevato.
Spesso utilizzerai questi tre componenti principali delle API insieme. Ad
esempio, puoi fornire un elemento
WifiP2pManager.ActionListener
per una chiamata a
discoverPeers()
in modo che i metodi
ActionListener.onSuccess()
e
ActionListener.onFailure()
possano ricevere notifiche. Un intent WIFI_P2P_PEERS_CHANGED_ACTION
viene trasmesso anche se il metodo discoverPeers()
rileva che l'elenco dei peer è cambiato.
Panoramica dell'API
La classe WifiP2pManager
fornisce metodi per consentirti di interagire con l'hardware Wi-Fi del tuo dispositivo per svolgere operazioni come il rilevamento e la connessione con app peer.
Sono disponibili le seguenti azioni:
Tabella 1. Metodi Wi-Fi P2P
Metodo | Descrizione |
initialize()
|
Registra l'applicazione con il framework Wi-Fi. Richiama questo tipo di connessione prima di chiamare qualsiasi altro metodo Wi-Fi P2P. |
connect()
|
Avvia una connessione peer-to-peer con un dispositivo con la configurazione specificata. |
cancelConnect()
|
Annulla qualsiasi negoziazione del gruppo peer-to-peer in corso. |
requestConnectInfo()
|
Richiede le informazioni sulla connessione di un dispositivo. |
createGroup()
|
Crea un gruppo peer-to-peer con il dispositivo corrente come proprietario del gruppo. |
removeGroup()
|
Rimuove il gruppo peer-to-peer corrente. |
requestGroupInfo()
|
Richiede informazioni sul gruppo peer-to-peer. |
discoverPeers()
|
Avvia il rilevamento dei compagni. |
requestPeers()
|
Richiede l'elenco corrente dei peer rilevati. |
I metodi WifiP2pManager
ti consentono di passare in un listener, in modo che il framework Wi-Fi P2P possa notificare alla tua attività lo stato di una chiamata. Le interfacce listener disponibili e le corrispondenti chiamate al metodo WifiP2pManager
che utilizzano i listener sono descritte nella tabella 2.
Tabella 2. Listener P2P Wi-Fi
Interfaccia listener | Azioni associate |
WifiP2pManager.ActionListener
|
connect() , cancelConnect() ,
createGroup() , removeGroup() e
discoverPeers()
|
WifiP2pManager.ChannelListener
|
initialize()
|
WifiP2pManager.ConnectionInfoListener
|
requestConnectInfo()
|
WifiP2pManager.GroupInfoListener
|
requestGroupInfo()
|
WifiP2pManager.PeerListListener
|
requestPeers()
|
Le API Wi-Fi P2P definiscono gli intent che vengono trasmessi quando si verificano determinati eventi P2P Wi-Fi, ad esempio quando viene rilevato un nuovo peer o quando lo stato Wi-Fi di un dispositivo cambia. Puoi registrarti per ricevere questi intent nella tua applicazione creando un ricevitore di trasmissione che gestisca questi intent:
Tabella 3. Intent Wi-Fi P2P
Intenzione | Descrizione |
WIFI_P2P_CONNECTION_CHANGED_ACTION
|
Trasmetti quando lo stato della connessione Wi-Fi del dispositivo cambia. |
WIFI_P2P_PEERS_CHANGED_ACTION
|
Trasmetti quando chiami discoverPeers() . In genere,
chiamerai requestPeers() per ricevere un elenco aggiornato di peer se
gestisci questo intent nella tua applicazione.
|
WIFI_P2P_STATE_CHANGED_ACTION
|
Consente di trasmettere quando il Wi-Fi P2P è attivato o disattivato sul dispositivo. |
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
|
Trasmetti quando i dettagli di un dispositivo vengono modificati, ad esempio il nome del dispositivo. |
Creazione di un ricevitore di trasmissione per intent Wi-Fi P2P
Un ricevitore consente di ricevere intent trasmessi dal sistema Android, in modo che la tua applicazione possa rispondere agli eventi che ti interessano. I passaggi di base per la creazione di un ricevitore di trasmissione per gestire gli intent Wi-Fi P2P sono i seguenti:
Crea una classe che estenda la classe
BroadcastReceiver
. Per il costruttore della classe, utilizzerai i parametri perWifiP2pManager
,WifiP2pManager.Channel
e l'attività in cui verrà registrato questo ricevitore della trasmissione. Ciò consente al ricevitore della trasmissione di inviare aggiornamenti dell'attività e di accedere all'hardware Wi-Fi e a un canale di comunicazione, se necessario.Nel ricevitore della trasmissione, controlla gli intent che ti interessano utilizzando il metodo
onReceive()
. Eseguire eventuali azioni necessarie in base all'intent ricevuto. Ad esempio, se il ricevitore della trasmissione riceve un intentWIFI_P2P_PEERS_CHANGED_ACTION
, puoi chiamare il metodorequestPeers()
per ottenere un elenco dei peer attualmente rilevati.
Il seguente codice mostra come creare un tipico ricevitore di trasmissione. Il ricevitore di broadcast prende un oggetto WifiP2pManager
e un'attività come argomenti e utilizza queste due classi per eseguire in modo appropriato le azioni necessarie quando il ricevitore della trasmissione riceve un intent:
Kotlin
/** * A BroadcastReceiver that notifies of important Wi-Fi p2p events. */ class WiFiDirectBroadcastReceiver( private val manager: WifiP2pManager, private val channel: WifiP2pManager.Channel, private val activity: MyWifiActivity ) : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action: String = intent.action when (action) { WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION -> { // Check to see if Wi-Fi is enabled and notify appropriate activity } WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION -> { // Call WifiP2pManager.requestPeers() to get a list of current peers } WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION -> { // Respond to new connection or disconnections } WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION -> { // Respond to this device's wifi state changing } } } }
Java
/** * 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 } } }
Sui dispositivi con Android 10 e versioni successive, i seguenti intent di trasmissione non sono persistenti:
WIFI_P2P_CONNECTION_CHANGED_ACTION
- Le applicazioni possono usare
requestConnectionInfo()
,requestNetworkInfo()
orequestGroupInfo()
per recuperare le informazioni sulla connessione attuale. WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
- Le applicazioni possono utilizzare
requestDeviceInfo()
per recuperare le informazioni sulla connessione corrente.
Creazione di un'applicazione P2P Wi-Fi
La creazione di un'applicazione P2P Wi-Fi comporta la creazione e la registrazione di un ricevitore broadcast per l'applicazione, il rilevamento di peer, la connessione a un peer e il trasferimento di dati a un peer. Nelle sezioni seguenti viene descritto come eseguire questa operazione.
Configurazione iniziale
Prima di utilizzare le API Wi-Fi P2P, devi assicurarti che l'applicazione possa accedere all'hardware e che il dispositivo supporti il protocollo Wi-Fi P2P. Se è supportato il protocollo Wi-Fi P2P, puoi ottenere un'istanza di WifiP2pManager
, creare e registrare il ricevitore di trasmissione e iniziare a utilizzare le API Wi-Fi P2P.
Richiedi l'autorizzazione per utilizzare l'hardware Wi-Fi sul dispositivo e dichiara che la tua applicazione dispone della versione minima corretta dell'SDK nel file manifest Android:
<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" /> <!-- If your app targets Android 13 (API level 33) or higher, you must declare the NEARBY_WIFI_DEVICES permission. --> <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" <!-- If your app derives location information from Wi-Fi APIs, don't include the "usesPermissionFlags" attribute. --> android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" <!-- If any feature in your app relies on precise location information, don't include the "maxSdkVersion" attribute. --> android:maxSdkVersion="32" />
Oltre alle autorizzazioni precedenti, le API seguenti richiedono anche l'attivazione della modalità di geolocalizzazione:
Verifica se il Wi-Fi P2P è attivo e supportato. Puoi verificarlo nel ricevitore della trasmissione quando riceve l'intent
WIFI_P2P_STATE_CHANGED_ACTION
. Avvisa la tua attività relativa allo stato del Wi-Fi P2P e reagisci di conseguenza:Kotlin
override fun onReceive(context: Context, intent: Intent) { ... val action: String = intent.action when (action) { WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION -> { val state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1) when (state) { WifiP2pManager.WIFI_P2P_STATE_ENABLED -> { // Wifi P2P is enabled } else -> { // Wi-Fi P2P is not enabled } } } } ... }
Java
@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 P2P is enabled } else { // Wi-Fi P2P is not enabled } } ... }
Nel metodo
onCreate()
della tua attività, ottieni un'istanza diWifiP2pManager
e registra la tua applicazione nel framework Wi-Fi P2P chiamandoinitialize()
. Questo metodo restituisce un valoreWifiP2pManager.Channel
, che viene utilizzato per connettere la tua applicazione al framework P2P Wi-Fi. Devi inoltre creare un'istanza del ricevitore di broadcast con gli oggettiWifiP2pManager
eWifiP2pManager.Channel
insieme a un riferimento alla tua attività. In questo modo il ricevitore della trasmissione può avvisare la tua attività di eventi interessanti e aggiornarla di conseguenza. Consente inoltre di modificare lo stato della rete Wi-Fi del dispositivo se necessario:Kotlin
val manager: WifiP2pManager? by lazy(LazyThreadSafetyMode.NONE) { getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager? } var channel: WifiP2pManager.Channel? = null var receiver: BroadcastReceiver? = null override fun onCreate(savedInstanceState: Bundle?) { ... channel = manager?.initialize(this, mainLooper, null) channel?.also { channel -> receiver = WiFiDirectBroadcastReceiver(manager, channel, this) } }
Java
WifiP2pManager manager; Channel channel; BroadcastReceiver receiver; ... @Override protected void onCreate(Bundle savedInstanceState){ ... manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); channel = manager.initialize(this, getMainLooper(), null); receiver = new WiFiDirectBroadcastReceiver(manager, channel, this); ... }
Crea un filtro per intent e aggiungi gli stessi intent controllati dal ricevitore della trasmissione:
Kotlin
val intentFilter = IntentFilter().apply { addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION) addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION) addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION) addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION) }
Java
IntentFilter intentFilter; ... @Override protected void onCreate(Bundle savedInstanceState){ ... intentFilter = new IntentFilter(); 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); ... }
Registra il ricevitore della trasmissione nel metodo
onResume()
della tua attività e annulla la registrazione nel metodoonPause()
della tua attività:Kotlin
/* register the broadcast receiver with the intent values to be matched */ override fun onResume() { super.onResume() receiver?.also { receiver -> registerReceiver(receiver, intentFilter) } } /* unregister the broadcast receiver */ override fun onPause() { super.onPause() receiver?.also { receiver -> unregisterReceiver(receiver) } }
Java
/* 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); }
Dopo aver acquistato un dispositivo
WifiP2pManager.Channel
e configurato un ricevitore trasmesso, la tua applicazione può effettuare chiamate di metodo Wi-Fi P2P e ricevere intent Wi-Fi P2P.Implementa l'applicazione utilizzando le funzionalità di P2P Wi-Fi chiamando i metodi in
WifiP2pManager
.
Le sezioni successive descrivono come eseguire le azioni più comuni, come scoprire e connettersi con i peer.
Scopri colleghi
Chiama discoverPeers()
per rilevare i peer disponibili che si trovano nel raggio d'azione e disponibili per la connessione. La chiamata a questa funzione è asincrona e l'esito positivo o negativo viene comunicato all'applicazione tramite onSuccess()
e onFailure()
se hai creato un WifiP2pManager.ActionListener
. Il metodo onSuccess()
indica solo che il processo di rilevamento è riuscito e non fornisce
informazioni sui peer effettivi che ha rilevato, se presenti. Il seguente esempio di codice mostra come eseguire la configurazione.
Kotlin
manager?.discoverPeers(channel, object : WifiP2pManager.ActionListener { override fun onSuccess() { ... } override fun onFailure(reasonCode: Int) { ... } })
Java
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { ... } @Override public void onFailure(int reasonCode) { ... } });
Se il processo di rilevamento ha esito positivo e rileva i peer, il sistema trasmette l'intent WIFI_P2P_PEERS_CHANGED_ACTION
, che puoi ascoltare in un ricevitore broadcast per ottenere un elenco di peer. Quando l'applicazione riceve l'intent WIFI_P2P_PEERS_CHANGED_ACTION
, puoi richiedere un elenco dei peer rilevati con requestPeers()
. Il seguente codice mostra come eseguire la configurazione.
Kotlin
override fun onReceive(context: Context, intent: Intent) { val action: String = intent.action when (action) { ... WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION -> { manager?.requestPeers(channel) { peers: WifiP2pDeviceList? -> // Handle peers list } } ... } }
Java
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); } }
Anche il metodo requestPeers()
è asincrono e può inviare una notifica alla tua attività quando è disponibile un elenco di peer con onPeersAvailable()
, definito nell'interfaccia WifiP2pManager.PeerListListener
. Il metodo onPeersAvailable()
fornisce un WifiP2pDeviceList
, che puoi eseguire l'iterazione per trovare il peer a cui connetterti.
Connettiti con i tuoi colleghi
Dopo aver ottenuto un elenco di possibili peer e selezionato un dispositivo a cui connetterti, chiama il metodo connect()
per connetterti al dispositivo. Questa chiamata al metodo richiede un oggetto WifiP2pConfig
contenente informazioni sul dispositivo a cui connettersi.
WifiP2pManager.ActionListener
può informarti di una connessione riuscita o
non riuscita. Il seguente codice mostra come creare una connessione a un dispositivo.
Kotlin
val device: WifiP2pDevice = ... val config = WifiP2pConfig() config.deviceAddress = device.deviceAddress channel?.also { channel -> manager?.connect(channel, config, object : WifiP2pManager.ActionListener { override fun onSuccess() { //success logic } override fun onFailure(reason: Int) { //failure logic } } )}
Java
//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 } });
Trasferire dati
Una volta stabilita una connessione, puoi trasferire i dati tra i dispositivi con socket. I passaggi di base per il trasferimento dei dati sono i seguenti:
- Crea una
ServerSocket
. Questo socket attende una connessione da un client su una porta specificata e si blocca fino a quando non si verifica, quindi esegui questa operazione in un thread in background. - Crea un client
Socket
. Il client utilizza l'indirizzo IP e la porta del socket del server per connettersi al dispositivo server. - Invia i dati dal client al server. Quando il socket client si connette correttamente al socket del server, puoi inviare dati dal client al server con flussi di byte.
- Il socket del server attende una connessione client (con il metodo
accept()
). Questa chiamata si blocca finché un client non si connette, quindi chiamala in un altro thread. Quando si verifica una connessione, il dispositivo server può ricevere i dati dal client.
L'esempio seguente, modificato dalla Demo Wi-Fi P2P, mostra come creare questa comunicazione socket client-server e trasferire immagini JPEG da un client a un server con un servizio. Per un esempio funzionante completo, compila ed esegui la demo.
Kotlin
class FileServerAsyncTask( private val context: Context, private var statusText: TextView ) : AsyncTask<Void, Void, String?>() { override fun doInBackground(vararg params: Void): String? { /** * Create a server socket. */ val serverSocket = ServerSocket(8888) return serverSocket.use { /** * Wait for client connections. This call blocks until a * connection is accepted from a client. */ val 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 */ val f = File(Environment.getExternalStorageDirectory().absolutePath + "/${context.packageName}/wifip2pshared-${System.currentTimeMillis()}.jpg") val dirs = File(f.parent) dirs.takeIf { it.doesNotExist() }?.apply { mkdirs() } f.createNewFile() val inputstream = client.getInputStream() copyFile(inputstream, FileOutputStream(f)) serverSocket.close() f.absolutePath } } private fun File.doesNotExist(): Boolean = !exists() /** * Start activity that can handle the JPEG image */ override fun onPostExecute(result: String?) { result?.run { statusText.text = "File copied - $result" val intent = Intent(android.content.Intent.ACTION_VIEW).apply { setDataAndType(Uri.parse("file://$result"), "image/*") } context.startActivity(intent) } } }
Java
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); } } }
Sul client, collegati al socket del server con un socket client e trasferisci i dati. In questo esempio viene trasferito un file JPEG nel file system del dispositivo client.
Kotlin
val context = applicationContext val host: String val port: Int val len: Int val socket = Socket() val buf = ByteArray(1024) ... try { /** * Create a client socket with the host, * port, and timeout information. */ socket.bind(null) socket.connect((InetSocketAddress(host, port)), 500) /** * Create a byte stream from a JPEG file and pipe it to the output stream * of the socket. This data is retrieved by the server device. */ val outputStream = socket.getOutputStream() val cr = context.contentResolver val inputStream: InputStream = cr.openInputStream(Uri.parse("path/to/picture.jpg")) while (inputStream.read(buf).also { len = it } != -1) { outputStream.write(buf, 0, len) } outputStream.close() inputStream.close() } catch (e: FileNotFoundException) { //catch logic } catch (e: IOException) { //catch logic } finally { /** * Clean up any open sockets when done * transferring or if an exception occurred. */ socket.takeIf { it.isConnected }?.apply { close() } }
Java
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 is 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 } } } }