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

Android 无法使用Wifi Direct启动和发现特定服务,android,android-service,android-wifi,wifi-direct,Android,Android Service,Android Wifi,Wifi Direct,我对Android编程相当陌生。但我已经为此工作了一个多星期了,它开始发出嘘声 我的想法是,我想使用Wifi Direct连接两台设备。但我只想连接到那些运行我的应用程序的设备。此外,我希望用户能够看到其他设备的一些信息(例如用户名),而不仅仅是wifip2p设备中包含的MAC或Android_XXXX名称。这就是为什么我决定寻找其他设备的设备,应该启动应用程序服务并搜索同时广播此服务的对等设备 问题是(我正在用两个真实的设备进行测试),即使它们运行完全相同的代码,但其中只有一个正在获取服务发现

我对Android编程相当陌生。但我已经为此工作了一个多星期了,它开始发出嘘声

我的想法是,我想使用Wifi Direct连接两台设备。但我只想连接到那些运行我的应用程序的设备。此外,我希望用户能够看到其他设备的一些信息(例如用户名),而不仅仅是wifip2p设备中包含的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.
        });
    }

    ...
}
公共类MoveFlufietsDialogFragment扩展DialogFragment实现ChannelListener、DeviceActionListener{
public final HashMap mBuddies=新HashMap();
@凌驾
创建对话框上的公共对话框(Bundle savedInstanceState){
...
minentfilter.addAction(WifiP2pManager.WIFI\u P2P\u STATE\u CHANGED\u ACTION);
minentfilter.addAction(WifiP2pManager.WIFI\u P2P\u PEERS\u CHANGED\u ACTION);
minentfilter.addAction(WifiP2pManager.WIFI\u P2P\u连接\u更改\u操作);
MinentFilter.addAction(WifiP2pManager.WIFI\u P2P\u此设备\u更改\u操作);
mManager=(WifiP2pManager)getActivity().getSystemService(Context.WIFI\u P2P\u SERVICE);
mChannel=mManager.initialize(getActivity(),getActivity().getMainLooper(),null);
...
startRegistration();
DiscoveryFlufietsService();
...
}
公共无效发现FlufietsService(){
DnsSdTxtRecordListener txtListener=新的DnsSdTxtRecordListener(){
@凌驾
公共无效onDnsSdTxtRecordAvailable(字符串fullDomain、映射记录、WifiP2pDevice设备){
//此侦听器和下一个侦听器仅在其中一个设备中调用。
String serviceName=(String)record.get(“serviceName”);
if((serviceName!=null)&(serviceName.equals(“flufiets”)){
//我将记录数据放在mBuddies哈希映射中。
...
mBuddies.put(device.deviceAddress,myPeerDataStructure);
}
}
};
DnsSdServiceResponseListener servListener=新的DnsSdServiceResponseListener(){
@凌驾
public void onDnsSdServiceAvailable(字符串instanceName、字符串注册类型、WifiP2pDevice resourceType){
if(mBuddies.containsKey(resourceType.deviceAddress)){
FlufietsPeer FlufietsPeer=mBuddies.get(resourceType.deviceAddress);
WiFiPeerListAdapter=((WiFiPeerListAdapter)MFFragmentList.getListAdapter());
adapter.add(flufietsPeer);
adapter.notifyDataSetChanged();
}
}
};
mssdresponseListeners(mcchannel、servListener、txtListener);
WifiP2pDnsSdServiceRequest serviceRequest=WifiP2pDnsSdServiceRequest.newInstance();
mManager.addServiceRequest(mChannel、serviceRequest、new ActionListener(){
//onSuccess/onFailure祝酒。
});
discoverServices(mcchannel,新的WifiP2pManager.ActionListener(){
//onSuccess/onFailure祝酒。
});
}
公开作废startRegistration(){
clearLocalServices(mChannel,新ActionListener(){
//onSuccess/onFailure祝酒。
});
映射记录=新的HashMap();
记录。放置(“服务名称”、“flufiets”);
...
WifiP2pDnsSdServiceInfo serviceInfo=WifiP2pDnsSdServiceInfo.newInstance(flufietsService,“_-tcp”,记录);
mManager.addLocalService(mChannel、serviceInfo、newActionListener(){
//onSuccess/onFailure祝酒。
});
}
@凌驾
恢复时公开作废(){
super.onResume();
mReceiver=新的WiFiDirectBroadcastReceiver(mManager、mChannel、this);
getActivity().registerReceiver(mrReceiver,minentFilter);
}
@凌驾
公共无效暂停(){
super.onPause();
getActivity().取消注册接收方(mReceiver);
}
@凌驾
公共void onStop(){
super.onStop();
clearLocalServices(mChannel,新ActionListener(){
//onSuccess/onFailure祝酒。
});
}
...
}
问题似乎与设备本身无关(有时有效,有时无效,但总是只在其中一个设备中)。我怀疑这与试图发现我们自己正在广播的服务或两台设备提供相同的服务有关。我已尝试更改服务的名称,因此每个设备将提供“发送”或“接收”服务,但不起作用。我只收到名为(onDnsSd…)的回调在其中一个设备中

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

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


非常感谢!

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

Ha