نمای کلی Wi-Fi Direct (همتا به همتا یا P2P).

Wi-Fi Direct (P2P) به دستگاه هایی با سخت افزار مناسب اجازه می دهد تا مستقیماً از طریق Wi-Fi بدون نقطه دسترسی میانی به یکدیگر متصل شوند. با استفاده از این APIها، هنگامی که هر دستگاه از Wi-Fi P2P پشتیبانی می کند، می توانید دستگاه های دیگر را کشف کرده و به آنها متصل شوید، سپس از طریق یک اتصال سریع در فواصل بسیار طولانی تر از اتصال بلوتوث ارتباط برقرار کنید. این برای برنامه‌هایی مفید است که داده‌ها را بین کاربران به اشتراک می‌گذارند، مانند یک بازی چند نفره یا یک برنامه اشتراک‌گذاری عکس.

API های Wi-Fi P2P از بخش های اصلی زیر تشکیل شده اند:

  • روش‌هایی که به شما امکان می‌دهند کشف، درخواست و اتصال به همتایان را که در کلاس 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() اتصال همتا به همتا را با دستگاهی با پیکربندی مشخص شده شروع می کند.
cancelConnect() هرگونه مذاکره گروهی همتا به همتا را لغو می کند.
requestConnectInfo() اطلاعات اتصال دستگاه را درخواست می کند.
createGroup() یک گروه همتا به همتا با دستگاه فعلی به عنوان مالک گروه ایجاد می کند.
removeGroup() گروه همتا به همتا کنونی را حذف می کند.
requestGroupInfo() اطلاعات گروه همتا به همتا را درخواست می کند.
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()

APIهای Wi-Fi P2P مقاصدی را تعریف می‌کنند که وقتی رویدادهای P2P Wi-Fi خاصی اتفاق می‌افتد، مانند زمانی که همتای جدیدی کشف می‌شود یا زمانی که وضعیت Wi-Fi دستگاه تغییر می‌کند، پخش می‌شوند. می توانید با ایجاد یک گیرنده پخش که این اهداف را مدیریت می کند، برای دریافت این اهداف در برنامه خود ثبت نام کنید:

جدول 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 ایجاد کنید

یک گیرنده پخش به شما امکان می دهد اهداف پخش شده توسط سیستم اندروید را دریافت کنید تا برنامه شما بتواند به رویدادهایی که به آنها علاقه دارید پاسخ دهد. مراحل اساسی برای ایجاد یک گیرنده پخش برای مدیریت اهداف Wi-Fi P2P به شرح زیر است:

  1. کلاسی ایجاد کنید که کلاس BroadcastReceiver را گسترش دهد. برای سازنده کلاس، از پارامترهای WifiP2pManager ، WifiP2pManager.Channel و فعالیتی که این گیرنده پخش در آن ثبت می شود استفاده خواهید کرد. این به گیرنده پخش اجازه می دهد تا به روز رسانی ها را برای فعالیت ارسال کند و همچنین به Wi- دسترسی داشته باشد. سخت افزار Fi و کانال ارتباطی در صورت نیاز.

  2. در گیرنده پخش، اهداف مورد نظر خود را در متد onReceive() بررسی کنید. هر گونه اقدام لازم را بسته به قصد دریافت شده انجام دهید. به عنوان مثال، اگر گیرنده پخش یک هدف WIFI_P2P_PEERS_CHANGED_ACTION دریافت می کند، می توانید متد requestPeers() را فراخوانی کنید تا لیستی از همتاهای کشف شده فعلی را دریافت کنید.

کد زیر نحوه ایجاد یک گیرنده پخش معمولی را به شما نشان می دهد. گیرنده پخش یک شی WifiP2pManager و یک اکتیویتی را به عنوان آرگومان می گیرد و از این دو کلاس برای اجرای مناسب اقدامات مورد نیاز هنگامی که گیرنده پخش یک هدف دریافت می کند استفاده می کند:

کاتلین

/**
* 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 شامل ایجاد و ثبت یک گیرنده پخش برای برنامه شما، کشف همتایان، اتصال به همتا و انتقال داده به همتا است. بخش های زیر نحوه انجام این کار را توضیح می دهند.

راه اندازی اولیه

قبل از استفاده از API های Wi-Fi P2P، باید مطمئن شوید که برنامه شما می تواند به سخت افزار دسترسی داشته باشد و دستگاه از پروتکل Wi-Fi P2P پشتیبانی می کند. اگر Wi-Fi P2P پشتیبانی می شود، می توانید نمونه ای از WifiP2pManager را دریافت کنید، گیرنده پخش خود را ایجاد و ثبت کنید و شروع به استفاده از API های Wi-Fi P2P کنید.

  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 روشن و پشتیبانی می‌شود یا خیر. هنگامی که هدف WIFI_P2P_STATE_CHANGED_ACTION را دریافت می کند، یک مکان خوب برای بررسی این موضوع در گیرنده پخش شما است. فعالیت خود را از وضعیت Wi-Fi P2P مطلع کنید و مطابق با آن واکنش نشان دهید:

    کاتلین

    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 استفاده می شود. همچنین باید یک نمونه از گیرنده پخش خود را با اشیاء WifiP2pManager و WifiP2pManager.Channel همراه با اشاره به فعالیت خود ایجاد کنید. این به گیرنده پخش شما امکان می دهد تا فعالیت شما را از رویدادهای جالب مطلع کند و آن را متناسب با آن به روز کند. همچنین به شما امکان می دهد در صورت لزوم وضعیت Wi-Fi دستگاه را دستکاری کنید:

    کاتلین

    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. یک فیلتر قصد ایجاد کنید و همان مقاصدی را که گیرنده پخش شما بررسی می کند اضافه کنید:

    کاتلین

    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. گیرنده پخش را در متد onResume() فعالیت خود ثبت کنید و آن را در متد onPause() فعالیت خود لغو ثبت کنید:

    کاتلین

    /* 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 پیاده‌سازی کنید.

بخش‌های بعدی نحوه انجام اقدامات رایج مانند کشف و اتصال به همتایان را شرح می‌دهد.

همتایان را کشف کنید

برای شناسایی همتایان موجود که در محدوده هستند و برای اتصال در دسترس هستند، با discoverPeers() تماس بگیرید. فراخوانی این تابع ناهمزمان است و اگر یک WifiP2pManager.ActionListener ایجاد کرده باشید، یک موفقیت یا شکست با onSuccess() و onFailure() به برنامه شما منتقل می شود. متد onSuccess() فقط به شما اطلاع می دهد که فرآیند کشف موفقیت آمیز بوده است و در صورت وجود هیچ اطلاعاتی در مورد همتایان واقعی که کشف کرده است ارائه نمی دهد. نمونه کد زیر نحوه تنظیم این را نشان می دهد.

کاتلین

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() درخواست کنید. کد زیر نحوه تنظیم این را نشان می دهد.

کاتلین

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 می تواند شما را از موفقیت یا شکست اتصال مطلع کند. کد زیر نحوه ایجاد اتصال به یک دستگاه را به شما نشان می دهد.

کاتلین

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 Demo تغییر یافته است، به شما نشان می دهد که چگونه این ارتباط سوکت سرویس گیرنده-سرور را ایجاد کنید و تصاویر JPEG را از یک کلاینت به یک سرور با یک سرویس انتقال دهید. برای مثال کاری کامل، نسخه ی نمایشی را کامپایل و اجرا کنید.

کاتلین

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 را بر روی سیستم فایل دستگاه مشتری منتقل می کند.

کاتلین

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

جاوا

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