สร้างการเชื่อมต่อ P2P ด้วย Wi-Fi Direct

Wi-Fi Direct (หรือที่เรียกว่า Peer-to-Peer หรือ P2P) ช่วยให้แอปพลิเคชันของคุณค้นหาและโต้ตอบกับอุปกรณ์ที่อยู่ใกล้เคียงได้อย่างรวดเร็ว ในระยะที่ไกลกว่าความสามารถของบลูทูธ

API ของ Wi-Fi Direct (P2P) ช่วยให้แอปพลิเคชันเชื่อมต่อกับอุปกรณ์ที่อยู่ใกล้เคียงได้โดยไม่ต้องเชื่อมต่อกับเครือข่ายหรือฮอตสปอต หากแอปของคุณออกแบบมาให้เป็นส่วนหนึ่งของเครือข่ายที่ปลอดภัยและมีระยะใกล้ Wi-Fi Direct จะเป็นตัวเลือกที่เหมาะสมกว่าการเชื่อมต่อเครือข่ายเฉพาะกิจแบบ Wi-Fi ทั่วไปด้วยเหตุผลต่อไปนี้

  • Wi-Fi Direct รองรับการเข้ารหัส WPA2 (เครือข่ายเฉพาะกิจบางเครือข่ายรองรับเฉพาะการเข้ารหัส WEP)
  • อุปกรณ์สามารถออกอากาศบริการที่ตนมี ซึ่งจะช่วยให้อุปกรณ์อื่นๆ ค้นหาอุปกรณ์ที่เหมาะสมได้ง่ายขึ้น
  • เมื่อพิจารณาว่าอุปกรณ์ใดควรเป็นเจ้าของกลุ่มสำหรับเครือข่าย Wi-Fi Direct จะตรวจสอบการจัดการพลังงาน, UI และความสามารถของบริการ ของอุปกรณ์แต่ละเครื่อง และใช้ข้อมูลนี้เพื่อเลือกอุปกรณ์ที่สามารถจัดการ ความรับผิดชอบของเซิร์ฟเวอร์ได้อย่างมีประสิทธิภาพมากที่สุด
  • Android ไม่รองรับโหมดเฉพาะกิจของ Wi-Fi

บทเรียนนี้จะแสดงวิธีค้นหาและเชื่อมต่อกับอุปกรณ์ที่อยู่ใกล้เคียงโดยใช้ Wi-Fi P2P

ตั้งค่าสิทธิ์ของแอปพลิเคชัน

หากต้องการใช้ Wi-Fi Direct ให้เพิ่มสิทธิ์ ACCESS_FINE_LOCATION CHANGE_WIFI_STATE ACCESS_WIFI_STATE และ INTERNET ลงในไฟล์ Manifest หากแอปกำหนดเป้าหมายเป็น Android 13 (API ระดับ 33) ขึ้นไป ให้เพิ่ม NEARBY_WIFI_DEVICES ลงในไฟล์ Manifest ด้วย Wi-Fi Direct ไม่ต้องใช้การเชื่อมต่ออินเทอร์เน็ต แต่ใช้ซ็อกเก็ต Java มาตรฐาน ซึ่งต้องใช้INTERNET สิทธิ์ ดังนั้นคุณต้องมีสิทธิ์ต่อไปนี้จึงจะใช้ Wi-Fi Direct ได้

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.nsdchat"
    ...
    <!-- 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:required="true"
        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" />
    <uses-permission
        android:required="true"
        android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission
        android:required="true"
        android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission
        android:required="true"
        android:name="android.permission.INTERNET"/>
    ...

นอกจากสิทธิ์ข้างต้นแล้ว API ต่อไปนี้ยังต้องเปิดใช้โหมดตำแหน่งด้วย

ตั้งค่า Broadcast Receiver และ Peer-to-Peer Manager

หากต้องการใช้ Wi-Fi Direct คุณต้องรอฟัง Broadcast Intent ที่จะแจ้งให้แอปพลิเคชันทราบเมื่อมีเหตุการณ์บางอย่างเกิดขึ้น ในแอปพลิเคชัน ให้สร้างอินสแตนซ์ของ IntentFilter และตั้งค่าให้รับฟังสิ่งต่อไปนี้

WIFI_P2P_STATE_CHANGED_ACTION
ระบุว่าเปิดใช้ Wi-Fi Direct หรือไม่
WIFI_P2P_PEERS_CHANGED_ACTION
ระบุว่ารายการเพียร์ที่ใช้ได้มีการเปลี่ยนแปลง
WIFI_P2P_CONNECTION_CHANGED_ACTION
ระบุว่าสถานะการเชื่อมต่อ Wi-Fi Direct เปลี่ยนแปลงแล้ว ตั้งแต่ Android 10 เป็นต้นไป การตั้งค่านี้จะไม่คงอยู่ หากแอปของคุณอาศัยการรับข้อมูลออกอากาศเหล่านี้ เมื่อลงทะเบียนเนื่องจากข้อมูลเหล่านี้คงอยู่ ให้ใช้วิธีการ get ที่เหมาะสมเมื่อเริ่มต้นเพื่อรับข้อมูลแทน
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
แสดงว่ารายละเอียดการกำหนดค่าของอุปกรณ์นี้มีการเปลี่ยนแปลง ตั้งแต่ Android 10 เป็นต้นไป การตั้งค่านี้จะไม่คงอยู่ หากแอปของคุณอาศัยการรับข้อมูลออกอากาศเหล่านี้ เมื่อลงทะเบียนเนื่องจากข้อมูลเหล่านี้คงอยู่ ให้ใช้วิธีการ get ที่เหมาะสมเมื่อเริ่มต้นเพื่อรับข้อมูลแทน

Kotlin

private val intentFilter = IntentFilter()
...
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

    // Indicates a change in the Wi-Fi Direct status.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)

    // Indicates a change in the list of available peers.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)

    // Indicates the state of Wi-Fi Direct connectivity has changed.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)

    // Indicates this device's details have changed.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)
    ...
}

Java

private final IntentFilter intentFilter = new IntentFilter();
...
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Indicates a change in the Wi-Fi Direct status.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);

    // Indicates a change in the list of available peers.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);

    // Indicates the state of Wi-Fi Direct connectivity has changed.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);

    // Indicates this device's details have changed.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
    ...
}

ในตอนท้ายของonCreate() ให้รับอินสแตนซ์ของ WifiP2pManager แล้วเรียกใช้เมธอด initialize() เมธอดนี้จะแสดงออบเจ็กต์ WifiP2pManager.Channel ซึ่งคุณจะใช้ในภายหลังเพื่อ เชื่อมต่อแอปกับเฟรมเวิร์ก Wi-Fi Direct

Kotlin

private lateinit var channel: WifiP2pManager.Channel
private lateinit var manager: WifiP2pManager

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    manager = getSystemService(Context.WIFI_P2P_SERVICE) as WifiP2pManager
    channel = manager.initialize(this, mainLooper, null)
}

Java

Channel channel;
WifiP2pManager manager;

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    channel = manager.initialize(this, getMainLooper(), null);
}

ตอนนี้ให้สร้างBroadcastReceiverคลาสใหม่ที่จะใช้เพื่อฟังการเปลี่ยนแปลง สถานะ Wi-Fi ของระบบ ในonReceive() เมธอด ให้เพิ่มเงื่อนไขเพื่อจัดการการเปลี่ยนแปลงสถานะแต่ละรายการที่ระบุไว้ข้างต้น

Kotlin

override fun onReceive(context: Context, intent: Intent) {
    when(intent.action) {
        WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION -> {
            // Determine if Wi-Fi Direct mode is enabled or not, alert
            // the Activity.
            val state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1)
            activity.isWifiP2pEnabled = state == WifiP2pManager.WIFI_P2P_STATE_ENABLED
        }
        WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION -> {

            // The peer list has changed! We should probably do something about
            // that.

        }
        WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION -> {

            // Connection state changed! We should probably do something about
            // that.

        }
        WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION -> {
            (activity.supportFragmentManager.findFragmentById(R.id.frag_list) as DeviceListFragment)
                    .apply {
                        updateThisDevice(
                                intent.getParcelableExtra(
                                        WifiP2pManager.EXTRA_WIFI_P2P_DEVICE) as WifiP2pDevice
                        )
                    }
        }
    }
}

Java

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
        // Determine if Wi-Fi Direct mode is enabled or not, alert
        // the Activity.
        int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
        if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
            activity.setIsWifiP2pEnabled(true);
        } else {
            activity.setIsWifiP2pEnabled(false);
        }
    } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {

        // The peer list has changed! We should probably do something about
        // that.

    } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {

        // Connection state changed! We should probably do something about
        // that.

    } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
        DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
                .findFragmentById(R.id.frag_list);
        fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
                WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));

    }
}

สุดท้าย ให้เพิ่มโค้ดเพื่อลงทะเบียนตัวกรอง Intent และ Broadcast Receiver เมื่อ กิจกรรมหลักทำงานอยู่ และยกเลิกการลงทะเบียนเมื่อกิจกรรมหยุดชั่วคราว วิธีที่ดีที่สุดคือการใช้เมธอด onResume() และ onPause()

Kotlin

/** register the BroadcastReceiver with the intent values to be matched  */
public override fun onResume() {
    super.onResume()
    receiver = WiFiDirectBroadcastReceiver(manager, channel, this)
    registerReceiver(receiver, intentFilter)
}

public override fun onPause() {
    super.onPause()
    unregisterReceiver(receiver)
}

Java

/** register the BroadcastReceiver with the intent values to be matched */
@Override
public void onResume() {
    super.onResume();
    receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
    registerReceiver(receiver, intentFilter);
}

@Override
public void onPause() {
    super.onPause();
    unregisterReceiver(receiver);
}

เริ่มการค้นหาเพียร์

หากต้องการเริ่มค้นหาอุปกรณ์ที่อยู่ใกล้เคียงด้วย Wi-Fi P2P ให้เรียกใช้ discoverPeers() เมธอดนี้รับอาร์กิวเมนต์ต่อไปนี้

  • WifiP2pManager.Channelที่คุณ ได้รับกลับมาเมื่อเริ่มต้น mManager แบบเพียร์ทูเพียร์
  • การติดตั้งใช้งาน WifiP2pManager.ActionListener ด้วยเมธอด ที่ระบบเรียกใช้สำหรับการค้นพบที่สำเร็จและไม่สำเร็จ

Kotlin

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

    override fun onSuccess() {
        // Code for when the discovery initiation is successful goes here.
        // No services have actually been discovered yet, so this method
        // can often be left blank. Code for peer discovery goes in the
        // onReceive method, detailed below.
    }

    override fun onFailure(reasonCode: Int) {
        // Code for when the discovery initiation fails goes here.
        // Alert the user that something went wrong.
    }
})

Java

manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {

    @Override
    public void onSuccess() {
        // Code for when the discovery initiation is successful goes here.
        // No services have actually been discovered yet, so this method
        // can often be left blank. Code for peer discovery goes in the
        // onReceive method, detailed below.
    }

    @Override
    public void onFailure(int reasonCode) {
        // Code for when the discovery initiation fails goes here.
        // Alert the user that something went wrong.
    }
});

โปรดทราบว่าการดำเนินการนี้เป็นเพียงการเริ่มต้นการค้นหาเพียร์เท่านั้น เมธอด discoverPeers() จะเริ่มกระบวนการค้นหาแล้ว ส่งคืนทันที ระบบจะแจ้งให้คุณทราบหากกระบวนการค้นหาอุปกรณ์ร่วม เริ่มต้นสำเร็จโดยการเรียกใช้เมธอดในเครื่องมือฟังการดำเนินการที่ระบุ นอกจากนี้ การค้นหายังคงใช้งานได้จนกว่าจะมีการเริ่มการเชื่อมต่อหรือมีการสร้างกลุ่ม P2P

ดึงข้อมูลรายชื่อเพียร์

ตอนนี้ให้เขียนโค้ดที่ดึงและประมวลผลรายการเพียร์ ก่อนอื่น ให้ใช้WifiP2pManager.PeerListListener อินเทอร์เฟซ ซึ่งให้ข้อมูลเกี่ยวกับอุปกรณ์ที่ Wi-Fi Direct ตรวจพบ นอกจากนี้ ข้อมูลนี้ยังช่วยให้แอปของคุณระบุได้ว่าเมื่อใดที่เพียร์เข้าร่วมหรือออกจากเครือข่าย ข้อมูลโค้ดต่อไปนี้แสดงการดำเนินการเหล่านี้ ที่เกี่ยวข้องกับเพียร์

Kotlin

private val peers = mutableListOf<WifiP2pDevice>()
...

private val peerListListener = WifiP2pManager.PeerListListener { peerList ->
    val refreshedPeers = peerList.deviceList
    if (refreshedPeers != peers) {
        peers.clear()
        peers.addAll(refreshedPeers)

        // If an AdapterView is backed by this data, notify it
        // of the change. For instance, if you have a ListView of
        // available peers, trigger an update.
        (listAdapter as WiFiPeerListAdapter).notifyDataSetChanged()

        // Perform any other updates needed based on the new list of
        // peers connected to the Wi-Fi P2P network.
    }

    if (peers.isEmpty()) {
        Log.d(TAG, "No devices found")
        return@PeerListListener
    }
}

Java

private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
...

private PeerListListener peerListListener = new PeerListListener() {
    @Override
    public void onPeersAvailable(WifiP2pDeviceList peerList) {

        List<WifiP2pDevice> refreshedPeers = peerList.getDeviceList();
        if (!refreshedPeers.equals(peers)) {
            peers.clear();
            peers.addAll(refreshedPeers);

            // If an AdapterView is backed by this data, notify it
            // of the change. For instance, if you have a ListView of
            // available peers, trigger an update.
            ((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();

            // Perform any other updates needed based on the new list of
            // peers connected to the Wi-Fi P2P network.
        }

        if (peers.size() == 0) {
            Log.d(WiFiDirectActivity.TAG, "No devices found");
            return;
        }
    }
}

ตอนนี้ให้แก้ไขเมธอด onReceive() ของ BroadcastReceiver เพื่อเรียกใช้ requestPeers() เมื่อได้รับ Intent ที่มี Action WIFI_P2P_PEERS_CHANGED_ACTION คุณ ต้องส่ง Listener นี้ไปยังตัวรับด้วยวิธีใดวิธีหนึ่ง วิธีหนึ่งคือการส่งเป็นอาร์กิวเมนต์ไปยังตัวสร้างของ BroadcastReceiver

Kotlin

fun onReceive(context: Context, intent: Intent) {
    when (intent.action) {
        ...
        WifiP2pManager.WIFI_P2P_PEERS_CHANGED_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()
            mManager?.requestPeers(channel, peerListListener)
            Log.d(TAG, "P2P peers changed")


        }
        ...
    }
}

Java

public void onReceive(Context context, Intent intent) {
    ...
    else 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 (mManager != null) {
            mManager.requestPeers(channel, peerListListener);
        }
        Log.d(WiFiDirectActivity.TAG, "P2P peers changed");
    }...
}

ตอนนี้เจตนาที่มีการดำเนินการ WIFI_P2P_PEERS_CHANGED_ACTION intent จะทริกเกอร์คำขอรายการเพียร์ที่อัปเดตแล้ว

เชื่อมต่อกับเพียร์

หากต้องการเชื่อมต่อกับอุปกรณ์ที่อยู่เครือข่ายเดียวกัน ให้สร้างออบเจ็กต์ WifiP2pConfig ใหม่ แล้วคัดลอกข้อมูลจาก WifiP2pDevice ที่แสดงถึงอุปกรณ์ที่คุณต้องการเชื่อมต่อ จากนั้นเรียกใช้connect() เมธอด

Kotlin

override fun connect() {
    // Picking the first device found on the network.
    val device = peers[0]

    val config = WifiP2pConfig().apply {
        deviceAddress = device.deviceAddress
        wps.setup = WpsInfo.PBC
    }

    manager.connect(channel, config, object : WifiP2pManager.ActionListener {

        override fun onSuccess() {
            // WiFiDirectBroadcastReceiver notifies us. Ignore for now.
        }

        override fun onFailure(reason: Int) {
            Toast.makeText(
                    this@WiFiDirectActivity,
                    "Connect failed. Retry.",
                    Toast.LENGTH_SHORT
            ).show()
        }
    })
}

Java

@Override
public void connect() {
    // Picking the first device found on the network.
    WifiP2pDevice device = peers.get(0);

    WifiP2pConfig config = new WifiP2pConfig();
    config.deviceAddress = device.deviceAddress;
    config.wps.setup = WpsInfo.PBC;

    manager.connect(channel, config, new ActionListener() {

        @Override
        public void onSuccess() {
            // WiFiDirectBroadcastReceiver notifies us. Ignore for now.
        }

        @Override
        public void onFailure(int reason) {
            Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",
                    Toast.LENGTH_SHORT).show();
        }
    });
}

หากอุปกรณ์แต่ละเครื่องในกลุ่มรองรับ Wi-Fi Direct คุณก็ไม่จำเป็นต้อง ขอรหัสผ่านของกลุ่มอย่างชัดเจนเมื่อเชื่อมต่อ อย่างไรก็ตาม หากต้องการอนุญาตให้อุปกรณ์ ที่ไม่รองรับ Wi-Fi Direct เข้าร่วมกลุ่ม คุณจะต้อง ดึงรหัสผ่านนี้โดยการเรียกใช้ requestGroupInfo() ตามที่แสดงในข้อมูลโค้ดต่อไปนี้

Kotlin

manager.requestGroupInfo(channel) { group ->
    val groupPassword = group.passphrase
}

Java

manager.requestGroupInfo(channel, new GroupInfoListener() {
  @Override
  public void onGroupInfoAvailable(WifiP2pGroup group) {
      String groupPassword = group.getPassphrase();
  }
});

โปรดทราบว่า WifiP2pManager.ActionListener ที่ใช้ในเมธอด connect() จะแจ้งเตือนคุณเมื่อการเริ่มต้นสำเร็จหรือไม่สำเร็จเท่านั้น หากต้องการฟังการเปลี่ยนแปลงในสถานะการเชื่อมต่อ ให้ใช้ อินเทอร์เฟซ WifiP2pManager.ConnectionInfoListener onConnectionInfoAvailable() การเรียกกลับจะแจ้งให้คุณทราบเมื่อสถานะของ การเชื่อมต่อเปลี่ยนแปลง ในกรณีที่จะมีการเชื่อมต่ออุปกรณ์หลายเครื่องกับอุปกรณ์เครื่องเดียว (เช่น เกมที่มีผู้เล่น 3 คนขึ้นไปหรือแอปแชท) ระบบจะกำหนดให้อุปกรณ์เครื่องหนึ่งเป็น "เจ้าของกลุ่ม" คุณสามารถกำหนดให้อุปกรณ์เครื่องใดเครื่องหนึ่งเป็นเจ้าของกลุ่มของเครือข่ายได้โดยทำตามขั้นตอนในส่วนสร้างกลุ่ม

Kotlin

private val connectionListener = WifiP2pManager.ConnectionInfoListener { info ->

    // String from WifiP2pInfo struct
    val groupOwnerAddress: String = info.groupOwnerAddress.hostAddress

    // After the group negotiation, we can determine the group owner
    // (server).
    if (info.groupFormed && info.isGroupOwner) {
        // Do whatever tasks are specific to the group owner.
        // One common case is creating a group owner thread and accepting
        // incoming connections.
    } else if (info.groupFormed) {
        // The other device acts as the peer (client). In this case,
        // you'll want to create a peer thread that connects
        // to the group owner.
    }
}

Java

@Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {

    // String from WifiP2pInfo struct
    String groupOwnerAddress = info.groupOwnerAddress.getHostAddress();

    // After the group negotiation, we can determine the group owner
    // (server).
    if (info.groupFormed && info.isGroupOwner) {
        // Do whatever tasks are specific to the group owner.
        // One common case is creating a group owner thread and accepting
        // incoming connections.
    } else if (info.groupFormed) {
        // The other device acts as the peer (client). In this case,
        // you'll want to create a peer thread that connects
        // to the group owner.
    }
}

ตอนนี้กลับไปที่onReceive()ของ BroadcastReceiver แล้วแก้ไขส่วน ที่รอรับ Intent WIFI_P2P_CONNECTION_CHANGED_ACTION เมื่อได้รับ Intent นี้ ให้เรียกใช้ requestConnectionInfo() นี่คือการเรียกแบบไม่พร้อมกัน ดังนั้นผลลัพธ์จะได้รับจากเครื่องมือฟังข้อมูลการเชื่อมต่อที่คุณระบุเป็น พารามิเตอร์

Kotlin

when (intent.action) {
    ...
    WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION -> {

        // Connection state changed! We should probably do something about
        // that.

        mManager?.let { manager ->

            val networkInfo: NetworkInfo? = intent
                    .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO) as NetworkInfo

            if (networkInfo?.isConnected == true) {

                // We are connected with the other device, request connection
                // info to find group owner IP

                manager.requestConnectionInfo(channel, connectionListener)
            }
        }
    }
    ...
}

Java

    ...
    } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {

        if (manager == null) {
            return;
        }

        NetworkInfo networkInfo = (NetworkInfo) intent
                .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);

        if (networkInfo.isConnected()) {

            // We are connected with the other device, request connection
            // info to find group owner IP

            manager.requestConnectionInfo(channel, connectionListener);
        }
        ...

สร้างกลุ่ม

หากต้องการให้อุปกรณ์ที่เรียกใช้แอปของคุณทำหน้าที่เป็นเจ้าของกลุ่มสำหรับเครือข่ายที่มีอุปกรณ์รุ่นเดิม ซึ่งก็คืออุปกรณ์ที่ไม่รองรับ Wi-Fi Direct คุณจะต้องทำตามลำดับขั้นตอนเดียวกันกับในส่วนเชื่อมต่อกับอุปกรณ์ที่อยู่ใกล้เคียง เพียงแต่สร้าง WifiP2pManager.ActionListener ใหม่โดยใช้ createGroup() แทน connect() การจัดการการเรียกกลับภายใน WifiP2pManager.ActionListener จะเหมือนกัน ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

Kotlin

manager.createGroup(channel, object : WifiP2pManager.ActionListener {
    override fun onSuccess() {
        // Device is ready to accept incoming connections from peers.
    }

    override fun onFailure(reason: Int) {
        Toast.makeText(
                this@WiFiDirectActivity,
                "P2P group creation failed. Retry.",
                Toast.LENGTH_SHORT
        ).show()
    }
})

Java

manager.createGroup(channel, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        // Device is ready to accept incoming connections from peers.
    }

    @Override
    public void onFailure(int reason) {
        Toast.makeText(WiFiDirectActivity.this, "P2P group creation failed. Retry.",
                Toast.LENGTH_SHORT).show();
    }
});

หมายเหตุ: หากอุปกรณ์ทั้งหมดในเครือข่ายรองรับ Wi-Fi Direct คุณจะใช้วิธีconnect()ในแต่ละอุปกรณ์ได้ เนื่องจากวิธีนี้จะสร้างกลุ่มและเลือกเจ้าของกลุ่มโดยอัตโนมัติ

หลังจากสร้างกลุ่มแล้ว คุณจะเรียกใช้ requestGroupInfo() เพื่อดึงรายละเอียดเกี่ยวกับอุปกรณ์ในเครือข่ายได้ ซึ่งรวมถึงชื่ออุปกรณ์และสถานะการเชื่อมต่อ