Wi-Fi Direct (P2P) pozwala urządzeniom z odpowiednim sprzętem łączyć się ze sobą bezpośrednio przez Wi-Fi bez pośredniego punktu dostępu. Dzięki tym interfejsom API możesz wykrywać inne urządzenia i łączyć się z nimi, gdy każde z nich obsługuje Wi-Fi P2P, a następnie komunikować się za pomocą szybkiego połączenia na odległość znacznie większą niż w przypadku połączenia Bluetooth. Przydaje się to w aplikacjach, które udostępniają dane między użytkownikami, np. w grach wieloosobowych lub aplikacjach do udostępniania zdjęć.
Interfejsy API sieci Wi-Fi P2P składają się z tych głównych części:
- Metody umożliwiające wykrywanie połączeń równorzędnych, wysyłanie żądań dotyczących ich i łączenie się z nimi, które są zdefiniowane w klasie
WifiP2pManager
. - Detektory, które pozwalają otrzymywać powiadomienia o udanych lub nieudanych wywołaniach metod
WifiP2pManager
. Gdy wywołują metodyWifiP2pManager
, każda z nich może otrzymywać określony detektor przekazywany jako parametr. - Intencje powiadamiające o konkretnych zdarzeniach wykrytych przez strukturę P2P sieci Wi-Fi, takich jak utrata połączenia lub nowo wykryte połączenie równorzędne.
Tych 3 głównych komponentów interfejsów API często używa się razem. Możesz na przykład dodać WifiP2pManager.ActionListener
do wywołania discoverPeers()
, aby metody ActionListener.onSuccess()
i ActionListener.onFailure()
mogły Cię powiadomić. Intencja WIFI_P2P_PEERS_CHANGED_ACTION
jest też wysyłana, gdy metoda discoverPeers()
wykryje, że lista elementów porównawczych uległa zmianie.
Omówienie interfejsu API
Klasa WifiP2pManager
udostępnia metody, które umożliwiają korzystanie ze sprzętu Wi-Fi na urządzeniu w takich sytuacjach jak wykrywanie rówieśników i łączenie się z nimi.
Dostępne są te opcje:
Tabela 1. Metody Wi-Fi P2P
Metoda | Opis |
initialize()
|
Rejestruje aplikację w platformie Wi-Fi. Wywołaj go przed wywołaniem jakiejkolwiek innej metody P2P Wi-Fi. |
connect()
|
Uruchamia połączenie peer-to-peer z urządzeniem o określonej konfiguracji. |
cancelConnect()
|
Anuluje wszystkie trwające negocjacje typu „peer-to-peer”. |
requestConnectInfo()
|
Żąda informacji o połączeniu urządzenia. |
createGroup()
|
Tworzy grupę równorzędną, której właścicielem jest obecne urządzenie. |
removeGroup()
|
Usuwa bieżącą grupę równorzędną. |
requestGroupInfo()
|
Żąda informacji o grupie peer-to-peer. |
discoverPeers()
|
Rozpoczyna odkrywanie aplikacji równorzędnych. |
requestPeers()
|
Pyta o bieżącą listę wykrytych elementów równorzędnych. |
Metody WifiP2pManager
umożliwiają przekazanie detektora, dzięki czemu platforma P2P sieci Wi-Fi może powiadamiać Twoją aktywność o stanie wywołania. Dostępne interfejsy detektorów oraz odpowiadające im wywołania metod WifiP2pManager
, które używają detektorów, zostały opisane w tabeli 2.
Tabela 2. Detektory Wi-Fi P2P
Interfejs słuchacza | Powiązane działania |
WifiP2pManager.ActionListener
|
connect() , cancelConnect() , createGroup() , removeGroup() i discoverPeers()
|
WifiP2pManager.ChannelListener
|
initialize()
|
WifiP2pManager.ConnectionInfoListener
|
requestConnectInfo()
|
WifiP2pManager.GroupInfoListener
|
requestGroupInfo()
|
WifiP2pManager.PeerListListener
|
requestPeers()
|
Interfejsy Wi-Fi API P2P definiują intencje, które są transmitowane po wystąpieniu określonych zdarzeń Wi-Fi P2P, na przykład po wykryciu nowego połączenia równorzędnego lub zmianie stanu połączenia Wi-Fi urządzenia. Aby zarejestrować się do otrzymywania tych intencji w aplikacji, utwórz odbiornik, który obsługuje te intencje:
Tabela 3. Intencje P2P w sieci Wi-Fi
Zamiar | Opis |
WIFI_P2P_CONNECTION_CHANGED_ACTION
|
Rozgłaszaj po zmianie stanu połączenia Wi-Fi na urządzeniu. |
WIFI_P2P_PEERS_CHANGED_ACTION
|
Przesyłaj powiadomienia, gdy dzwonisz pod numer discoverPeers() . Jeśli obsługujesz tę intencję w aplikacji, zwykle wywołujesz requestPeers() , aby uzyskać zaktualizowaną listę elementów równorzędnych.
|
WIFI_P2P_STATE_CHANGED_ACTION
|
Przesyłaj, gdy na urządzeniu jest włączona lub wyłączona sieć Wi-Fi P2P. |
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
|
Wysyłaj po zmianie szczegółów urządzenia (np. jego nazwy). |
Utwórz odbiornik dla intencji Wi-Fi P2P
Odbiornik transmisji umożliwia odbieranie intencji transmitowanych przez system Android, dzięki czemu aplikacja może odpowiadać na zdarzenia, które Cię interesują. Podstawowe kroki, które trzeba wykonać, by utworzyć odbiornik do obsługi intencji P2P sieci Wi-Fi:
Utwórz klasę, która rozszerza klasę
BroadcastReceiver
. W konstruktorze klasy użyjesz parametrówWifiP2pManager
iWifiP2pManager.Channel
oraz działania, w którym ten odbiornik będzie zarejestrowany. Dzięki temu odbiornik może wysyłać aktualizacje o aktywności, a w razie potrzeby mieć dostęp do sprzętu Wi-Fi i kanału komunikacyjnego.W odbiorniku wybierz interesujące Cię intencje w przypadku metody
onReceive()
. Wykonaj odpowiednie działania zależnie od otrzymanej intencji. Jeśli na przykład odbiornik odbiera intencjęWIFI_P2P_PEERS_CHANGED_ACTION
, możesz wywołać metodęrequestPeers()
, by uzyskać listę obecnie wykrytych elementów równorzędnych.
Poniższy kod pokazuje, jak utworzyć typowy odbiornik. Odbiornik sygnału przyjmuje obiekt WifiP2pManager
i działanie jako argumenty, a potem używa tych 2 klas do odpowiedniego wykonywania niezbędnych działań, gdy odbiornik odbiera intencję:
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 } } }
Na urządzeniach z Androidem 10 lub nowszym te intencje przesyłania nie są przyklejone:
WIFI_P2P_CONNECTION_CHANGED_ACTION
- Aplikacje mogą pobierać informacje o bieżącym połączeniu za pomocą
requestConnectionInfo()
,requestNetworkInfo()
lubrequestGroupInfo()
. WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
- Aplikacje mogą używać
requestDeviceInfo()
do pobierania bieżących informacji o połączeniu.
Utwórz aplikację Wi-Fi P2P
Utworzenie aplikacji Wi-Fi P2P obejmuje utworzenie i zarejestrowanie odbiornika dla aplikacji, wykrycie peera, nawiązanie połączenia z peerem i przesłanie do niego danych. Jak to zrobić, dowiesz się w sekcjach poniżej.
Konfiguracja początkowa
Przed użyciem interfejsów API sieci Wi-Fi P2P upewnij się, że aplikacja ma dostęp do sprzętu, a urządzenie obsługuje protokół Wi-Fi P2P. Jeśli sieć Wi-Fi P2P jest obsługiwana, możesz uzyskać instancję WifiP2pManager
, utworzyć i zarejestrować odbiornik, a następnie zacząć korzystać z interfejsów API sieci Wi-Fi P2P.
Poproś o pozwolenie na korzystanie ze sprzętu Wi-Fi na urządzeniu i zadeklaruj, że aplikacja ma prawidłową minimalną wersję pakietu SDK w pliku manifestu Androida:
<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" />
Oprócz poprzednich uprawnień te interfejsy API wymagają też włączenia trybu lokalizacji:
Sprawdź, czy sieć Wi-Fi P2P jest włączona i obsługiwana. Możesz to sprawdzić w odbiorniku, gdy otrzyma intencję
WIFI_P2P_STATE_CHANGED_ACTION
. Powiadomi Cię o aktywności stanu P2P sieci Wi-Fi i zareaguj odpowiednio: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 } } ... }
W metodzie
onCreate()
aktywności uzyskaj instancjęWifiP2pManager
i zarejestruj aplikację za pomocą platformy Wi-Fi P2P, wywołującinitialize()
. Ta metoda zwracaWifiP2pManager.Channel
, który służy do połączenia aplikacji ze platformą Wi-Fi P2P. Należy też utworzyć instancję odbiornika z obiektamiWifiP2pManager
iWifiP2pManager.Channel
wraz z odwołaniem do Twojej aktywności. Dzięki temu Twój odbiornik będzie mógł powiadamiać Cię o interesujących wydarzeniach i odpowiednio aktualizować te informacje. W razie potrzeby umożliwia też manipulowanie stanem Wi-Fi urządzenia: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); ... }
Utwórz filtr intencji i dodaj te same intencje, które sprawdza odbiornik:
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); ... }
Zarejestruj odbiornik w metodzie
onResume()
swojej aktywności i wyrejestruj go w metodzieonPause()
swojej aktywności: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); }
Gdy otrzymasz
WifiP2pManager.Channel
i skonfigurujesz odbiornik, aplikacja będzie mogła nawiązywać połączenia metodą P2P Wi-Fi i odbierać intencje Wi-Fi.Wdróż aplikację, korzystając z funkcji Wi-Fi P2P, wywołując te metody w
WifiP2pManager
.
W kolejnych sekcjach dowiesz się, jak wykonywać typowe czynności, takie jak znajdowanie elementów równorzędnych i łączenie się z nimi.
Znajdź aplikacje z grupy porównawczej
Wywołaj discoverPeers()
, aby wykryć dostępne połączenia równorzędne, które znajdują się w zasięgu i można nawiązać połączenie. Wywołanie tej funkcji jest asynchroniczne, a o sukcesie lub niepowodzeniu aplikacji za pomocą funkcji onSuccess()
i onFailure()
, jeśli został utworzony WifiP2pManager.ActionListener
. Metoda onSuccess()
informuje tylko o tym, że proces wykrywania się udał, i nie zawiera żadnych informacji o wykrytych elementach równorzędnych (jeśli takie wystąpiły). Poniższy przykładowy kod pokazuje, jak to skonfigurować.
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) { ... } });
Jeśli proces wykrywania się powiedzie i wykryje elementy równorzędne, system rozgłasza intencję WIFI_P2P_PEERS_CHANGED_ACTION
, której możesz nasłuchiwać w odbiorniku, aby uzyskać listę takich elementów. Gdy aplikacja otrzyma intencję WIFI_P2P_PEERS_CHANGED_ACTION
, możesz zażądać listy wykrytych elementów równorzędnych za pomocą requestPeers()
. Poniższy kod pokazuje, jak to skonfigurować.
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); } }
Metoda requestPeers()
jest też asynchroniczna i może powiadamiać Twoją aktywność o dostępności listy elementów równorzędnych za pomocą funkcji onPeersAvailable()
zdefiniowanej w interfejsie WifiP2pManager.PeerListListener
. Metoda onPeersAvailable()
udostępnia tabelę WifiP2pDeviceList
, którą możesz iterować, aby znaleźć element równorzędny, z którym chcesz się połączyć.
Połącz się z innymi wydawcami
Po uzyskaniu listy możliwych elementów równorzędnych i wybraniu urządzenia, z którym chcesz się połączyć, wywołaj metodę connect()
, aby nawiązać połączenie. To wywołanie metody wymaga obiektu WifiP2pConfig
zawierającego informacje o urządzeniu, z którym ma się połączyć.
WifiP2pManager.ActionListener
może powiadamiać Cię o udanej lub nieudanej próbie połączenia. Ten kod ilustruje, jak utworzyć połączenie z urządzeniem.
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 } });
Przenoszenie danych
Po nawiązaniu połączenia będzie można przesyłać dane między urządzeniami z gniazdkami. Podstawowe kroki przenoszenia danych:
- Utwórz
ServerSocket
. To gniazdo czeka na połączenie z klientem na określonym porcie i blokuje, dopóki nie wystąpi, więc zrób to w wątku w tle. - Utwórz klienta
Socket
. Klient łączy się z serwerem przy użyciu adresu IP i portu gniazda serwera. - Wysyłanie danych z klienta na serwer. Gdy gniazdo klienta połączy się z gniazdem serwera, możesz wysyłać dane z klienta do serwera za pomocą strumieni bajtów.
- Gniazdo serwera czeka na połączenie z klientem (w przypadku metody
accept()
). To wywołanie blokuje się do czasu połączenia z klientem, więc wywołaj je w innym wątku. W przypadku połączenia serwer może odebrać dane od klienta.
Poniższy przykład, modyfikowany na podstawie prezentacji Wi-Fi P2P, pokazuje, jak utworzyć komunikację typu klient-serwer i przesłać obrazy JPEG z klienta na serwer z usługą. Aby uzyskać pełny przykład, skompiluj i uruchom wersję demonstracyjną.
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); } } }
Na kliencie połącz się z gniazdem serwera za pomocą tego gniazda i prześlij dane. W tym przykładzie plik JPEG zostanie przesłany do systemu plików urządzenia klienckiego.
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 } } } }