NsdManager not finding http server - android

I'm running a simple http server on my local network and trying to use NsdManager from an Android device to discover it. I've followed the Android training guide on this matter, but my device is not finding any services.
Here's my Android code:
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setupNetworkDiscovery()
{
discoveryListener = new NsdManager.DiscoveryListener()
{
#Override
public void onStopDiscoveryFailed(String serviceType, int errorCode)
{
// TODO Auto-generated method stub
}
#Override
public void onStartDiscoveryFailed(String serviceType, int errorCode)
{
Log.d(getPackageName(), "Start failed");
}
#Override
public void onServiceLost(NsdServiceInfo serviceInfo)
{
// TODO Auto-generated method stub
}
#Override
public void onServiceFound(NsdServiceInfo serviceInfo)
{
Log.d(getPackageName(), "Found a service");
// display the service info
StringBuilder sb = new StringBuilder();
sb.append(serviceInfo.toString());
sb.append(" - name: ");
sb.append(serviceInfo.getServiceName());
sb.append("; type: ");
sb.append(serviceInfo.getServiceType());
sb.append("\n");
servicesLabel.append(sb.toString());
}
#Override
public void onDiscoveryStopped(String serviceType)
{
// TODO Auto-generated method stub
}
#Override
public void onDiscoveryStarted(String serviceType)
{
Log.d(getPackageName(), "Start succeeded");
}
};
nsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);
nsdManager.discoverServices("_http._tcp", NsdManager.PROTOCOL_DNS_SD, discoveryListener);
}
The only log message I get is "Start succeeded" from onDiscoveryStarted.
The server is certainly running, as I can connect to it using a browser. nmap also confirms the port is open:
Nmap scan report for 192.168.1.104
Host is up (0.00011s latency).
PORT STATE SERVICE
8080/tcp open http-proxy
What am I doing wrong?
Thanks in advance!

I don't think it's your primary issue, but the service type should be "_http._tcp."
(you are missing the dot at the end)
For me (API 21), your code works fine, discovering "_http._tcp" still returns the services that are "_http._tcp."

Related

MQTT Paho Client not reconnect automatically to broker on Android Service

I've a Service to manage my MQTT Client connection, the MQTT works fine, but the problem is when I restart Broker Server, the Android client not reconnect. A exception is triggered on onConnectionLost() callback.
Notes
I'm using Moquette Broker at same computer -> Moquette
I've two Android clients app, a using Service (the problematic) and other working on a Thread, without Service (this works fine, reconnect is ok).
I can't run the Android Client MQTT lib, because this I'm using the Eclipse Paho MQTT.
Yes, I make setAutomaticReconnect(true);
Problem
The Android app that use Service, to works forever, not reconnect to MQTT Broker.
Code
MQTTService.java
public class MQTTService extends Service implements MqttCallbackExtended {
boolean running;
private static final String TAG = "MQTTService";
public static final String ACTION_MQTT_CONNECTED = "ACTION_MQTT_CONNECTED";
public static final String ACTION_MQTT_DISCONNECTED = "ACTION_MQTT_DISCONNECTED";
public static final String ACTION_DATA_ARRIVED = "ACTION_DATA_ARRIVED";
// MQTT
MqttClient mqttClient;
final String serverURI = "tcp://"+ServidorServices.IP+":1883";
final String clientId = "Responsavel";
String topicoId;
Thread mqttStartThread;
public boolean subscribe(String topic) {
try {
Log.i(TAG,"Subscripe: " + topic);
mqttClient.subscribe(topic);
mqttClient.subscribe("LOCATION_REAL");
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
// Life Cycle
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG,"onBind()");
return null;
}
#Override
public void onCreate() {
Log.d(TAG,"onCreate()");
running = true;
topicoId = getSharedPreferences("myprefs",MODE_PRIVATE).getString("tag_id_aluno","0");
mqttStartThread = new MQTTStartThread(this);
if(topicoId.equals("0")) {
Log.i(TAG,"Error to subscribe");
return;
}
mqttStartThread.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG,"onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
class MQTTStartThread extends Thread {
MqttCallbackExtended mqttCallbackExtended;
public MQTTStartThread(MqttCallbackExtended callbackExtended) {
this.mqttCallbackExtended = callbackExtended;
}
#Override
public void run() {
try {
mqttClient = new MqttClient(serverURI,clientId,new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setAutomaticReconnect(true);
options.setCleanSession(true);
mqttClient.setCallback(mqttCallbackExtended);
mqttClient.connect();
} catch (Exception e) {
Log.i(TAG,"Exception MQTT CONNECT: " + e.getMessage());
e.printStackTrace();
}
}
}
#Override
public void onDestroy() {
Log.d(TAG,"onDestroy()");
running = false;
if (mqttClient != null) {
try {
if (mqttClient.isConnected()) mqttClient.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public boolean onUnbind(Intent intent) {
Log.i(TAG,"onUnbind()");
return super.onUnbind(intent);
}
// Callbacks MQTT
#Override
public void connectComplete(boolean reconnect, String serverURI) {
Log.i(TAG,"connectComplete()");
if (topicoId == null) {
Log.i(TAG,"Erro ao ler ID da Tag");
return;
}
sendBroadcast(new Intent(ACTION_MQTT_CONNECTED));
subscribe(topicoId);
}
#Override
public void connectionLost(Throwable cause) {
Log.i(TAG,"connectionLost(): " + cause.getMessage());
cause.printStackTrace();
sendBroadcast(new Intent(ACTION_MQTT_DISCONNECTED));
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i(TAG,"messageArrived() topic: " + topic);
if (topic.equals("LOCATION_REAL")) {
Log.i(TAG,"Data: " + new String(message.getPayload()));
} else {
Context context = MQTTService.this;
String data = new String(message.getPayload());
Intent intent = new Intent(context,MapsActivity.class);
intent.putExtra("location",data);
LatLng latLng = new LatLng(Double.valueOf(data.split("_")[0]),Double.valueOf(data.split("_")[1]));
String lugar = Utils.getAddressFromLatLng(latLng,getApplicationContext());
NotificationUtil.create(context,intent,"Embarque",lugar,1);
if (data.split("_").length < 3) {
return;
}
double latitude = Double.valueOf(data.split("_")[0]);
double longitude = Double.valueOf(data.split("_")[1]);
String horario = data.split(" ")[2];
Intent iMqttBroadcast = new Intent(ACTION_DATA_ARRIVED);
iMqttBroadcast.putExtra("topico",String.valueOf(topic));
iMqttBroadcast.putExtra("latitude",latitude);
iMqttBroadcast.putExtra("longitude",longitude);
iMqttBroadcast.putExtra("evento","Embarcou");
iMqttBroadcast.putExtra("horario",horario);
sendBroadcast(iMqttBroadcast);
}
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.i(TAG,"deliveryComplete()");
}
}
Exception Stacktrace
I/MQTTService: connectionLost(): Connection lost
W/System.err: Connection lost (32109) - java.io.EOFException
W/System.err: at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146)
W/System.err: at java.lang.Thread.run(Thread.java:818)
W/System.err: Caused by: java.io.EOFException
W/System.err: at java.io.DataInputStream.readByte(DataInputStream.java:77)
W/System.err: at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65)
W/System.err: at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107)
W/System.err: ... 1 more
I think you forgot to include MqttConnectOptions with MqttClient object.
Please try like following
mqttClient.connect(options);
instead of
mqttClient.connect();
Hope it may help to resolve your re-connect issue.
As method description says.
options.setAutomaticReconnect(true);
The client will attempt to reconnect to the server. It will initially wait 1 second before it attempts to reconnect, for every failed reconnect attempt, the delay will doubleuntil it is at 2 minutes at which point the delay will stay at 2 minutes.
Another option would be you could manage retry interval in case of connection lost events.

Android NSD: registration with null service type

The result of the registration shouldn't be empty, this is what I get from logcat and the callback of successful registration.
registerService 46518
onServiceRegistered name: mytest, type: null, host: null, port: 0, txtRecord:
Everything is empty, the port 46518 which was generated by the system, the type, the txtrecord.
The following code is from the official guide
private String mServiceName = "mytest";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
// Initialize a server socket on the next available port.
ServerSocket mServerSocket = new ServerSocket(0);
int mLocalPort = mServerSocket.getLocalPort();
registerService(mLocalPort);
} catch (IOException e) {
e.printStackTrace();
}
}
public void registerService(int port) {
Log.i(tag, "registerService " + port);
// Create the NsdServiceInfo object, and populate it.
NsdServiceInfo serviceInfo = new NsdServiceInfo();
// The name is subject to change based on conflicts with other services advertised on the same network.
serviceInfo.setServiceName(mServiceName);
serviceInfo.setServiceType("_mytest._tcp");
serviceInfo.setPort(port);
serviceInfo.setAttribute("info", android.os.Build.MODEL);
NsdManager mNsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);
mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);
}
NsdManager.RegistrationListener mRegistrationListener = new NsdManager.RegistrationListener() {
#Override
public void onServiceRegistered(NsdServiceInfo nsdServiceInfo) {
// Save the service name. Android may have changed it in order to
// resolve a conflict, so update the name you initially requested
// with the name Android actually used.
mServiceName = nsdServiceInfo.getServiceName();
Log.i(tag, "onServiceRegistered " + nsdServiceInfo);
}
#Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
// Registration failed! Put debugging code here to determine why.
Log.i(tag, "onRegistrationFailed code " + errorCode + "\n" + serviceInfo);
}
#Override
public void onServiceUnregistered(NsdServiceInfo arg0) {
// Service has been unregistered. This only happens when you call
// NsdManager.unregisterService() and pass in this listener.
Log.i(tag, "onServiceUnregistered " + arg0);
}
#Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
// Unregistration failed. Put debugging code here to determine why.
Log.i(tag, "onRegistrationFailed code " + errorCode + "\n" + serviceInfo);
}
};
Got the same on my LG G5 (Android 7.0)
Checked if the MDNS-Packets show up in Wireshark and they did!
It seems that the service is announced with the right ip and port,
even if the NsdServiceInfo in onServiceRegistered() says something different.

Android NSD onServiceFound() not getting called

First time trying to do IP Discovery in Android. I used the http://developer.android.com/training/connect-devices-wirelessly/nsd.html#discover and wrote the code. I am not registering the device, just Discovering Services in the network. When I run the project in emulator or device the onDiscoveryStarted() gets called, but the onServiceFound() is never called. Please find my Code below. Any input is much appreciated. Thanks!
public class MainActivity extends AppCompatActivity {
private Button discoverButton;
Context mContext;
NsdManager mNsdManager;
NsdManager.ResolveListener mResolveListener;
NsdManager.DiscoveryListener mDiscoveryListener;
NsdManager.RegistrationListener mRegistrationListener;
public static final String SERVICE_TYPE = "_http._tcp.";
public static final String TAG = "MyApp_MAIN_CLIENT";
public String mServiceName = "MyApp";
/*
* public static final String SERVICE_TYPE = "_http._tcp.";
public static final String TAG = "NsdHelper";
public String mServiceName = "NsdChat";
* */
NsdServiceInfo mService;
private Handler mUpdateHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNsdManager = (NsdManager) this.getSystemService(Context.NSD_SERVICE);
discoverButton = (Button) findViewById(R.id.netButton);
discoverButton.setOnClickListener(new View.OnClickListener() {
public void onClick(android.view.View v) {
initializeDiscoveryListener();
initializeResolveListener();
discoverServices();
}
});
}
public void discoverServices() {
mNsdManager.discoverServices(
SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
public void initializeDiscoveryListener() {
// Instantiate a new DiscoveryListener
mDiscoveryListener = new NsdManager.DiscoveryListener() {
// Called as soon as service discovery begins.
#Override
public void onDiscoveryStarted(String regType) {
Log.d(TAG, "Service discovery started");
}
#Override
public void onServiceFound(NsdServiceInfo service) {
// A service was found! Do something with it.
Log.d(TAG, "Service discovery success" + service);
if (!service.getServiceType().equals(SERVICE_TYPE)) {
// Service type is the string containing the protocol and
// transport layer for this service.
Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
} /*else if (service.getServiceName().equals(mServiceName)) {
// The name of the service tells the user what they'd be
// connecting to. It could be "Bob's Chat App".
Log.d(TAG, "Same machine: " + mServiceName);
}
//else if (service.getServiceName().contains("NsdChat")){*/
else{
mNsdManager.resolveService(service, mResolveListener);
}
}
#Override
public void onServiceLost(NsdServiceInfo service) {
// When the network service is no longer available.
// Internal bookkeeping code goes here.
Log.e(TAG, "service lost" + service);
}
#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);
}
};
}// end of initializeListener()
public void initializeResolveListener() {
mResolveListener = new NsdManager.ResolveListener() {
#Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.e(TAG, "Resolve failed" + errorCode);
}
#Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
Log.e(TAG, "Resolve Succeeded. " + serviceInfo);
if (serviceInfo.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same IP.");
return;
}
mService = serviceInfo;
int port = mService.getPort();
InetAddress host = mService.getHost();
Log.d(TAG,host.toString());
}
};
}//end of initializeResolveListener
#Override
protected void onPause() {
super.onPause();
stopDiscovery();
tearDown();
}
#Override
protected void onResume() {
super.onResume();
discoverServices();
}
#Override
protected void onDestroy() {
tearDown();
super.onDestroy();
}
public void stopDiscovery() {
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
public void tearDown() {
mNsdManager.unregisterService(mRegistrationListener);
}
}
From NdsManager documentation page:
The API currently supports DNS based service discovery and discovery
is currently limited to a local network over Multicast DNS.
From this Local networking limitations emulator docs page:
Currently, the emulator does not support IGMP or multicast.
Hope this will help you
Probably due to the age of this post, I hope you already found a solution.
If not, my experience is that the Android Emulator (API level 25) does not provide a full network stack and the service discovery through NSD isn't working.
I switched to debugging on a real device (like an Android TV or tablet) and then my whole NSD/Bonjour-like setup was working. The methods of the DiscoveryListener and the ResolveListener were called and an IP and port (in my case) were retrieved.
After some hours working with Android NSD, I discovered that this library does not work with routers that don't support Multicast. While the other answers may are correct, this could also be the cause of your problem. Possible solutions: enable Multicast on your router if possible, or use another network library.
The Network Service Discovery Manager class provides the API to discover services on a network.
This will work when your device is connected to the same WIFI network as that of the device providing the service.
Hope this helps!!
Happy Coding!!

new PeerConnectionFactory() gives error on android

I am trying to implement WebRTC DataChannel on Android. I want to create a simple peerconnection object which will open DataChannel to send data over the network using WebRTC. I am getting error when I try to create my PeerConnection Object. I learnt that we use factory to create peerconnection object using factory.createPeerConnection().
For this, I have to create the PeerConnectionFactory object first. After this, I can use it to create PeerConnection Object. I get errors Could not find method android.media.MediaCodec.setParameters and Fatal Signal 11 (SIGSEGV) at 0x00000000 (code=1) when I try to create PeerConnectionFactory object. I also tried the following code with PeerConnectionFactory.initializeAndroidGlobals(this, false, false, false); This is what I am trying to do:
PeerConnectionFactory factory = new PeerConnectionFactory();
peer = new Peer();
This is how my Peer object looks like:
public class Peer implements SdpObserver, PeerConnection.Observer, DataChannel.Observer {
private PeerConnection pc;
private DataChannel dc;
public Peer() {
this.pc = factory.createPeerConnection(RTCConfig.getIceServer(),
RTCConfig.getMediaConstraints(), this);
dc = this.pc.createDataChannel("sendDataChannel", new DataChannel.Init());
}
#Override
public void onAddStream(MediaStream arg0) {
// TODO Auto-generated method stub
}
#Override
public void onDataChannel(DataChannel dataChannel) {
this.dc = dataChannel;
}
#Override
public void onIceCandidate(final IceCandidate candidate) {
try {
JSONObject payload = new JSONObject();
payload.put("type", "candidate");
payload.put("label", candidate.sdpMLineIndex);
payload.put("id", candidate.sdpMid);
payload.put("candidate", candidate.sdp);
sendSocketMessageDataChannel(payload.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onIceConnectionChange(IceConnectionState iceConnectionState) {
}
#Override
public void onIceGatheringChange(IceGatheringState arg0) {
// TODO Auto-generated method stub
}
#Override
public void onRemoveStream(MediaStream arg0) {
// TODO Auto-generated method stub
}
#Override
public void onRenegotiationNeeded() {
// TODO Auto-generated method stub
}
#Override
public void onSignalingChange(SignalingState arg0) {
// TODO Auto-generated method stub
}
#Override
public void onCreateFailure(String msg) {
Toast.makeText(getApplicationContext(),
msg, Toast.LENGTH_SHORT)
.show();
}
#Override
public void onCreateSuccess(SessionDescription sdp) {
try {
JSONObject payload = new JSONObject();
payload.put("type", sdp.type.canonicalForm());
payload.put("sdp", sdp.description);
sendSocketMessageDataChannel(payload.toString());
pc.setLocalDescription(FilePeer.this, sdp);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onSetFailure(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onSetSuccess() {
// TODO Auto-generated method stub
}
#Override
public void onMessage(Buffer data) {
Log.w("FILE", data.toString());
}
#Override
public void onStateChange() {
Toast.makeText(getApplicationContext(),
"State Got Changed", Toast.LENGTH_SHORT)
.show();
/*
byte[] bytes = new byte[10];
bytes[0] = 0;
bytes[1] = 1;
bytes[2] = 2;
bytes[3] = 3;
bytes[4] = 4;
bytes[5] = 5;
bytes[6] = 6;
bytes[7] = 7;
bytes[8] = 8;
bytes[9] = 9;
ByteBuffer buf = ByteBuffer.wrap(bytes);
Buffer b = new Buffer(buf, true);
dc.send(b);
*/
}
}
Can anybody point me to any sample source code which implements DataChannel on Android? Kindly also let me know if I am not doing it in a right way. I could not find the documentation for Android Native WebRTC which tells how to do it. I am trying to implement whatever I have learnt from using WebRTC on web.
Kindly, let me know if my question is not clear.
PeerConnectionFactory no longer requires initializing audio & video engines to be enabled.
PeerConnectionFactory.initializeAndroidGlobals(this, false, false, false);
Now you will be able to disable audio and video, and use data channels
This is a known bug in WebRTC code for Android. Following threads talk more on this bug:
https://code.google.com/p/webrtc/issues/detail?id=3416
https://code.google.com/p/webrtc/issues/detail?id=3234
The bug is currently in open status. However, there is a workaround available which will work for now. In Android Globals, we need to pass the audio and video parameters as true:
PeerConnectionFactory.initializeAndroidGlobals(getApplicationContext(), true, true, VideoRendererGui.getEGLContext());
Use this instead PeerConnectionFactory.initializeAndroidGlobals(acontext, TRUE, false, false, NULL);
Then create the factory. factory = new PeerConnectionFactory();
Then in your class Peer create the peer connection as this : factory.createPeerConnection(iceServers, sdpMediaConstraints, this);.
This worked for me to establish ONLY DataChannel without EGLContext for video streaming.
UPDATE: If you still have this error, go to a newer version! This is very deprecated.

android wifi-direct connect success callback calling repeatedly

i trying to connect to one wifi device using wifidirect but when i run following code it's always show connected device notification infinitely may i know where i made mistake
Here is my code snippet
if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
final Context ctx = context;
//showing this pop up message always can you help me to understand this issue please
Toast.makeText(ctx, "WIFI_P2P_PEERS_CHANGED_ACTION",Toast.LENGTH_LONG).show();
if (mManager != null) {
mManager.requestPeers(mChannel, new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peers) {
for ( WifiP2pDevice peer : peers.getDeviceList()) {
WifiP2pDevice device=peer;
String serverName = "Android_f9c4";
if(device.deviceName.equals(serverName)){
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
mManager.connect(mChannel,config ,new ActionListener() {
//whats wrong here
#Override
public void onSuccess() {
// This fire always
Toast.makeText(ctx, "connected",Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(int reason) {
// TODO Auto-generated method stub
Toast.makeText(ctx, "Not connected",Toast.LENGTH_LONG).show();
}
});
}
}
}
});
}
}
}
use
ArrayList<WifiP2pDevice> list=peers.getDeviceList();
for( WifiP2pDevice peer : list)
in place of
for ( WifiP2pDevice peer : peers.getDeviceList()) {

Categories

Resources