Wi-Fi Direct (P2P) umożliwia urządzeniom z odpowiednim sprzętem łączenie się bezpośrednio ze sobą przez Wi-Fi bez pośredniego punktu dostępu. Te interfejsy API pozwalają na wykrywanie innych urządzeń i łączenie się z nimi, jeśli każde z nich obsługuje sieć Wi-Fi P2P, a następnie komunikowanie się przez szybkie łącze na odległość dużo 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 czy aplikacjach do udostępniania zdjęć.
Interfejsy Wi-Fi API P2P składają się z tych głównych elementów:
- Metody, które umożliwiają wykrywanie elementów równorzędnych, wysyłanie do nich żądań i łączenie się z nimi, które są zdefiniowane w klasie
WifiP2pManager
. - Detektory, które umożliwiają otrzymywanie powiadomień o udanej lub nieudanej próbie wywołania metody
WifiP2pManager
. Przy wywoływaniu metodWifiP2pManager
każda metoda może otrzymać określony odbiornik przekazany jako parametr. - Intencje powiadamiające o konkretnych zdarzeniach wykrytych przez platformę P2P sieci Wi-Fi, takich jak utrata połączenia lub nowo wykryte połączenie równorzędne.
Te 3 główne komponenty interfejsów API często są używane razem. Możesz na przykład podać WifiP2pManager.ActionListener
wywołania discoverPeers()
, aby metody ActionListener.onSuccess()
i ActionListener.onFailure()
mogły Cię powiadomić. Zamiar WIFI_P2P_PEERS_CHANGED_ACTION
jest też przesyłany, gdy metoda discoverPeers()
wykryje, że lista podobnych reklamodawców się zmieniła.
Omówienie interfejsu API
Klasa WifiP2pManager
udostępnia metody, które umożliwiają interakcję ze sprzętem Wi-Fi Twojego urządzenia i na przykład wykrywanie sieci równorzędnych i łączenie się z nimi.
Dostępne są te opcje:
Tabela 1. Metody P2P sieci Wi-Fi
Metoda | Description |
initialize()
|
Rejestruje aplikację za pomocą platformy Wi-Fi. Wywołaj to przed wywołaniem dowolnej innej metody P2P sieci Wi-Fi. |
connect()
|
Rozpoczyna połączenie peer-to-peer z urządzeniem o określonej konfiguracji. |
cancelConnect()
|
Anuluje trwające negocjacje w grupie peer-to-peer. |
requestConnectInfo()
|
Żąda informacji o połączeniu z urządzeniem. |
createGroup()
|
Tworzy grupę peer-to-peer z obecnym urządzeniem jako właścicielem grupy. |
removeGroup()
|
Usuwa bieżącą grupę peer-to-peer. |
requestGroupInfo()
|
Wysyła żądanie informacji o grupie peer-to-peer. |
discoverPeers()
|
Inicjuje badanie porównawcze. |
requestPeers()
|
Wysyła żądanie udostępnienia bieżącej listy wykrytych elementów równorzędnych. |
Metody WifiP2pManager
umożliwiają przekazywanie przez odbiornik, dzięki czemu platforma P2P sieci Wi-Fi może powiadamiać Twoją aktywność o stanie połączenia. Dostępne interfejsy nasłuchiwania i odpowiadające im wywołania metody WifiP2pManager
, które korzystają z detektorów, zostały opisane w tabeli 2.
Tabela 2. Detektory P2P sieci Wi-Fi
Interfejs detektora | 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 P2P API definiują intencje, które są transmitowane, gdy występują określone zdarzenia P2P sieci Wi-Fi, np. gdy zostaje wykryte nowe połączenie równorzędne lub zmiana stanu sieci Wi-Fi urządzenia. Możesz zarejestrować się, aby otrzymywać te intencje w swojej aplikacji, tworząc odbiornik, który obsługuje te intencje:
Tabela 3. Intencje P2P sieci Wi-Fi
Zamiar | Description |
WIFI_P2P_CONNECTION_CHANGED_ACTION
|
Transmituj w przypadku zmiany stanu połączenia Wi-Fi na urządzeniu. |
WIFI_P2P_PEERS_CHANGED_ACTION
|
Przesyłaj, gdy dzwonisz do: discoverPeers() . Jeśli obsługujesz tę intencję w swojej aplikacji, zwykle wywołujesz requestPeers() , aby uzyskać zaktualizowaną listę połączeń równorzędnych.
|
WIFI_P2P_STATE_CHANGED_ACTION
|
Przesyłanie, gdy sieć Wi-Fi P2P jest włączona lub wyłączona na urządzeniu. |
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
|
Komunikaty po zmianie informacji o urządzeniu, np. jego nazwy. |
Tworzenie odbiornika dla intencji P2P sieci Wi-Fi
Odbiornik umożliwia odbieranie intencji przesyłanych przez system Android, dzięki czemu aplikacja może reagować na zdarzenia, które Cię interesują. Oto podstawowe czynności, które należy wykonać, aby utworzyć odbiornik transmisji do obsługi intencji P2P sieci Wi-Fi:
Utwórz klasę, która stanowi rozszerzenie klasy
BroadcastReceiver
. W konstruktorze klasy użyjesz parametrówWifiP2pManager
iWifiP2pManager.Channel
oraz działania, w którym zostanie zarejestrowany odbiornik. Dzięki temu odbiornik może wysyłać aktualizacje aktywności oraz w razie potrzeby mieć dostęp do sprzętu Wi-Fi i kanału komunikacyjnego.W odbiorniku sprawdź intencje, które Cię interesują w metodzie
onReceive()
. Wykonaj odpowiednie działania w zależności od otrzymanej intencji. Jeśli na przykład odbiornik otrzymuje intencjęWIFI_P2P_PEERS_CHANGED_ACTION
, możesz wywołać metodęrequestPeers()
, aby uzyskać listę aktualnie wykrytych elementów równorzędnych.
Poniższy kod pokazuje, jak utworzyć typowego odbiornika. Odbiornik wykorzystuje WifiP2pManager
obiekt i działanie jako argumenty, a następnie używa tych 2 klas do odpowiedniego wykonania wymaganych działań, gdy odbiornik otrzyma 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
- Do pobierania bieżących informacji o połączeniu aplikacje mogą używać poleceń
requestConnectionInfo()
,requestNetworkInfo()
lubrequestGroupInfo()
. WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
- Aplikacje mogą pobierać bieżące informacje o połączeniu za pomocą
requestDeviceInfo()
.
Utwórz aplikację P2P sieci Wi-Fi
Utworzenie aplikacji P2P sieci Wi-Fi obejmuje utworzenie i zarejestrowanie odbiornika transmisji dla aplikacji, odnajdywanie sieci równorzędnych, nawiązanie połączenia z peerem i przesłanie danych do niego. W sekcjach poniżej opisujemy, jak to zrobić.
Konfiguracja początkowa
Przed skorzystaniem z interfejsów Wi-Fi API P2P upewnij się, że aplikacja ma dostęp do sprzętu, a urządzenie obsługuje protokół P2P sieci Wi-Fi. Jeśli sieć Wi-Fi P2P jest obsługiwana, możesz uzyskać instancję WifiP2pManager
, utworzyć i zarejestrować odbiornik, a potem zacząć korzystać z interfejsów Wi-Fi P2P API.
Poproś o pozwolenie na korzystanie ze sprzętu Wi-Fi na urządzeniu i zadeklaruj, że Twoja aplikacja ma w pliku manifestu Androida prawidłową minimalną wersję pakietu SDK:
<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ń następujące interfejsy API wymagają również włączenia trybu lokalizacji:
Sprawdź, czy sieć Wi-Fi P2P jest włączona i obsługiwana. Dobrze jest to sprawdzić w odbiorniku, gdy otrzymuje intencję
WIFI_P2P_STATE_CHANGED_ACTION
. Powiadamiaj o stanie połączenia Wi-Fi o stanie P2P i odpowiednio zareaguj: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 wystąpienieWifiP2pManager
i zarejestruj aplikację w platformie P2P Wi-Fi, wywołującinitialize()
. Ta metoda zwraca kodWifiP2pManager.Channel
, który służy do połączenia aplikacji z platformą P2P sieci Wi-Fi. Utwórz też instancję odbiornika z obiektamiWifiP2pManager
iWifiP2pManager.Channel
wraz z odniesieniem do swojej aktywności. Dzięki temu odbiornik będzie mógł powiadomić Cię o interesujących wydarzeniach i odpowiednio je zaktualizować. W razie potrzeby możesz też zmieniać stan 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, korzystając z metody
onResume()
swojej aktywności, i wyrejestruj go, korzystając z metodyonPause()
: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 masz urządzenie
WifiP2pManager.Channel
i skonfigurujesz odbiornik, aplikacja może wykonywać połączenia P2P przez Wi-Fi i odbierać intencje P2P Wi-Fi.Zaimplementuj swoją aplikację, korzystając z funkcji P2P sieci Wi-Fi, wywołując te metody w komponencie
WifiP2pManager
.
W następnych sekcjach opisujemy, jak wykonywać typowe działania, takie jak odkrywanie aplikacji z grupy porównawczej i nawiązywanie z nimi więzi.
Odkryj aplikacje z grupy porównawczej
Wywołaj discoverPeers()
, aby wykryć dostępnych peerów, którzy są w zasięgu i mogą się z nim połączyć. Wywołanie tej funkcji jest asynchroniczne, a o powodzenie lub niepowodzenie są przekazywane do aplikacji za pomocą funkcji onSuccess()
i onFailure()
, jeśli utworzono WifiP2pManager.ActionListener
. Metoda onSuccess()
informuje tylko o pomyślnym procesie wykrywania i nie dostarcza żadnych informacji o elementach równorzędnych, które wykryła. 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 peera, system przekaże intencję WIFI_P2P_PEERS_CHANGED_ACTION
, której można nasłuchiwać w odbiorniku, aby uzyskać listę innych aplikacji. Gdy aplikacja otrzyma intencję WIFI_P2P_PEERS_CHANGED_ACTION
, możesz poprosić o listę wykrytych elementów równorzędnych za pomocą requestPeers()
. Poniższy kod pokazuje, jak to zrobić.
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()
również jest asynchroniczna i może powiadamiać działanie użytkownika o dostępności listy połączeń równorzędnych w onPeersAvailable()
, która jest definiowana w interfejsie WifiP2pManager.PeerListListener
. Metoda onPeersAvailable()
udostępnia WifiP2pDeviceList
, który można wielokrotnie przeglądać, aby znaleźć peera, z którym chcesz się połączyć.
Połącz się z grupą porównawczą
Po uzyskaniu listy możliwych peerów i wybraniu urządzenia, z którym chcesz się połączyć, wywołaj metodę connect()
, aby połączyć się z urządzeniem. To wywołanie metody wymaga obiektu WifiP2pConfig
zawierającego informacje o urządzeniu, z którym ma zostać nawiązane połączenie.
WifiP2pManager.ActionListener
może powiadomić Cię o udanym lub nieudanym nawiązaniu połączenia. Poniższy kod pokazuje, 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 etapy przenoszenia danych:
- Utwórz
ServerSocket
. To gniazdo oczekuje na połączenie od klienta przez określony port i blokuje się, dopóki nie nastąpi. Zrób to w wątku w tle. - Utwórz klienta
Socket
. Klient łączy się z urządzeniem serwera za pomocą adresu IP i portu gniazda serwera. - Wysyłanie danych klienta na serwer. Gdy gniazdo klienta połączy się z gniazdem serwera, będzie można wysyłać dane od klienta do serwera za pomocą strumieni bajtów.
- Gniazdo serwera oczekuje na połączenie z klientem (w metodzie
accept()
). To wywołanie jest blokowane do czasu, gdy klient się połączy, więc wywołaj je w innym wątku. Po nawiązaniu połączenia serwer może odebrać dane od klienta.
Poniższy przykład, zmodyfikowany na podstawie demonstracji P2P sieci Wi-Fi, pokazuje, jak utworzyć komunikację typu klient-serwer i jak przesłać obrazy JPEG z klienta na serwer z usługą. Aby uzyskać pełny przykład działania, 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); } } }
Po stronie klienta połącz się z gniazdem serwera przez gniazdo klienta i przenieś dane. W tym przykładzie przesyła się plik JPEG w systemie 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 } } } }