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

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

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

  • روش‌هایی که به شما امکان می‌دهند نظیرها را کشف، درخواست و به آنها متصل شوید، که در کلاس WifiP2pManager تعریف شده‌اند.
  • شنونده‌هایی که به شما امکان می‌دهند از موفقیت یا شکست فراخوانی‌های متد WifiP2pManager مطلع شوید. هنگام فراخوانی متدهای WifiP2pManager ، هر متد می‌تواند یک شنونده خاص که به عنوان پارامتر ارسال می‌شود را دریافت کند.
  • اینتنت‌هایی که شما را از رویدادهای خاص شناسایی‌شده توسط چارچوب Wi-Fi P2P، مانند قطع اتصال یا یک همتای تازه کشف‌شده، مطلع می‌کنند.

شما اغلب از این سه جزء اصلی APIها با هم استفاده خواهید کرد. برای مثال، می‌توانید یک WifiP2pManager.ActionListener برای فراخوانی discoverPeers() ارائه دهید تا متدهای ActionListener.onSuccess() و ActionListener.onFailure() بتوانند به شما اطلاع دهند. اگر متد discoverPeers() متوجه شود که لیست peerها تغییر کرده است، یک Intent از نوع WIFI_P2P_PEERS_CHANGED_ACTION نیز پخش می‌شود.

مرور کلی API

کلاس WifiP2pManager متدهایی را ارائه می‌دهد که به شما امکان می‌دهد با سخت‌افزار Wi-Fi روی دستگاه خود تعامل داشته باشید تا کارهایی مانند کشف و اتصال به دستگاه‌های همتا را انجام دهید. اقدامات زیر در دسترس هستند:

جدول 1. روش‌های Wi-Fi P2P

روش توضیحات
initialize() برنامه را در چارچوب Wi-Fi ثبت می‌کند. قبل از فراخوانی هر روش Wi-Fi P2P دیگر، این را فراخوانی کنید.
connect() یک اتصال نظیر به نظیر را با دستگاهی با پیکربندی مشخص شده آغاز می‌کند.
cancelConnect() هرگونه مذاکره گروهی نظیر به نظیر در حال انجام را لغو می‌کند.
requestConnectInfo() اطلاعات اتصال دستگاه را درخواست می‌کند.
createGroup() یک گروه نظیر به نظیر ایجاد می‌کند که دستگاه فعلی مالک گروه است.
removeGroup() گروه نظیر به نظیر فعلی را حذف می‌کند.
requestGroupInfo() اطلاعات گروه نظیر به نظیر را درخواست می‌کند.
discoverPeers() کشف همسالان را آغاز می‌کند.
requestPeers() لیست فعلی نظیرهای کشف شده را درخواست می‌کند.

متدهای WifiP2pManager به شما امکان می‌دهند یک شنونده (listener) ارسال کنید، به طوری که چارچوب 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، intentهایی را تعریف می‌کنند که هنگام وقوع رویدادهای خاص Wi-Fi P2P، مانند زمانی که یک peer جدید کشف می‌شود یا زمانی که وضعیت Wi-Fi یک دستگاه تغییر می‌کند، منتشر می‌شوند. می‌توانید با ایجاد یک broadcast receiver که این intentها را مدیریت می‌کند، برای دریافت این intentها در برنامه خود ثبت‌نام کنید:

جدول 3. اهداف Wi-Fi P2P

قصد توضیحات
WIFI_P2P_CONNECTION_CHANGED_ACTION پخش زمانی که وضعیت اتصال Wi-Fi دستگاه تغییر می‌کند.
WIFI_P2P_PEERS_CHANGED_ACTION وقتی که شما تابع discoverPeers() را فراخوانی می‌کنید، اعلان عمومی (Broadcast) می‌شود. اگر این intent را در برنامه خود مدیریت کنید، معمولاً برای دریافت لیست به‌روز شده از peerها 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 و activity که این broadcast receiver در آن ثبت خواهد شد، استفاده خواهید کرد. این به broadcast receiver اجازه می‌دهد تا به‌روزرسانی‌هایی را برای activity ارسال کند و همچنین در صورت نیاز به سخت‌افزار Wi-Fi و یک کانال ارتباطی دسترسی داشته باشد.

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

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

کاتلین

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

در دستگاه‌هایی که اندروید ۱۰ و بالاتر دارند، اهداف پخش زیر غیرچسبنده هستند:

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

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

    کاتلین

    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 را انجام دهد و Intentهای Wi-Fi P2P را دریافت کند.

  7. با فراخوانی متدهای موجود در WifiP2pManager ، برنامه خود را با استفاده از ویژگی‌های Wi-Fi P2P پیاده‌سازی کنید.

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

همسالان را کشف کنید

برای شناسایی جفت‌های موجود که در محدوده و برای اتصال در دسترس هستند، تابع discoverPeers() را فراخوانی کنید. فراخوانی این تابع ناهمزمان است و موفقیت یا شکست با onSuccess() و onFailure() به برنامه شما اطلاع داده می‌شود، اگر WifiP2pManager.ActionListener ایجاد کرده باشید. متد 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 تعریف شده است، هنگامی که لیستی از peerها در دسترس است، activity شما را مطلع کند. متد onPeersAvailable() یک WifiP2pDeviceList در اختیار شما قرار می‌دهد که می‌توانید با پیمایش در آن، peer مورد نظر برای اتصال را پیدا کنید.

به همسالان متصل شوید

پس از دریافت لیستی از peerهای ممکن و انتخاب دستگاهی برای اتصال، متد 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 ایجاد کنید. این سوکت منتظر اتصال از یک کلاینت روی پورت مشخص شده می‌ماند و تا زمانی که اتصال برقرار شود، مسدود می‌شود، بنابراین این کار را در یک thread پس‌زمینه انجام دهید.
  2. یک Socket کلاینت ایجاد کنید. کلاینت از آدرس IP و پورت سوکت سرور برای اتصال به دستگاه سرور استفاده می‌کند.
  3. ارسال داده از کلاینت به سرور. هنگامی که سوکت کلاینت با موفقیت به سوکت سرور متصل شد، می‌توانید داده‌ها را از کلاینت به سرور با جریان‌های بایتی ارسال کنید.
  4. سوکت سرور منتظر اتصال کلاینت می‌ماند (با متد accept() ). این فراخوانی تا زمانی که کلاینت متصل شود، مسدود می‌شود، بنابراین این را در یک thread دیگر فراخوانی کنید. وقتی اتصالی برقرار می‌شود، دستگاه سرور می‌تواند داده‌ها را از کلاینت دریافت کند.

مثال زیر که از نسخه آزمایشی Wi-Fi P2P اصلاح شده است، به شما نشان می‌دهد که چگونه این ارتباط سوکت کلاینت-سرور را ایجاد کنید و تصاویر 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
           }
       }
   }
}