Wifi P2P服务发现行为异常。我看到间歇性的问题,其中DNSSD侦听器不总是被调用,因此我不知道附近运行同一应用程序的设备。我正在使用以下两个API-一个用于注册要被其他设备发现的服务,另一个用于发现在其他设备上运行的附近服务。任何想法,如果我在这里做错了什么,或者在我调用这些API之前是否需要进行一些特定的其他android API调用序列,以确保每当有新服务注册甚至某项服务时,始终会调用侦听器在调用API以发现本地服务之前已注册。
注册本地服务的API:
private void registerService() {
Map<String, String> values = new HashMap<String, String>();
values.put("name", "Steve");
values.put("port", "8080");
WifiP2pServiceInfo srvcInfo = WifiP2pDnsSdServiceInfo.newInstance(mMyDevice.deviceName, "_http._tcp", values);
manager.addLocalService(channel, srvcInfo, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Toast.makeText(WiFiDirectActivity.this, "Local service added successfully",
Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reasonCode) {
Toast.makeText(WiFiDirectActivity.this, "Local service addition failed : " + reasonCode,
Toast.LENGTH_SHORT).show();
}
});
}
用于发现本地服务的API:
public void discoverService() {
manager.clearServiceRequests(channel, null);
DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
@Override
/* Callback includes:
* fullDomain: full domain name: e.g "printer._ipp._tcp.local."
* record: TXT record data as a map of key/value pairs.
* device: The device running the advertised service.
*/
public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {
Log.d(TAG, "DnsSdTxtRecord available -" + record.toString());
}
};
DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
@Override
public void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice resourceType) {
Log.d(TAG, "onBonjourServiceAvailable " + instanceName);
}
};
manager.setDnsSdResponseListeners(channel, servListener, txtListener);
WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
manager.addServiceRequest(channel, serviceRequest, new ActionListener() {
@Override
public void onSuccess() {
// Success!
Log.d(TAG, "addServiceRequest success");
}
@Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
Log.d(TAG, "addServiceRequest failure with code " + code);
}
});
manager.discoverServices(channel, new ActionListener() {
@Override
public void onSuccess() {
// Success!
Log.d(TAG, "discoverServices success");
}
@Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
if (code == WifiP2pManager.P2P_UNSUPPORTED) {
Log.d(TAG, "P2P isn't supported on this device.");
} else {
Log.d(TAG, "discoverServices failure");
}
}
});
}
注意:经理和 channel 初始化为
WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);
最佳答案
WifiP2p
(一般而言):
不久前,我正在开发一个应用程序,该应用程序具有一个基于WifiP2p
和Service Broadcasting/Discovery
的非常复杂的网络连接系统。基于这种经验,我已经在SO上写了几篇关于难度,磨损和问题的文章。这是其中的两个(它们充满了我通过WifiP2p
和Service Discovery
本身获得的有关WifiP2p
的内部知识):
Why is discovering peers for Android WifiDirect so unreliable
Wi-fi P2P. Inform all peers available of some event
我建议您阅读我的两个答案(即使它们更多地关注WifiP2p
本身)。他们应该给您一些有关使用WifiP2p Service Discovery
时应寻找的内容的观点。
我可以轻松地说,如果您要构建一个高效,相对可靠且健壮的WifiP2p
连接系统(尤其是Service Discovery
),则必须付出很多努力。
WifiP2p Service Discovery
:
为了更好地回答您的确切问题,我将告诉您我做了什么(与您不同)以使Service Discovery
非常可靠地工作。
1.广播Service
:
首先:在注册Service
(使用addLocalService
方法)之前,您应该使用WifiP2pManager
的clearLocalServices
方法。并且重要的是,如果侦听器传入的是用addLocalService
回调返回的clearLocalServices
,则只应调用ojit_roji调用。
尽管这可以很好地设置广播,但我发现其他节点并不总是能够检测到广播的onSuccess
(尤其是当这些节点在注册本地service
时尚未主动检测服务时,但后来“加入”了) )。我找不到100%可靠地解决此问题的方法。相信我,我可能正在尝试所有与Service
相关的事情。不,WifiP2p
-clearLocalServices
序列并没有真正令人满意的结果。或更重要的是:做一些不同的事情效果更好。我决定要做的是,在成功添加本地服务(来自addLocalService
的onSuccess
回调)之后,我启动了一个addLocalService
,它将定期调用Thread
的方法WifiP2pManager
。这似乎迫使重新广播所有discoverPeers
信息。
所以...基本上,您的广播代码的基础看起来应该更像这样(请注意,如果网络连接系统正确,请注意,我将在此处发布的每段代码都将去除所有“检查”)状态,则应自行设计以使其最适合您的解决方案):
public void startBroadcastingService(){
mWifiP2pManager.clearLocalServices(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
mWifiP2pManager.addLocalService(mWifiP2pChannel, mWifiP2pServiceInfo,
new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// service broadcasting started
mServiceBroadcastingHandler
.postDelayed(mServiceBroadcastingRunnable,
SERVICE_BROADCASTING_INTERVAL);
}
@Override
public void onFailure(int error) {
// react to failure of adding the local service
}
});
}
@Override
public void onFailure(int error) {
// react to failure of clearing the local services
}
});
}
service
应该在哪里:private Runnable mServiceBroadcastingRunnable = new Runnable() {
@Override
public void run() {
mWifiP2pManager.discoverPeers(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(int error) {
}
});
mServiceBroadcastingHandler
.postDelayed(mServiceBroadcastingRunnable, SERVICE_BROADCASTING_INTERVAL);
}
};
2.发现
mServiceBroadcastingRunnable
:为了发现您的
Service
,我使用了类似的方法。既可以设置发现功能,也可以尝试强制service
进行“重新发现”。通过以下三种
services
方法的序列进行设置:WifiP2pManager
,removeServiceRequest
,addServiceRequest
它们以这种精确的顺序被调用,只有在前一个方法通过
discoverServices
回调“返回”之后,才调用特定的方法(确切地说是第二个或第三个方法)。onSuccess
的重新发现是通过直观的方法执行的(只是通过重复上述顺序:services
-> removeServiceRequest
-> addServiceRequest
)。我的代码基础看起来像这样(要开始
discoverServices
,我首先要调用Service Discovery
然后是prepareServiceDiscovery()
):public void prepareServiceDiscovery() {
mWifiP2pManager.setDnsSdResponseListeners(mWifiP2pChannel,
new WifiP2pManager.DnsSdServiceResponseListener() {
@Override
public void onDnsSdServiceAvailable(String instanceName,
String registrationType, WifiP2pDevice srcDevice) {
// do all the things you need to do with detected service
}
}, new WifiP2pManager.DnsSdTxtRecordListener() {
@Override
public void onDnsSdTxtRecordAvailable(
String fullDomainName, Map<String, String> record,
WifiP2pDevice device) {
// do all the things you need to do with detailed information about detected service
}
});
mWifiP2pServiceRequest = WifiP2pDnsSdServiceRequest.newInstance();
}
private void startServiceDiscovery() {
mWifiP2pManager.removeServiceRequest(mWifiP2pChannel, mWifiP2pServiceRequest,
new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
mWifiP2pManager.addServiceRequest(mWifiP2pChannel, mWifiP2pServiceRequest,
new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
mWifiP2pManager.discoverServices(mWifiP2pChannel,
new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
//service discovery started
mServiceDiscoveringHandler.postDelayed(
mServiceDiscoveringRunnable,
SERVICE_DISCOVERING_INTERVAL);
}
@Override
public void onFailure(int error) {
// react to failure of starting service discovery
}
});
}
@Override
public void onFailure(int error) {
// react to failure of adding service request
}
});
}
@Override
public void onFailure(int reason) {
// react to failure of removing service request
}
});
}
startServiceDiscovery()
只是:private Runnable mServiceDiscoveringRunnable = new Runnable() {
@Override
public void run() {
startServiceDiscovery();
}
};
所有这些使我的系统运行良好。它还不是很完美,但是由于缺乏有关该主题的文档,我想我不能做更多的事情来改进它。
如果您测试这种方法,请务必告诉我它如何为您工作(或是否为您工作;))。