Ответ 1
Чтобы открыть все службы подключенной сети, просто измените тип сервиса, который вы открываете,
public static final String SERVICE_TYPE = "_services._dns-sd._udp";
Я пытаюсь запустить приложение с помощью Android Native Service Discovery, но иногда, когда я запускаю приложение, он не обнаруживает всех сервисов из моей сети. Я запускаю код из https://github.com/joeluchoa/nsd, используя четыре галактики nexus и большую часть времени каждый из них открывает различное количество сервисов одновременно.
В основном я запускаю службу с помощью ServerSocket:
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);
Затем я публикую его с помощью метода registerService из NsdManager:
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);
Чтобы обнаружить службы, я использую метод DiscoverServices из NsdManager:
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);
}
};
Я делаю что-то неправильно? Кто-нибудь знает решение или обходное решение для этого?
Чтобы открыть все службы подключенной сети, просто измените тип сервиса, который вы открываете,
public static final String SERVICE_TYPE = "_services._dns-sd._udp";
У меня была та же проблема, переустановка помогла. Попробуйте использовать:)
Я боюсь, что в реализации все еще есть ошибки, которые заставляют его пропускать службы. Я провел пару дней тестирования с несколькими устройствами Android и MacBook, и он просто не работает все время. Я задокументировал свои результаты в отчете об ошибках в трекерах Android: https://code.google.com/p/android/issues/detail?id=178080
Я склонен думать, что вся реализация NSD в Android должна быть немного шелушащейся. У меня также есть простая активность, чтобы продемонстрировать жизненный цикл (не открываются сокеты), а иногда и работает, а иногда и не работает. Я просто не понимаю. Вот активность, если у кого-то есть понимание:
https://github.com/mholzel/Dump/blob/master/NetworkServiceDiscoveryViaWifi.java
С другой стороны, NSD, основанный на Wifi Direct, кажется мне очень надежным:
https://github.com/mholzel/Dump/blob/master/NetworkServiceDiscoveryViaWifiDirect.java
Обратите внимание, что ни одна из этих операций не имеет ресурсов, поэтому просто добавьте действия в свой манифест с соответствующими разрешениями.
Это может быть немного запоздалым для ответа, но я нашел хорошее решение для 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);
}
}
Надеюсь, это поможет