Implementación de Bonjour en Android
zeroconf jmdns (5)
¿Sabe por un hecho que la multidifusión está habilitada en su teléfono? Consulte http://home.heeere.com/tech-androidjmdns.html .
Y probablemente deberías buscar los servicios "_ipp._tcp.local" (o algo similar) en lugar de los servicios "_http.tcp". Pero eso es solo para probar, ¿verdad? :-)
Estoy tratando de implementar bonjour / zero conf en mi aplicación de Android. Estoy usando la biblioteca jmDns para buscar todos los dispositivos disponibles. Aquí está el código que estoy usando para buscar los dispositivos en la misma red:
public class ListDevices extends ListActivity {
JmDNS jmdns;
JmDNSImpl impl;
MulticastLock lock;
protected ServiceListener listener;
protected ServiceInfo info;
public ListView lv;
public ArrayList<String> deviceList;
public int cancel = 0;
public final static String TAG = "ListDevices";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
deviceList = new ArrayList<String>();
showAllPrinters();
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, deviceList));
lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(),
((TextView) view).getText(), Toast.LENGTH_SHORT).show();
}
});
this.listener = new ServiceListener() {
public void serviceAdded(ServiceEvent event) {
deviceList.add("Service added : " + event.getName() + "."
+ event.getType());
Log.v(TAG, "Service added : " + event.getName() + "."
+ event.getType());
}
public void serviceRemoved(ServiceEvent event) {
deviceList.add("Service removed : " + event.getName() + "."
+ event.getType());
Log.v(TAG, "Service removed : " + event.getName() + "."
+ event.getType());
}
public void serviceResolved(ServiceEvent event) {
deviceList.add("Service resolved: " + event.getInfo());
Log.v(TAG, "Service resolved: " + event.getInfo());
}
};
}
public void showAllPrinters() {
Log.d("ListDevices", "in showAllPrinters");
try {
WifiManager wifi = (WifiManager)
getSystemService(Context.WIFI_SERVICE);
lock = wifi.createMulticastLock("fliing_lock");
lock.setReferenceCounted(true);
lock.acquire();
InetAddress inetAddress = getLocalIpAddress();
jmdns = JmDNS.create(inetAddress, "TEST");
ServiceInfo[] infos = jmdns.list("_http._tcp.local.");
if (infos != null && infos.length > 0) {
for (int i = 0; i < infos.length; i++) {
deviceList.add(infos[i].getName());
}
} else {
deviceList.add("No device found.");
}
impl = (JmDNSImpl) jmdns;
} catch (IOException e) {
e.printStackTrace();
}
}
public InetAddress getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface
.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = (NetworkInterface) en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf
.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = (InetAddress) enumIpAddr
.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress;
}
}
}
} catch (SocketException ex) {
Log.e("ListDevices", ex.toString());
}
return null;
}
@Override
protected void onPause() {
super.onPause();
if (isFinishing()) {
lock.release();
}
}
}
Básicamente, los estoy agregando en una lista para que pueda mostrar una lista de todos los dispositivos disponibles. Ahora, cuando estoy ejecutando este código, no obtengo ninguna excepción / nada como error. Pero, por otro lado, no se agrega nada a mi lista [PD: hay al menos 5-6 PC y Mac en la red.
También traté de obtener la lista de este código:
jmdns.addServiceListener("_http._tcp.local.", listener);
listener
se define en el onCreate
de la actividad. Pero esto tampoco devolvió ningún dispositivo.
Por favor ayuda, sugiere lo que estoy haciendo mal aquí. Cualquier ayuda es apreciada!
Android 4.1 agrega Network Service Discovery que parece estar simplemente envolviendo la pila de Bonjour en diferentes términos. También veo una API de nivel inferior llamada android.net.wifi.p2p.WifiP2pManager que expone DNS-SD (así como UPnP?) Directamente.
Tenga en cuenta que el demonio mDNSResponder subyacente no parece estar funcionando todo el tiempo, y no se usa para búsquedas de DNS en todo el sistema (por ejemplo, desde un navegador) hasta donde puedo decir ahora.
Como se señaló en los comentarios anteriores, el soporte nativo de Android no funciona y / o no se implementa completamente para permitir la recuperación de registros TXT (a partir de Android v5.1). Tampoco pude conseguir que la biblioteca jmDns funcione para el descubrimiento. Finalmente encontré el proyecto mdnsjava y me funcionó muy fácilmente. Tenga en cuenta que su código de ejemplo no es correcto. Aquí hay una muestra del código que usé para encontrar de forma sincrónica todas las impresoras IPP:
String type[] = {"_ipp._tcp.local."};
Lookup resolve = null;
try {
resolve = new Lookup(type, Type.ANY, DClass.IN);
ServiceInstance[] records = resolve.lookupServices();
for (ServiceInstance record : records) {
Log.d(TAG, record.toString());
Map txtMap = record.getTextAttributes();
}
} catch (IOException e) {
e.printStackTrace();
}
También tenga en cuenta que necesita agregar la biblioteca dnsjava a su carpeta libs y su build.gradle. Utilicé la versión 2.1.7.
No puedo darte ninguna ayuda específica con el código, pero estoy bastante seguro de que hay problemas con Android y mDNS al menos con algunos teléfonos y (creo) el emulador.
Más información aquí:
http://rgladwell.wordpress.com/2010/04/18/gotchas-android-and-multicast-dns/
Puede usar una herramienta existente de Play Store de Android para escanear la red local primero, como "Bonjour browser" para asegurarse de que haya los servicios que desea escanear. Luego puede verificar la palabra clave jmDNS para escanear la red.
Pero hay un problema conocido de que jmDns no funciona en algunos dispositivos Android 4.x.