Wi-Fi Direct(P2P) 개요

Wi-Fi Direct (P2P)를 사용하면 적절한 하드웨어가 있는 기기를 각 기기에 직접 연결할 수 있습니다. 중간 액세스 포인트 없이 Wi-Fi를 통해 다른 네트워크에 전송할 수 있습니다. 이러한 API를 사용하면 각 기기가 Wi-Fi P2P를 지원할 때 다른 장치를 검색하고 연결한 다음 다른 컴퓨터보다 훨씬 긴 거리를 두고 빠른 연결을 통해 통신할 수 있습니다 Bluetooth 연결 이는 여러 애플리케이션 간에 데이터를 공유하는 애플리케이션에 사진 공유 애플리케이션 등의 사용자를 대상으로 합니다.

Wi-Fi P2P API는 다음과 같은 주요 부분으로 구성됩니다.

  • 피어를 검색, 요청, 연결할 수 있게 해 주는 메서드인 에 정의된 WifiP2pManager 클래스
  • 애플리케이션의 성공 또는 실패를 알릴 수 있는 리스너 WifiP2pManager 메서드 호출 WifiP2pManager 메서드를 호출할 때는 각각 메서드는 매개변수로 전달된 특정 리스너를 수신할 수 있습니다.
  • Wi-Fi P2P에서 감지한 특정 이벤트를 사용자에게 알리는 인텐트 연결이 끊어졌거나 새로 발견된 피어와 같은 불명확한 상호 연결로 인해 발생할 수 있습니다.

API의 이러한 세 가지 주요 구성요소를 함께 사용하는 경우가 많습니다. 대상 예를 들어 WifiP2pManager.ActionListener 드림 통화를 discoverPeers() 이렇게 하면 ActionListener.onSuccess()ActionListener.onFailure() 메서드가 여러분에게 알릴 수 있습니다. 가 WIFI_P2P_PEERS_CHANGED_ACTION 드림 discoverPeers() 메서드가 동종 앱 목록이 변경되었습니다.

API 개요

WifiP2pManager 클래스는 개발자가 피어 검색 및 연결 등의 작업을 수행할 수 있는 기기의 Wi-Fi 하드웨어입니다. 다음과 같은 작업이 가능합니다.

표 1. Wi-Fi P2P 메서드

방법 설명
initialize() Wi-Fi 프레임워크로 애플리케이션을 등록합니다. 다음 날짜 이전에 호출 다른 Wi-Fi P2P 메서드를 호출할 수 없습니다.
connect() 지정된 구성이 있는 기기와 P2P 연결을 시작합니다.
cancelConnect() 모든 진행 중인 P2P 그룹 협상을 취소합니다.
requestConnectInfo() 기기의 연결 정보를 요청합니다.
createGroup() 현재 기기를 그룹 소유주로 하는 P2P 그룹을 생성합니다.
removeGroup() 현재 P2P 그룹을 삭제합니다.
requestGroupInfo() P2P 그룹 정보를 요청합니다.
discoverPeers() 피어 검색을 시작합니다.
requestPeers() 검색된 피어의 최신 목록을 요청합니다.

WifiP2pManager 메서드를 사용하면 Wi-Fi P2P 프레임워크가 확인할 수 있습니다. 사용 가능한 리스너 인터페이스와 해당하는 WifiP2pManager 메서드 호출 리스너 사용 방법은 표 2에 설명되어 있습니다.

표 2. Wi-Fi P2P 리스너

리스너 인터페이스 관련 작업
WifiP2pManager.ActionListener connect(), cancelConnect(), createGroup(), removeGroup(), discoverPeers()
WifiP2pManager.ChannelListener initialize()
WifiP2pManager.ConnectionInfoListener requestConnectInfo()
WifiP2pManager.GroupInfoListener requestGroupInfo()
WifiP2pManager.PeerListListener requestPeers()

Wi-Fi P2P API는 특정 Wi-Fi P2P 시에 브로드캐스트되는 인텐트를 정의합니다. 새 피어가 검색될 때 또는 기기의 Wi-Fi가 상태를 변경할 수 있습니다 다음 방법으로 애플리케이션에서 이러한 인텐트를 수신하도록 등록할 수 있습니다. broadcast receiver 만들기 는 이러한 인텐트를 처리하는 데 사용됩니다.

표 3. Wi-Fi P2P 인텐트

인텐트 설명
WIFI_P2P_CONNECTION_CHANGED_ACTION 기기의 Wi-Fi 연결 상태가 변경될 때 브로드캐스트합니다.
WIFI_P2P_PEERS_CHANGED_ACTION discoverPeers()를 호출할 때 브로드캐스트합니다. 일반적으로 다음과 같은 경우 requestPeers()를 호출하여 업데이트된 동종 앱 목록을 가져옵니다. 애플리케이션에서 이 인텐트를 처리할 수 있습니다.
WIFI_P2P_STATE_CHANGED_ACTION 기기에서 Wi-Fi P2P가 활성화되었거나 비활성화되었는지 브로드캐스트합니다.
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION 기기 이름과 같은 기기의 세부정보가 변경되면 브로드캐스트합니다.

Wi-Fi P2P 인텐트의 Broadcast Receiver 만들기

broadcast receiver를 통해 Android에서 브로드캐스트하는 인텐트를 수신할 수 있음 여러분의 애플리케이션이 관심 있는 이벤트에 대응할 수 있도록 인치 Wi-Fi P2P를 처리하기 위해 broadcast receiver를 만드는 기본 단계 인텐트는 다음과 같습니다.

  1. 다음 메서드를 확장하는 클래스를 만듭니다. BroadcastReceiver 클래스 수업용 WifiP2pManager의 매개변수를 사용합니다. WifiP2pManager.Channel 및 이 broadcast receiver에서 실행할 활동 등록할 수 있습니다. 이렇게 하면 broadcast receiver가 와이파이 하드웨어와 통신 시스템에 액세스할 수 있어야 합니다. 사용할 수 있습니다.

  2. broadcast receiver에서 관심 있는 인텐트 확인 를 onReceive() 드림 메서드를 사용하여 축소하도록 요청합니다. 실행하려는 인텐트에 따라 필요한 작업 실행 있습니다. 예를 들어 broadcast receiver가 WIFI_P2P_PEERS_CHANGED_ACTION 인텐트가 포함된 경우 requestPeers()를 호출할 수 있습니다. 메서드를 사용하여 현재 검색된 피어의 목록을 가져옵니다.

다음 코드는 일반적인 Broadcast Receiver를 생성하는 방법을 보여줍니다. 이 broadcast receiver는 WifiP2pManager 객체와 활동을 인수로 사용 이 두 가지 클래스를 사용하여 broadcast receiver가 인텐트를 수신합니다.

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
           }
       }
   }
}

자바

/**
* 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
       }
   }
}

Android 10 이상을 실행하는 기기에서 다음 브로드캐스트 인텐트는 비고정:

WIFI_P2P_CONNECTION_CHANGED_ACTION
응용 프로그램에서 사용할 수 있는 requestConnectionInfo(), requestNetworkInfo()님, 또는 requestGroupInfo()를 사용하여 현재 연결 정보를 가져옵니다.
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
애플리케이션에서 requestDeviceInfo() 현재 연결 정보를 검색합니다.

Wi-Fi P2P 애플리케이션 만들기

Wi-Fi P2P 애플리케이션을 만들려면 브로드캐스트를 만들고 등록해야 합니다. 애플리케이션용 수신기, 피어 검색, 피어에 연결 데이터를 피어로 전송합니다 다음 섹션에서는 그 방법을 설명합니다.

초기 설정

Wi-Fi P2P API를 사용하기 전에 애플리케이션이 하드웨어에 액세스하고 기기가 Wi-Fi P2P 프로토콜을 지원하는지 확인합니다. 만약 Wi-Fi P2P가 지원됩니다. WifiP2pManager의 인스턴스를 가져와서 Broadcast receiver를 등록하고 Wi-Fi P2P API 사용을 시작합니다.

  1. 기기에서 Wi-Fi 하드웨어를 사용할 권한을 요청하고 애플리케이션이 올바른 최소 SDK 버전을 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" />
    

    위의 권한 외에 다음 API에 위치도 필요합니다. 사용 설정할 모드:

  2. Wi-Fi P2P가 켜져 있고 지원되는지 확인합니다. 이를 확인하기에 좋은 곳은 broadcast receiver를 수신하면 WIFI_P2P_STATE_CHANGED_ACTION 인텐트를 처리하세요. Wi-Fi P2P 활동 알림 적절하게 대응합니다.

    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
               }
           }
       }
    }
    ...
    }
    

    자바

    @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
       }
    }
    ...
    }
    
  3. 활동의 onCreate() 드림 메서드를 호출하고 WifiP2pManager의 인스턴스를 가져오고 애플리케이션을 등록합니다. initialize()를 호출하여 Wi-Fi P2P 프레임워크로 전송해야 합니다. 이 메서드는 WifiP2pManager.Channel: 애플리케이션을 Wi-Fi P2P 프레임워크 또한 브로드캐스트의 인스턴스도 WifiP2pManagerWifiP2pManager.Channel 객체가 있는 수신기 내 활동에 대한 참조를 추가할 수 있습니다 이를 통해 broadcast receiver는 흥미있는 이벤트를 활동에 알리고 그에 따라 업데이트하세요. 또한 를 사용하면 필요한 경우 기기의 Wi-Fi 상태를 조작할 수 있습니다.

    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)
       }
    }
    

    자바

    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);
       ...
    }
    
  4. 인텐트 필터를 만들고 broadcast receiver와 동일한 인텐트 추가 다음을 확인합니다.

    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)
    }
    

    자바

    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);
       ...
    }
    
  5. broadcast receiver를 onResume() 메서드 에서 등록을 취소할 수 있습니다. onPause() 메서드를 활동:

    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)
       }
    }
    

    자바

    /* 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);
    }
    
  6. WifiP2pManager.Channel를 받고 방송을 설정한 경우 애플리케이션은 Wi-Fi P2P 메서드를 호출하고 Wi-Fi를 수신할 수 있습니다. P2P 인텐트

  7. 다음을 호출하여 Wi-Fi P2P 기능을 사용하여 애플리케이션을 구현합니다. WifiP2pManager에 있습니다.

다음 섹션에서는 Cloud Shell에서 검색 및 연결할 수 있습니다

피어 검색

discoverPeers()를 호출하여 범위 내에 있고 사용 가능한 피어를 감지합니다. 연결할 수 있습니다 이 함수에 대한 호출은 비동기식이며 성공 또는 실패가 onSuccess()onFailure()를 통해 애플리케이션에 전달됩니다. (WifiP2pManager.ActionListener를 만든 경우) onSuccess() 메서드만 탐색 프로세스가 성공했음을 알리고 발견한 실제 피어에 대한 정보 다음 코드 샘플이 이를 설정하는 방법을 보여줍니다.

Kotlin

manager?.discoverPeers(channel, object : WifiP2pManager.ActionListener {

   override fun onSuccess() {
       ...
   }

   override fun onFailure(reasonCode: Int) {
       ...
   }
})

자바

manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
   @Override
   public void onSuccess() {
       ...
   }

   @Override
   public void onFailure(int reasonCode) {
       ...
   }
});

검색 프로세스가 성공하고 피어를 감지하면 시스템이 브로드캐스트에서 수신 대기할 수 있는 WIFI_P2P_PEERS_CHANGED_ACTION 인텐트 수신기를 사용하여 피어 목록을 가져옵니다. 애플리케이션이 WIFI_P2P_PEERS_CHANGED_ACTION 인텐트가 포함된 경우 발견된 대상 목록을 요청할 수 있습니다. requestPeers()와 피어링됩니다. 다음 코드는 이를 설정하는 방법을 보여줍니다.

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
           }
       }
       ...
   }
}

자바

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);
   }
}

requestPeers() 메서드도 비동기식이며 활동에 알릴 수 있습니다. 피어 목록을 사용할 수 있을 때 onPeersAvailable(), 이는 WifiP2pManager.PeerListListener 인터페이스에 정의되어 있습니다. 이 onPeersAvailable() 메서드는 WifiP2pDeviceList 이 과정을 반복하여 연결할 피어를 찾을 수 있습니다.

피어 연결

가능한 동종 앱 목록을 가져오고 연결할 기기를 선택한 후 connect() 메서드를 호출하여 기기에 연결합니다. 이 메서드 호출은 WifiP2pConfig 필요 연결할 기기에 대한 정보가 포함된 객체입니다. WifiP2pManager.ActionListener에서 연결 성공 알림을 보내거나 있습니다 다음 코드는 기기에 연결하는 방법을 보여줍니다.

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
       }
   }
)}

자바

//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
   }
});

데이터 전송

연결이 설정되면 장치 간에 데이터를 전송할 수 있습니다. 연결할 수 있습니다 데이터를 전송하기 위한 기본 단계는 다음과 같습니다.

  1. ServerSocket를 만듭니다. 이 소켓은 지정된 포트의 클라이언트에서 연결을 대기하다가 백그라운드 스레드에서 수행해야 합니다.
  2. 클라이언트 Socket를 만듭니다. 클라이언트는 서버 장치에 연결하기 위한 서버 소켓의 IP 주소 및 포트.
  3. 클라이언트에서 서버로 데이터를 전송합니다. 클라이언트 소켓이 성공적으로 서버 소켓에 연결하면 클라이언트에서 바이트 스트림과 함께 보냅니다.
  4. 서버 소켓이 클라이언트 연결 ( accept() 메서드). 이 통화는 차단되지 않으므로 다른 스레드에서 호출하세요. 사용자가 서버 장치가 클라이언트로부터 데이터를 수신할 수 있습니다.

다음 예는 Wi-Fi P2P에서 수정되었습니다. 데모 이 클라이언트-서버 소켓 통신을 생성하고 서비스를 사용하여 클라이언트에서 서버로 JPEG 이미지. 완벽한 작동을 위해 데모를 컴파일하고 실행합니다

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)
       }
   }
}

자바

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);
       }
   }
}

클라이언트에서 클라이언트 소켓으로 서버 소켓에 연결하고 데이터를 수집하는 데 사용됩니다 이 예에서는 클라이언트 기기의 파일 시스템에서 JPEG 파일을 전송합니다.

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
           }
       }
   }
}