Android NSD未发现所有服务
我正在尝试使用Android本机服务发现来运行应用程序,但有时当我运行应用程序时,它无法从我的网络中发现所有服务。我使用四个galaxy nexus运行代码,大多数情况下,它们同时发现了不同数量的服务 基本上,我使用ServerSocket运行服务:Android NSD未发现所有服务,android,zeroconf,service-discovery,wifi-direct,Android,Zeroconf,Service Discovery,Wifi Direct,我正在尝试使用Android本机服务发现来运行应用程序,但有时当我运行应用程序时,它无法从我的网络中发现所有服务。我使用四个galaxy nexus运行代码,大多数情况下,它们同时发现了不同数量的服务 基本上,我使用ServerSocket运行服务: ServerSocket server = new ServerSocket(0); Log.i(TAG, "IP " + server.getInetAddress() + ", running on port " + serve
ServerSocket server = new ServerSocket(0);
Log.i(TAG, "IP " + server.getInetAddress()
+ ", running on port " + server.getLocalPort());
Intent intent = new Intent(MySocket.this,
MyPresence.class);
intent.putExtra("PORT", server.getLocalPort());
startService(intent);
然后,我使用NsdManager中的registerService方法发布它:
NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setServiceName(Build.SERIAL + "-" + new Date().getTime());
serviceInfo.setServiceType(SERVICE_TYPE);
serviceInfo.setPort(port);
mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD,
mRegistrationListener);
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
mDiscoveryListener);
为了发现服务,我使用了来自NsdManager的discoverServices方法:
NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setServiceName(Build.SERIAL + "-" + new Date().getTime());
serviceInfo.setServiceType(SERVICE_TYPE);
serviceInfo.setPort(port);
mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD,
mRegistrationListener);
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
mDiscoveryListener);
使用mDiscoveryListener,如下所示:
mDiscoveryListener = new NsdManager.DiscoveryListener() {
@Override
public void onDiscoveryStarted(String regType) {
Log.d(TAG, "Service discovery started");
}
@Override
public void onServiceFound(NsdServiceInfo service) {
Log.d(TAG, "Service discovery success");
Log.d(TAG, String.format("%s %s %s %d",
service.getServiceName(), service.getServiceType(),
service.getHost(), service.getPort()));
if (!service.getServiceType().contains(SERVICE_TYPE)) {
Log.d(TAG,
"Unknown Service Type: " + service.getServiceType());
} else if (service.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same machine: " + mServiceName);
} else {
mNsdManager.resolveService(service, mResolveListener);
}
}
@Override
public void onServiceLost(NsdServiceInfo service) {
Log.e(TAG, "service lost" + service);
}
@Override
public void onDiscoveryStopped(String serviceType) {
Log.i(TAG, serviceType + " Discovery stopped: " + serviceType);
}
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, serviceType + " Discovery failed: Error code:"
+ errorCode);
mNsdManager.stopServiceDiscovery(this);
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, serviceType + " Discovery failed: Error code:"
+ errorCode);
mNsdManager.stopServiceDiscovery(this);
}
};
我做错什么了吗?有人知道这方面的解决方案或解决方法吗?我也有同样的问题,请帮助。尝试使用:)我担心在实现中仍然存在导致它错过服务的bug。我已经用多台Android设备和一台MacBook做了几天的测试,但它不是一直都能工作。我在Android bug tracker中记录了我在bug报告中的发现:
我倾向于认为整个NSD在Android中的实现一定有点不稳定。我还有一个简单的活动来演示生命周期(没有打开任何套接字),有时它可以工作,有时它不工作。我就是不明白。如果任何人有一些见解,以下是活动: 另一方面,基于Wifi Direct的NSD对我来说似乎非常可靠:
请注意,这两个活动都没有任何资源,因此只需使用适当的权限将活动添加到清单中即可 现在回答这个问题可能有点晚了,但我在他们的开发者网站上找到了一个很好的针对android give的NSD解决方案。我做了一些修改,效果非常好
public class NsdClient {
private Context mContext;
private NsdManager mNsdManager;
NsdManager.DiscoveryListener mDiscoveryListener;
//To find all the available networks SERVICE_TYPE = "_services._dns-sd._udp"
public static final String SERVICE_TYPE = "_hap._tcp.";
public static final String TAG = "NsdClient";
private static ArrayList<NsdServiceInfo> ServicesAvailable = new ArrayList<>();
public NsdClient(Context context) {
mContext = context;
mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
}
public void initializeNsd() {
initializeDiscoveryListener();
}
public void initializeDiscoveryListener() {
mDiscoveryListener = new NsdManager.DiscoveryListener() {
@Override
public void onDiscoveryStarted(String regType) {
Log.d(TAG, "Service discovery started " + regType);
}
@Override
public void onServiceFound(NsdServiceInfo service) {
Log.d(TAG, "Service discovery success " + service);
AVAILABLE_NETWORKS.add(service);
if (!service.getServiceType().equals(SERVICE_TYPE)) {
Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
} else if (service.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same Machine: " + mServiceName);
} else if (service.getServiceName().contains(mServiceName)) {
Log.d(TAG, "Resolving Services: " + service);
mNsdManager.resolveService(service, new initializeResolveListener());
}
}
@Override
public void onServiceLost(NsdServiceInfo service) {
Log.e(TAG, "service lost" + service);
if (ServicesAvailable.equals(service)) {
ServicesAvailable = null;
}
}
@Override
public void onDiscoveryStopped(String serviceType) {
Log.i(TAG, "Discovery stopped: " + serviceType);
}
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
};
}
public class initializeResolveListener implements NsdManager.ResolveListener {
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.e(TAG, "Resolve failed " + errorCode);
switch (errorCode) {
case NsdManager.FAILURE_ALREADY_ACTIVE:
Log.e(TAG, "FAILURE ALREADY ACTIVE");
mNsdManager.resolveService(serviceInfo, new initializeResolveListener());
break;
case NsdManager.FAILURE_INTERNAL_ERROR:
Log.e(TAG, "FAILURE_INTERNAL_ERROR");
break;
case NsdManager.FAILURE_MAX_LIMIT:
Log.e(TAG, "FAILURE_MAX_LIMIT");
break;
}
}
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
Log.e(TAG, "Resolve Succeeded. " + serviceInfo);
if (serviceInfo.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same IP.");
return;
}
}
}
public void stopDiscovery() {
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
public List<NsdServiceInfo> getChosenServiceInfo() {
return ServicesAvailable;
}
public void discoverServices() {
mNsdManager.discoverServices(
SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
}
公共类NSD客户端{
私有上下文;
私人NSD经理mNsdManager;
NsdManager.DiscoveryListener mDiscoveryListener;
//要查找所有可用网络服务,请键入=“\u服务.\u dns-sd.\u udp”
公共静态最终字符串服务\u TYPE=“\u hap.\u tcp.”;
公共静态最终字符串TAG=“NsdClient”;
private static ArrayList ServicesAvailable=new ArrayList();
公共NSD客户端(上下文){
mContext=上下文;
mNsdManager=(NsdManager)context.getSystemService(context.NSD_SERVICE);
}
public void initializeNsd(){
初始化DiscoveryListener();
}
public void initializeDiscoveryListener(){
mDiscoveryListener=新的NsdManager.DiscoveryListener(){
@凌驾
public void onDiscoveryStarted(字符串regType){
Log.d(标记“服务发现已启动”+regType);
}
@凌驾
公共无效OnServiceFund(NsdServiceInfo服务){
Log.d(标签“服务发现成功”+服务);
可用网络。添加(服务);
如果(!service.getServiceType().equals(服务类型)){
Log.d(标记“未知服务类型:”+Service.getServiceType());
}else if(service.getServiceName().equals(MSServiceName)){
Log.d(标签,“同一台机器:+mServiceName”);
}else if(service.getServiceName()包含(msServiceName)){
Log.d(标签“解析服务:”+服务);
mNsdManager.resolveService(服务,新的初始化项resolveListener());
}
}
@凌驾
ServiceLost上的公共void(NsdServiceInfo服务){
日志e(标签“服务丢失”+服务);
if(服务可用。等于(服务)){
ServicesAvailable=null;
}
}
@凌驾
public void onDiscoveryStopped(字符串服务类型){
Log.i(标记“发现已停止:“+serviceType”);
}
@凌驾
public void onStartDiscoveryFailed(字符串服务类型,int errorCode){
Log.e(标记“发现失败:错误代码:”+errorCode);
mNsdManager.stopServiceDiscovery(此);
}
@凌驾
public void onStopDiscoveryFailed(字符串服务类型,整数错误代码){
Log.e(标记“发现失败:错误代码:”+errorCode);
mNsdManager.stopServiceDiscovery(此);
}
};
}
公共类initializeResolveListener实现NsdManager.ResolveListener{
@凌驾
public void onresolvefiled(NsdServiceInfo serviceInfo,int errorCode){
Log.e(标签“解决失败”+错误代码);
开关(错误代码){
案例NsdManager.FAILURE_已处于活动状态:
Log.e(标签“故障已激活”);
mNsdManager.resolveService(serviceInfo,新的初始值设定项resolveListener());
打破
案例NsdManager.FAILURE\u内部错误:
Log.e(标记“故障\内部错误”);
打破
案例NsdManager.FAILURE_MAX_LIMIT:
Log.e(标签“故障最大极限”);
打破
}
}
@凌驾
已解决服务上的公共无效(NsdServiceInfo服务信息){
Log.e(标记“Resolve Successed.”+serviceInfo);
if(serviceInfo.getServiceName().equals(msservicename)){
Log.d(标签“相同IP”);
返回;
}
}
}
公共发现{
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
公共列表getChosenServiceInfo(){
返回服务可用;
}
公共空间发现服务(){
mNsdManager.discoverServices(
服务类型、NsdManager.PROTOCOL、DNS、mDiscoveryListener);
}
}
希望这有助于发现连接网络的所有服务只需更改正在发现的服务类型
public static final String SERVICE_TYPE = "_services._dns-sd._udp";
我发现未发现设备存在同样的问题,并能够通过在发现服务之前获取WifiManager多播锁来解决该问题:
val multicastLock: WifiManager.MulticastLock = (mContext.getSystemService(Context.WIFI_SERVICE) as WifiManager).createMulticastLock(TAG)
multicastLock.setReferenceCounted(true)
multicastLock.acquire()
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener)
mNsdManager.stopServiceDiscovery(mDiscoveryListener)
multicastLock.release()
然后在发现服务后释放锁:
val multicastLock: WifiManager.MulticastLock = (mContext.getSystemService(Context.WIFI_SERVICE) as WifiManager).createMulticastLock(TAG)
multicastLock.setReferenceCounted(true)
multicastLock.acquire()
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener)
mNsdManager.stopServiceDiscovery(mDiscoveryListener)
multicastLock.release()
当我在网络中有两台设备具有相同的N时,我试图修复一个似乎弹出的NPE时,我在你的帖子上出现了一个摄像头