I am currently using Network Service Discovery to detect HTTP services on my local network. I used the Google Android NSDChat project example, and it only returns to me the host names, however, the host IP address NULL.
This is my function that will return the host name
public void onServiceFound(NsdServiceInfo service) {
Log.d(TAG, "Service discovery success" + service.getHost());
//pref.putString("name", service.getServiceName());
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)){
mNsdManager.resolveService(service, mResolveListener);
}
}
public void initializeResolveListener() {
mResolveListener = new NsdManager.ResolveListener() {
#Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
// Called when the resolve fails. Use the error code to debug.
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();
host = mService.getHost(); // getHost() will work now
Log.d(TAG, "Service discovery success" + host );
}
};
}
I face similar problem and I found this website. However after trying it, it did not work as well.
Host is null in NsdServiceInfo of NsdManager.DiscoveryListener.onServiceFound
Related
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.
I am trying to pull the data from Intel's Fossil Android based Smartwatch (BLE device) via Google Fit Android SDK. The BLE Scan seem to happen, pairing occurs but inside the result Callback it doesn't go to onDeviceFound (I can proceed from there if it reaches). It eventually times out within few seconds from the start of the scan.
Any help would be appreciated.
Thanks for the docs link. I did go through all of that thoroughly but it didn't help. This is my Class file and I can call startBleScan from my MainActivity, the BleScan seems to be working, but after that it doesn't proceed to go on to onDeviceFound method.
public class BlueToothDevicesManager {
private static final String TAG = "BlueToothDevicesManager";
private static final int REQUEST_BLUETOOTH = 1001;
private Main2Activity mMonitor;
private GoogleApiClient mClient;
public BlueToothDevicesManager(Main2Activity monitor, GoogleApiClient client) {
mMonitor = monitor;
mClient = client;
}
public void startBleScan() {
if (mClient.isConnected()) {
Log.i(TAG, "Google account is connected");
}
BleScanCallback callback = new BleScanCallback() {
#Override
public void onDeviceFound(BleDevice device) {
Log.i(TAG, "BLE Device Found: " + device.getName());
claimDevice(device);
}
#Override
public void onScanStopped() {
Log.i(TAG, "BLE scan stopped");
}
};
PendingResult result = Fitness.BleApi.startBleScan(mClient, new StartBleScanRequest.Builder()
.setDataTypes(DataType.TYPE_POWER_SAMPLE, DataType.TYPE_STEP_COUNT_CADENCE, DataType.TYPE_STEP_COUNT_DELTA, DataType.TYPE_SPEED, DataType.TYPE_ACTIVITY_SAMPLE, DataType.TYPE_DISTANCE_DELTA, DataType.TYPE_ACTIVITY_SEGMENT, DataType.TYPE_LOCATION_SAMPLE)
.setBleScanCallback(callback)
.build());
result.setResultCallback(new ResultCallback() {
#Override
public void onResult(#NonNull Result result) {
Status status = result.getStatus();
if (!status.isSuccess()) {
String a = status.getStatusCode() + "";
Log.i(TAG, a);
switch (status.getStatusCode()) {
case FitnessStatusCodes.DISABLED_BLUETOOTH:
try {
status.startResolutionForResult(mMonitor, REQUEST_BLUETOOTH);
} catch (SendIntentException e) {
Log.i(TAG, "SendIntentException: " + e.getMessage());
}
break;
}
Log.i(TAG, "BLE scan unsuccessful");
} else {
Log.i(TAG, "ble scan status message: " + status.getStatusMessage());
Log.i(TAG, "Ble scan successful: " + status.getResolution());
}
}
});
}
public void claimDevice(BleDevice device) {
//Stop ble scan
//Claim device
PendingResult<Status> pendingResult = Fitness.BleApi.claimBleDevice(mClient, device);
pendingResult.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status st) {
if (st.isSuccess()) {
Log.i(TAG, "Claimed device successfully");
} else {
Log.e(TAG, "Did not successfully claim device");
}
}
});
}
}
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!!
I'm trying to use the native Android SIP stack to make direct SIP calls within a LAN. It appears that within the native stack, you are required to register a local profile in order to make SIP calls.
Here is the code I (try to) use to register a profile. I do not have a SIP server on this network, so I just use localhost for a domain.
if (mSipManager == null) {
mSipManager = SipManager.newInstance(mContext);
try {
SipProfile.Builder builder = new SipProfile.Builder("foo", "localhost");
builder.setPassword("bar");
mSipProfile = builder.build();
mSipManager.register(mSipProfile, 30000, new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
Log.v(TAG, "Registering with profile with SIP Server. URI: " + localProfileUri);
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
Log.v(TAG, "Registered with profile with SIP Server. URI: " + localProfileUri);
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
Log.e(TAG, "Registration failed. Code: " + Integer.toString(errorCode));
Log.e(TAG, errorMessage);
}
});
} catch (ParseException e) {
Log.e(TAG, "Unable to set up local SipProfile.", e);
} catch (SipException e) {
Log.e(TAG, "Unable to open local SipProfile.", e);
}
}
Elsewhere, here is my code for making a call:
try {
Log.v(TAG, "VOIP Supported: " + SipManager.isVoipSupported(mActivity));
Log.v(TAG, "SIP API Supported: " + SipManager.isApiSupported(mActivity));
SipProfile.Builder builder = new SipProfile.Builder(mSipUri);
SipProfile remote = builder.build();
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onCalling(SipAudioCall call) {
Log.d(TAG, "SIP Call initiating...");
}
#Override
public void onCallEstablished(SipAudioCall call) {
Log.d(TAG, "SIP Call established.");
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
}
#Override
public void onCallEnded(SipAudioCall call) {
Log.d(TAG, "SIP Call ended.");
}
#Override
public void onError(SipAudioCall call, int errorCode, String errorMessage) {
Log.e(TAG, "SIP Call Error. Code: " + Integer.toString(errorCode));
Log.e(TAG, errorMessage);
}
};
mSipCall = mSipManager.makeAudioCall(mSipProfile, remote, listener, 10);
} catch (ParseException e) {
Log.e(TAG, "Unable to set up remote SipProfile.", e);
} catch (SipException e) {
Log.e(TAG, "SipAudioCall error.", e);
}
This all results in the following logcat output:
11-20 11:46:33.150 1412-1412/package.name E/XmlTest﹕ 1- Unable to open local SipProfile.
android.net.sip.SipException: SipService.createSession() returns null
at android.net.sip.SipManager.register(SipManager.java:481)
I'm unable to find further details as to why createSession is returning null; is it because I've not provided a valid server for the profile to register with? If so, is there a way to use the native SIP stack without registering with a server?
It turns out the problem is that Android's SIP stack appears to require the local SIP Profile you provide to the SIPManager (in the first codeblock above, represented by builder and mSipProfile) to have a valid IP address supplied to it.
Where I originally specified "localhost", you must actually provide the IP address of whatever interface you are making the SIP call over; if you are using a VPN, you must provide the IP of the VPN interface.
i want to build an application using wifi direct to transfer files and i'm using NFC to reduce pairing time. I've already follow the instruction in http://developer.android.com/guide/topics/connectivity/wifip2p.html and http://developer.android.com/training/connect-devices-wirelessly/wifi-direct.html but my apps won't connect. and i took the code from wifi direct demo from android example.
when i trace the problem is when wifi direct broadcast receiver WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION the network info won't to connect with other device so, in my main class that implements ConnectionInfoListener that have a method onConnectionInfoAvailable it's never triggered.
can anyone help me? thx before
the code is like this
Wifi Direct BroadCast Receiver
`
public void onReceive(Context arg0, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
// UI update to indicate wifi p2p status.
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// Wifi Direct mode is enabled
activity.setIsWifiP2pEnabled(true);
} else {
activity.setIsWifiP2pEnabled(false);
//activity.resetData();
}
//Log.d(WiFiDirectActivity.TAG, "P2P state changed - " + state);
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
// request available peers from the wifi p2p manager. This is an
// asynchronous call and the calling activity is notified with a
// callback on PeerListListener.onPeersAvailable()
if (manager != null) {
}
//Log.d(WiFiDirectActivity.TAG, "P2P peers changed");
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
if (manager == null) {
return;
}
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
if (networkInfo.isConnected()) {
// we are connected with the other device, request connection
// info to find group owner IP
manager.requestConnectionInfo(channel, activity);
} else {
// It's a disconnect
}
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
WifiP2pDevice device = (WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
activity.myname = device.deviceName + " " + device.deviceAddress + " " + device.primaryDeviceType + " " + device.secondaryDeviceType + " " + device.status;
}
}`
my main class
`
// how to connect
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = names[1];
config.wps.setup = WpsInfo.PBC;
config.groupOwnerIntent = 15;
connect(config);
public void connect(WifiP2pConfig config) {
manager.connect(channel, config, new ActionListener() {
#Override
public void onSuccess() {
// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
}
#Override
public void onFailure(int reason) {
Toast.makeText(getApplicationContext(), "Connect failed. Retry.", Toast.LENGTH_SHORT).show();
}
});
}
public void disconnect() {
manager.removeGroup(channel, new ActionListener() {
#Override
public void onFailure(int reasonCode) {
//Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);
Toast.makeText(getApplicationContext(), "Disconnect failed. Reason :" + reasonCode, Toast.LENGTH_SHORT).show();
}
#Override
public void onSuccess() {
Toast.makeText(getApplicationContext(), "Disconnected", Toast.LENGTH_SHORT).show();
}
});
}
public void onChannelDisconnected() {
// we will try once more
if (manager != null && !retryChannel) {
Toast.makeText(this, "Channel lost. Trying again", Toast.LENGTH_LONG).show();
//resetData();
retryChannel = true;
manager.initialize(this, getMainLooper(), this);
} else {
Toast.makeText(this,
"Severe! Channel is probably lost premanently. Try Disable/Re-Enable P2P.",
Toast.LENGTH_LONG).show();
}
}
public void onConnectionInfoAvailable(WifiP2pInfo info) {
// TODO Auto-generated method stub
this.info = info;
// After the group negotiation, we can determine the group owner.
if (info.groupFormed && info.isGroupOwner) {
// Do whatever tasks are specific to the group owner.
// One common case is creating a server thread and accepting
// incoming connections.
Toast.makeText(getApplicationContext(), "Owner", Toast.LENGTH_SHORT).show();
} else if (info.groupFormed) {
// The other device acts as the client. In this case,
// you'll want to create a client thread that connects to the group
// owner.
Toast.makeText(getApplicationContext(), "Client", Toast.LENGTH_SHORT).show();
}
}
`
onConnectionInfoAvailable will never be executed because the networkInfo.isConnected() is never true.
Please help me.. Thx..