Wi-Fi Direct Android

2020-02-26 02:42发布

问题:

I want to transfer files between 2 devices via Wi-Fi Direct.

I wanted to do the same thing as in WifiDirectDemo, but I can't transfer data from the group owner to the other device, so I tried this: each time when one of the devices clicks connect, the other device is set as the group owner, so on each connection the device who asks for connection is always the client and can send data.

The problem with this is that Android always remembers the first group created and therefore its group owner. In other words, what I did only works the first time unless I go to settings and forget the group created by the first connection.

I know that by using the disconnect button, the Wi-Fi group is removed, but the Android system puts it in remembered groups and uses its setting (group owner negotiation) when a new connection is to be made.

The second thing I tried was to create a ServerSocket on each device (on another port), so this way both the group owner and the other device would be clients and servers at the same time. I don't know if the group owner can be set as a client, but I cant create a ServerSocket on both devices. Here is my code:

<pre>
  @Override
    public void onConnectionInfoAvailable(final WifiP2pInfo info) {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
        this.info = info;
        this.getView().setVisibility(View.VISIBLE);

        // The owner IP is now known.
        TextView view = (TextView) mContentView.findViewById(R.id.group_owner);
        view.setText( getResources().getString(R.string.group_owner_text)
                + ((info.isGroupOwner == true) ? getResources().getString(R.string.yes)
                        : getResources().getString(R.string.no)));

        // InetAddress from WifiP2pInfo struct.
        view = (TextView) mContentView.findViewById(R.id.device_info);
        view.setText("Group Owner IP - " + info.groupOwnerAddress.getHostAddress());


        // After the group negotiation, we assign the group owner as the file
        // server. The file server is single threaded, single connection server
        // socket.
        if (info.groupFormed && info.isGroupOwner) {
            new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text),8988)
                    .execute();
            mContentView.findViewById(R.id.btn_start_client).setVisibility(View.VISIBLE);
            Log.d(WiFiDirectActivity.TAG, "serveur8988cree");
        } else if (info.groupFormed) {
            // The other device acts as the client. In this case, we enable the
            // Get file button.
            // In this case we create a server socket on another port
            new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text),8987)
            .execute();
            mContentView.findViewById(R.id.btn_start_client).setVisibility(View.VISIBLE);
            Log.d(WiFiDirectActivity.TAG, "serveur8987cree");
            ((TextView) mContentView.findViewById(R.id.status_text)).setText(getResources()
                    .getString(R.string.client_text));
        }
</pre>

Thanks for help.

回答1:

You can delete all groups through reflection but, it's bit of a hack and class members might change later

 private void deletePersistentInfo() {
    try {

        Class persistentInterface = null;

        //Iterate and get class PersistentGroupInfoListener
        for (Class<?> classR : WifiP2pManager.class.getDeclaredClasses()) {
            if (classR.getName().contains("PersistentGroupInfoListener")) {
                persistentInterface = classR;
                break;
            }

        }

        final Method deletePersistentGroupMethod = WifiP2pManager.class.getDeclaredMethod("deletePersistentGroup", new Class[]{Channel.class, int.class, ActionListener.class});




        //anonymous class to implement PersistentGroupInfoListener which has a method, onPersistentGroupInfoAvailable
        Object persitentInterfaceObject =
                java.lang.reflect.Proxy.newProxyInstance(persistentInterface.getClassLoader(),
                        new java.lang.Class[]{persistentInterface},
                        new java.lang.reflect.InvocationHandler() {
                            @Override
                            public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws java.lang.Throwable {
                                String method_name = method.getName();

                                if (method_name.equals("onPersistentGroupInfoAvailable")) {
                                    Class wifiP2pGroupListClass =  Class.forName("android.net.wifi.p2p.WifiP2pGroupList");
                                    Object wifiP2pGroupListObject = wifiP2pGroupListClass.cast(args[0]);

                                    Collection<WifiP2pGroup> wifiP2pGroupList = (Collection<WifiP2pGroup>) wifiP2pGroupListClass.getMethod("getGroupList", null).invoke(wifiP2pGroupListObject, null);
                                    for (WifiP2pGroup group : wifiP2pGroupList) {
                                        deletePersistentGroupMethod.invoke(wifiP2pManager, channel, (Integer) WifiP2pGroup.class.getMethod("getNetworkId").invoke(group, null), new ActionListener() {
                                            @Override
                                            public void onSuccess() {
                                                //All groups deleted
                                            }

                                            @Override
                                            public void onFailure(int i) {

                                            }
                                        });
                                    }
                                }

                                return null;
                            }
                        });

        Method requestPersistentGroupMethod =
                WifiP2pManager.class.getDeclaredMethod("requestPersistentGroupInfo", new Class[]{Channel.class, persistentInterface});

        requestPersistentGroupMethod.invoke(wifiP2pManager, channel, persitentInterfaceObject);

    } catch (Exception ex) {
        ex.printStackTrace();
    }
}


回答2:

To send data you need to know the IP address (not the device address) of the receiver. For the P2P client, the IP address of group_owner is available in the WifiP2pInfo variable, so it can use this to send data to the group owner. If the group owner knows the IP address of the P2P client to which it wants to send data, then it can also send files. This can be achieved in two ways.

  1. Group owner assigns the IP addresses to the clients and stores the information about it.
  2. Every newly added client sends its IP address to the group owner at the time of joining the group.