无法使用Wifi Direct启动和发现特定服务

时间:2013-08-16 22:00:16

标签: android android-service android-wifi wifi-direct

我对Android编程很新。但是我现在已经工作了一个多星期了,而且它开始变得愚蠢了。

我的想法是我想使用Wifi Direct连接两台设备。但我只想连接那些运行我的应用程序的人。此外,我希望用户能够看到其他设备的一些信息(例如用户名),而不仅仅是WifiP2pDevice中包含的MAC或Android_XXXX名称。这就是为什么我决定寻找其他设备的设备应该启动应用服务并搜索同时也在广播此服务的对等设备。

问题(我正在使用两个真实设备进行测试)是,即使它们运行完全相同的代码,也只有其中一个获得服务发现回调(下面的onDnsSd ...监听器)。所以,一方以正确的方式行事,而不是另一方。此外,我正在获得“旧”服务,这意味着显然每次我开始服务(即使我取消以前开始的服务),该服务似乎仍然至少在几分钟内播出。

我包含了我的代码的缩短版本:

public class MoveFlufietsDialogFragment extends DialogFragment implements ChannelListener, DeviceActionListener {

    public final HashMap<String, FlufietsPeer> mBuddies = new HashMap<String, FlufietsPeer>();

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    ...
        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);

        mManager = (WifiP2pManager) getActivity().getSystemService(Context.WIFI_P2P_SERVICE);
        mChannel = mManager.initialize(getActivity(), getActivity().getMainLooper(), null);
        ...
        startRegistration();
        discoverFlufietsService();
        ...
    }


    public void discoverFlufietsService() {
        DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
            @Override
            public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {
                // This and the next listener are only called in one of the devices.
                String serviceName = (String) record.get("serviceName");
                if ((serviceName != null) && (serviceName.equals("flufiets")) {
                    // I put the record data in the mBuddies HashMap.
                    ...
                    mBuddies.put(device.deviceAddress, myPeerDataStructure);
                }
            }
        };

        DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
            @Override
            public void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice resourceType) {
                if (mBuddies.containsKey(resourceType.deviceAddress)) {
                    FlufietsPeer flufietsPeer = mBuddies.get(resourceType.deviceAddress);
                    WiFiPeerListAdapter adapter = ((WiFiPeerListAdapter) mFragmentList.getListAdapter());
                    adapter.add(flufietsPeer);
                    adapter.notifyDataSetChanged();
                }
            }
        };

        mManager.setDnsSdResponseListeners(mChannel, servListener, txtListener);

        WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
        mManager.addServiceRequest(mChannel, serviceRequest, new ActionListener() {
            // onSuccess/onFailure toasts.
        });

        mManager.discoverServices(mChannel, new WifiP2pManager.ActionListener() {
            // onSuccess/onFailure toasts.
        });
    }

    public void startRegistration() {
        mManager.clearLocalServices(mChannel, new ActionListener() {
            // onSuccess/onFailure toasts.
        });

        Map record = new HashMap();
        record.put("serviceName", "flufiets");
        ...

        WifiP2pDnsSdServiceInfo serviceInfo = WifiP2pDnsSdServiceInfo.newInstance(flufietsService, "_tcp", record);

        mManager.addLocalService(mChannel, serviceInfo, new ActionListener() {
            // onSuccess/onFailure toasts.
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
        getActivity().registerReceiver(mReceiver, mIntentFilter);
    }

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

    @Override
    public void onStop() {
        super.onStop();
        mManager.clearLocalServices(mChannel, new ActionListener() {
            // onSuccess/onFailure toasts.
        });
    }

    ...
}

这个问题似乎与设备本身无关(有时它可以工作,有时却没有,但总是只在其中一个)。我怀疑它与尝试发现我们自己正在播放的服务或者由两个设备提供相同的服务有关。我已经尝试更改服务的名称,因此每个设备都会提供“发送”或“接收”服务,但它不起作用。我只在其中一个设备中获得了调用(onDnsSd ...)的回调。

关于获取旧服务的事情,当我总是清除它们时,很奇怪(我在服务记录数据中包含一个时间戳,我总是可以丢弃除了最后一个,但似乎不符合逻辑)

有什么想法吗?任何帮助都会非常感激,因为编写应用程序不再有趣(: - )=

非常感谢!

1 个答案:

答案 0 :(得分:0)

您需要等到clearLocalService调用成功,然后再添加本地服务。因此,将addLocalService调用放入clearLocalServices的onSuccess回调中。