2

我对 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...) 的回调。

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

有任何想法吗?任何帮助将不胜感激,因为编写应用程序不再有趣 (:-)=

非常感谢!

4

1 回答 1

0

您需要等到 clearLocalService 调用成功后再添加本地服务。所以把 addLocalService 调用放到 clearLocalServices 的 onSuccess 回调中。

于 2014-01-28T05:30:11.467 回答