Подключите более двух устройств с помощью Wifi Direct / Wifi P2P - PullRequest
1 голос
/ 13 июня 2019

Я успешно могу соединить два устройства и передать между ними строку, очень похожую на демонстрационную версию Android Studio.Однако, когда я пытаюсь подключить третье устройство, это невозможно сделать.Я попытался использовать manager.createGroup () вместо manager.connect (), но он не работает.

В частности, мне нужно передать строку с первого устройства на второе, со второго устройства натретий и с третьего устройства обратно на первое.Это должно быть динамически для всех подключенных устройств, поэтому цикл будет работать, если есть 8 устройств.

Код: Основная активность

 Button btnOnOff, btnDiscover, btnSend;
    ListView listView;
    TextView read_msg_box, connectionStatus;
    EditText writeMsg;

    WifiManager wifiManager;
    WifiP2pManager mManager;
    WifiP2pManager.Channel mChannel;

    BroadcastReceiver mReceiver;
    IntentFilter mIntentFilter;

    //these 3 are created for getting the information about the devices
    List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
    String[] deviceNameArray; //used to show the device name in the ListView
    WifiP2pDevice[] deviceArray; //used to connect to a device

    static final int MESSAGE_READ = 1; //for the handler

    ServerClass serverClass;
    ClientClass clientClass;
    SendReceive sendReceive;

    Button myTurnBtn;
 //   Boolean myTurn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initalWork();
        exqListener();
    }

    //for reading the message sent
    //Handler is needed to access variables from other threads
    //Handler is the best way to communicate between threads
    Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {

            switch(msg.what){
                case MESSAGE_READ:
                    byte[] readBuff = (byte[]) msg.obj;
                    String tempMsg = new String(readBuff,0,msg.arg1);
                    //if tempMsg.equals("go") then show the myTurn button
                    if (tempMsg.equals("go")) {
                        myTurnBtn.setVisibility(View.VISIBLE);
                        Toast.makeText(MainActivity.this, "success", Toast.LENGTH_SHORT).show();
                } else {
                        Toast.makeText(MainActivity.this, "not valid", Toast.LENGTH_SHORT).show();
                    }

                    //  then set MyTurn button visible
                    //print to screen "success"
                    //else
                    //print not valid


                    read_msg_box.setText(tempMsg);
                    break;
            }

            return true;
        }
    });

    private void exqListener() {

        btnOnOff.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //turn wifi off if on and on if off
                //check status
                if (wifiManager.isWifiEnabled()) {
                    //turn off wifi
                    wifiManager.setWifiEnabled(false);
                    btnOnOff.setText("ON");
                } else {
                    //turn on wifi
                    wifiManager.setWifiEnabled(true);
                    btnOnOff.setText("OFF");
                }
            }
        });

        btnDiscover.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //discovering other devices
                mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
                    @Override
                    public void onSuccess() {
                        connectionStatus.setText("Discovery Started");
                    }

                    @Override
                    public void onFailure(int reason) {
                        connectionStatus.setText("Discovery failed");
                    }
                });  //after discovering devices, need to get the information of the nearby devices (peers)
            }
        });

        //connect to the device that is clicked
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                final WifiP2pDevice device = deviceArray[position]; //linking up the position in the ListView with deviceArray position
                WifiP2pConfig config = new WifiP2pConfig();
                config.deviceAddress = device.deviceAddress;

                //connect to the chosen device - only tells of success or failure: need to use ConnectionInfoListener
                mManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
                    @Override
                    public void onSuccess() {
                        Toast.makeText(getApplicationContext(), "Connected to " + device.deviceName, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onFailure(int reason) {
                        Toast.makeText(getApplicationContext(), "Not Connected", Toast.LENGTH_SHORT).show();
                    }
                });


            }
        });

      /*  btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String msg = writeMsg.getText().toString();
                sendReceive.write(msg.getBytes());
                //
            }
        }); */

       myTurnBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //when button is clicked. Send message to receiving device ("go")
                String go = "go";
                sendReceive.write(go.getBytes()); //pass the go string into the write message

                //set button to be invisible
                myTurnBtn.setVisibility(View.INVISIBLE);
            }
        });
    }

    private void initalWork() {
        btnOnOff = findViewById(R.id.onOff);
        btnDiscover = findViewById(R.id.discover);
        btnSend = findViewById(R.id.sendButton);
        listView = findViewById(R.id.peerListView);
        read_msg_box = findViewById(R.id.readMsg);
        connectionStatus = findViewById(R.id.connectionStatus);
        writeMsg = findViewById(R.id.writeMsg);
        myTurnBtn = findViewById(R.id.myTurnBtn);

        wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); //this class provides the API for managing wifi peer to peer connectivity
        //anythign regarding the wifi p2p, this manager is used
        mChannel = mManager.initialize(this, getMainLooper(), null); //a channel that connects the application to the wifi p2p framework
        //most p2p operations require a channel as an argument

        mReceiver = new WifiDirectBroadcastReceiver(mManager, mChannel, this);

        mIntentFilter = new IntentFilter();
        //add all four actions
        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

      //  myTurnBtn =findViewById(R.id.myTurnBtn);


    }

    //gathering and displaying devices available
    WifiP2pManager.PeerListListener peerListListener = new WifiP2pManager.PeerListListener() {
        @Override
        public void onPeersAvailable(WifiP2pDeviceList peerList) {
            if (!peerList.getDeviceList().equals(peers)) { //if the previous list != the current list
                peers.clear(); //clear the list
                peers.addAll(peerList.getDeviceList()); //add all avaailable peers

                //initialise deviceNameArray and deviceArray with a size of as many devices that have been found and stored in peers ArrayList
                deviceNameArray = new String[peerList.getDeviceList().size()];
                deviceArray = new WifiP2pDevice[peerList.getDeviceList().size()];

                int index = 0;
                //we have a peerList and two arrays
                //using the peerList, we can add all the devices in the two arrays
                for (WifiP2pDevice device : peerList.getDeviceList()) {  //for each device in the peerList.getDeviceList()
                    //each iteration, the value of a device is stored in the device variable
                    deviceNameArray[index] = device.deviceName; //add all devices from deviceNameArray - storing the deviceName
                    deviceArray[index] = device;  //add all devices from deviceArray
                    index++;
                    Log.d(TAG, "looping through devices: " +device);

                    //when loop is finished:
                    //we have name of all devices in the deviceNameArray
                    //we have all device objects in the deviceArray
                }

                //shows the list of devices in the ListView
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1
                        , deviceNameArray);
                listView.setAdapter(adapter);
            }
            if (peers.size() == 0) {
                Toast.makeText(getApplicationContext(), "No devices found", Toast.LENGTH_SHORT).show();
                return;
            }
        }
    };

    //get information about host and client servers and manage sending and recieving data
    WifiP2pManager.ConnectionInfoListener connectionInfoListener = new WifiP2pManager.ConnectionInfoListener() {
        @Override
        public void onConnectionInfoAvailable(WifiP2pInfo info) {
            final InetAddress groupOwnerAddress = info.groupOwnerAddress; //used for sending and receiving data

            //set groupOwn as the Host
            if (info.groupFormed && info.isGroupOwner) {
                connectionStatus.setText("Host");
                myTurnBtn.setVisibility(View.VISIBLE);
                serverClass = new ServerClass();
                serverClass.start();
            } else if (info.groupFormed) {
                connectionStatus.setText("Client");
                clientClass = new ClientClass(groupOwnerAddress);
                clientClass.start();
            }
        }
    };

    //register the broadcast recevier
    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(mReceiver, mIntentFilter);
    }

    //unregister the broadcast receiver
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mReceiver);
    }


    public class ServerClass extends Thread {

        Socket socket;
        ServerSocket serverSocket;

        @Override
        public void run() {
            try {
                serverSocket = new ServerSocket(8888); //port must always be the same - can choose any number
                socket = serverSocket.accept(); //socket is ready to accept message
                sendReceive = new SendReceive(socket);
                sendReceive.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private class SendReceive extends Thread {
        private Socket socket;
        private InputStream inputStream;
        private OutputStream outputStream;

        //constructor
        public SendReceive(Socket skt) {
            socket = skt;
            try {
                inputStream = socket.getInputStream();
                outputStream = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }


        }
        //override run method
        @Override
        public void run() {
            byte[] buffer = new byte[1024]; //can choose any value
            int bytes;

            while (socket != null) { //always read to receive message
                try {
                    bytes = inputStream.read(buffer); //buffer contains the message, bytes contains the number of bytes in the message
                    if (bytes > 0) {
                        handler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();
                        //handler used to deal with threading issues
                        //obtain message and send the data
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //method to send data
        public void write(byte[] bytes) {
            try {
                outputStream.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public class ClientClass extends Thread {

        Socket socket;
        String hostAddress;

        //hostAddress is provided at runtime when ClientClass is created
        public ClientClass(InetAddress hostAddress) {
            this.hostAddress = hostAddress.getHostAddress();
            socket = new Socket();
        }

        @Override
        public void run() {
            try {
                socket.connect(new InetSocketAddress(hostAddress, 8888), 500); //same port number as server side
                sendReceive = new SendReceive(socket);
                sendReceive.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


Приемник широковещания:

 private WifiP2pManager mManager;
    private WifiP2pManager.Channel mChannel;
    private MainActivity mActivity;  //think about how this is used and how this can be possible with my app, on the Gameplay activity???

    /**
     * Constructor with args
     * @param manager
     * @param channel
     * @param activity
     */
    public WifiDirectBroadcastReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel, MainActivity activity) {
        mManager = manager;
        mChannel = channel;
        mActivity = activity;

    }
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction(); //use this to check the current action

        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) { //indicates whether Wi-Fi p2p is enabled
            int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1); //we will either have the value of the state or the default -1

            if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) { //if wifi is enabled
                Toast.makeText(context, "Wifi is ON", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(context, "Wifi is OFF", Toast.LENGTH_SHORT).show();
            }

        } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { //indicates that the available peer list has changed
            //do something - get a list of peers by calling WifiP2pManager.requestPeers()
            if (mManager!=null) {
                mManager.requestPeers(mChannel, mActivity.peerListListener);  //pass in peerListListener from mainActivity
            }

        } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { //indicates the state of the wifi p2p connectivity has changed
            //do something - respond to a new connection or disconnections
            if (mManager == null) {
                return;
            }

            NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
            if (networkInfo.isConnected()) {
                mManager.requestConnectionInfo(mChannel,mActivity.connectionInfoListener);
            } else {
                mActivity.connectionStatus.setText("Device Disconnected");
            }
        } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) { //indicates this device's configuration details have changed
            //do something - respond to this device's wifi state changing
        }

    }
}
...