Im trying to let my Google Glass and my android phone connect to a NodeJs server that Im running on my computer, so that I can send messages from my android phone to my Google Glass.
For this Im using koush's AndroidAsync library, which works great on my android phone and I have absolutely no trouble connecting my phone to the NodeJS server with this library.
However, the same code doesnt seem to work on my Google Glass. My Google Glass DOES connect, because the on connection eventhandler of my NodeJS server IS triggered, it just doesnt seem to trigger any of the ConnectCallback functions on my Google Glass.
Here is the code Im using in my Google Glass app:
SocketIOClient.connect(AsyncHttpClient.getDefaultInstance(), "http://192.168.1.229:5000", new ConnectCallback() {
#Override
public void onConnectCompleted(Exception ex, SocketIOClient client) {
Log.i("SOCKET", "CONNECTION COMPLETED");
if (ex != null) {
ex.printStackTrace();
return;
}
client.setStringCallback(new StringCallback() {
#Override
public void onString(String string, Acknowledge acknowledge) {
Log.d("SOCKET", string);
}
});
client.setJSONCallback(new JSONCallback() {
#Override
public void onJSON(JSONObject jsonObject, Acknowledge acknowledge) {
Log.d("SOCKET", jsonObject.toString());
}
});
client.on("event", new EventCallback() {
#Override
public void onEvent(JSONArray jsonArray, Acknowledge acknowledge) {
Log.i("DATA: ", jsonArray.toString());
Gson gson = new Gson();
}
});
mClient = client;
}
});
}
As you can see, Im trying to log "CONNECTION COMPLETED" in the "onConnectCompleted" function, but it never fires and nothing is ever logged.
I find this rather strange, as the same code DOES work on my android phone and "CONNECTION COMPLETED" IS logged when I run this bit of code on my android phone. The strangest thing is that my node server actually picks up the Google Glass as the on connection event is triggered on the server when my Glass connects.
So, can anybody help me find out why my Google Glass IS apparently connecting to my NodeJS server, but is NOT triggering any events when it connects. (Not triggering the ConnectCallback functions, "CONNECTION COMPLETED" is never logged)?
Thanks in advance,
Bram
I was facing the same issue here and noticed although my Glass showed it was connected to my Wifi network, it actually wasn't. I tried adb shell netcfg on it and to my surprise the wlan0 interface had no IP assigned. I reconnected it to the wifi network again and it all started to work just fine.
The weird thing though is that I was expecting some sort of error to be logged (even though I was using a different Socket.IO client). I believe the case to be a timeout that didn't expire (connection/socket timeout) so it was still attempting to connect and didn't fail in time for us to see the log entry. I guess these libraries have a relatively high connection timeout set by default, so you wouldn't see an error before many seconds would go by.
Related
We are trying to create an android application for video chat using socket.io. We are using node js for the server. The server is running on a laptop. I tried to connect to the server using an Android emulator on the same laptop. But the server is not responding. I thought we shouldn't try to connect the emulator running on the same laptop where the server is running. I tried with Samsung S9+ device but the same result, the server is not responding. But interestingly when I tried to connect to the server from the Kindle device, the server is responding and printing the log. I used the same code for Emulator, S9+, and Kindle devices. Only when kindle device is trying to connect, the server is responding. Below is the code.
Android code:
String SIGNALING_URI = "http://192.168.1.101:7000"; // Laptop IP where the server is running and port 7000 where the server is listening
try {
socket = IO.socket(SIGNALING_URI);
socket.on(CREATEOFFER, new Emitter.Listener() {
#Override
public void call(Object... args) {
createOffer = true;
peerConnection.createOffer(sdpObserver, new MediaConstraints());
}
});
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
Node.js (server) code:
var socketIO = require('socket.io');
var server = require('http').createServer().listen(7000, '0.0.0.0');
var io = socketIO.listen(server);
io.sockets.on('connection', function (client) {
console.log('new connection: ' + client.id);
client.on('offer', function (details) {
client.broadcast.emit('offer', details);
console.log('offer: ' + JSON.stringify(details));
});
client.on('answer', function (details) {
client.broadcast.emit('answer', details);
console.log('answer: ' + JSON.stringify(details));
});
client.on('candidate', function (details) {
client.broadcast.emit('candidate', details);
console.log('candidate: ' + JSON.stringify(details));
});
client.broadcast.emit('createoffer', {});
});
Server code should print "new connection: " log when a client is trying to connect. But it is not printing that log when Android emulator or S9+ device are trying to connect but the log is getting printed when Kindle is trying to connect. I tried to do this using web sockets instead of using socket io. The server is responding for kindle device only even using web sockets also. Can anyone please let me know if there is anything wrong in the code or do I need to change any settings on S9+ device and emulator to make it work?
Update 1:
It seems I am using socket.io-client:0.8.2 version. But on the server node js, it seems I am using socket.io 2.3.0. Does it create any problems. Where I can find compatible versions of socket io for java and node.js. Just wanted to make sure that compatibility is not causing this issue.
Update 2:
I am able to see "new connection: " on the console multiple times with different client IDs. But these logs are not generated when I was trying to connect on Emulator or S9+ device. To make sure, I tried to print socket ID on client side after IO.socket(SIGNALING_URI) by using socket.id() which is printing null on the client side.
How to check programmatically whether the Wifi network the phone is connected to has internet access ?
I cannot use "ping google.com" type solutions because it does not work on some devices such as Honor 10
Well, in order to decide whether a device is connected to the internet we have to define what "connected to the internet" actually means. As far as I know, the Android SDK doesn't offer any way to check that and I think that is because you have to ping a specific address after all, in order to see if it is reachable.
On my Android device, the WiFi indicator in the status bar shows an exclamation point whenever I am connected to the WiFi network but my internet connection is down. I am not sure, but I think it pings a google server (like 8.8.8.8) behind the scenes in order to find out.
I think the best approach is not to ping Google, rather ping the specific address that you use in your app, for example if you use Last.fm API, ping that instead, because you could get in a situation where the Google server is reachable but the Last.fm API is down. This is just a general example, but the solution depends on your goal.
Just try connecting to whatever it is that you need to talk to, and handle failures in a graceful way.
Pinging something (even the server you want to talk to) isn't reliable, as the server, or some part of the network may block PING.
Pinging something "well known" (like Google's name-server on 8.8.8.8) isn't reliable because it only tells you that it is up, not necessarily that you can reach the server you want to talk to. (Or, it might even be that the "well known" entity is down or unreachable, but your server is working OK).
Doing something other than just trying to connect to what you want risks introducing TOCTOU (Time-of-check to time-of-use) errors.
I've found a solution that is quick and does not require using ping command or having to load a page.
The solution uses Volley, Android's HTTP library:
public static void isInternetAccessWorking(Context context, final InternetAccessListener listener) {
StringRequest stringRequest = new StringRequest(Request.Method.GET, "https://www.google.com",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
listener.hasInternet(true);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
listener.hasInternet(false);
}
});
Volley.newRequestQueue(context).add(stringRequest);
}
This method is not blocking: the activity or fragment calling isInternetAccessWorking() has to provide a parameter implementing InternetAccessListener that will receive the response
public interface InternetAccessListener {
void hasInternet(Boolean result);
}
I have written an app that connects to a BLE device. The app works OK on most devices; but some devices (most noticeably Huawei P8 Lite and Nexus 6P) refuse to connect after the Bluetooth adapter has been disabled.
This is the test sequence:
Make sure the app is NOT running.
Slide down from the top, disable BT for a couple of seconds, then re-enable bluetooth.
Start the app. The app automatically connects to a bluetooth address stored in the preferences.
Wait for connect. This is where nothing happens on Huawei phones, but other phones, such as Samsung, works like a charm.
Verify from another phone the device is advertising and you can
connect to it.
This is the code I use to connect:
private final Runnable mBeginConnectRunnable = new Runnable() {
#Override
public void run() {
synchronized (GattConnection.this) {
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
try {
mBluetoothAdapter.cancelDiscovery();
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(mAddress);
mGatt = mBluetoothDevice.connectGatt(mContext, mBackgroundConnect, mGattCallback);
final boolean connectSuccess = mGatt.connect();
Log.d(TAG, String.format(Locale.ENGLISH, "mGatt.connect(%s, %s) %s",
mAddress,
mBackgroundConnect ? "background[slow]" : "foreground[fast]",
connectSuccess ? "success" : "failed"));
refreshDeviceCache(mGatt);
} catch (Exception ex) {
Log.e(TAG, "Create connection failed: " + ex.getMessage());
setState(State.Closed);
}
} else {
Log.d(TAG, "Can't create connection. Adapter is disabled");
setState(State.Closed);
}
}
}
};
All calls are posted via a Handler to the main thread. I can see it waits for a connect, gives up after 30 seconds at which I call BluetoothGatt.close() on the object and nulls it. It's like nothing is out there.
After some time, later in the day, it works again.
Help is highly appreciated :-)
Update September 14, 2018: After great explanation from Emil I've updated our app and as such don't have this problem on the Nexus. I've noticed the Huawei P8 Lite continues to scan in the background and it seems there is nothing you can do to stop it.
To demonstrate the problems I've made a very simple and clean app that exercise the Bluetooth LE functionality on a phone and used it to demonstrate this problem and also the P8 is broken. The app is available here: https://play.google.com/store/apps/details?id=eu.millibit.bluetootherror
Source is available here: https://bitbucket.org/millibit/eu.millibit.bluetootherror/src/master/
I hope I over time can extend this app to make it a test vehicle for Android documenting all the stange behavior from Android and collect it in a database. In case you are interested in contributing, don't hesitate to drop me a mail on bt.error#millibit.dk
The Android Bluetooth stack has a design flaw in its API. When you connect to a specific device by Bluetooth Device Address, there is no way to tell if you mean a Public address or Random address.
If you start to connect to a device with autoConnect=false which is not bonded and has not recently been seen in a Scan, it will assume you mean a Public address. So if you try to connect to a device having a static random address, it will fail.
To be sure you connect with the correct address type if the device is not bonded, you MUST perform a scan first, find the device and THEN start the connection attempt.
I'm building a chat application using xmpp over Ejabbered for server and smack for android client
I've established connecting , login , send and receiving messages ,then I've faced a problem with user network disconnecting and reconnecting , which has been solved by Reconnecting Manger in smack and xmpp-0198, however there is a case where i need to create a new connection in smack but use the previous session (stream) to get all the messages stored in that session (they don't get stored to offline messages)
,and if i create a new connection with new stream id , user messages get lost .
so is there a connection constructor to implement this solution .
or server side configuration to store thous messages to offline messages
I think one of the following will solve your issue-
First check is mod_offline enabled in the server side.
If mod_offline enabled then check offline message limit in the server side. It should be greater than 0.
Use PingManager to stable your connection. I am here putting sample code to use PingManager in android-
During XMPPTcpConnection initiation-
pingManager = PingManager.getInstanceFor(this.connection);
pingManager.registerPingFailedListener(new PingFailedListener() {
#Override
public void pingFailed() {
// session dropped, request for reconnection
}
});
When XMPPTcpCOnnection authenticated-
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
configurePingManager();
}
private void configurePingManager() {
pingManager.setPingInterval(ACCORDING_SERVER_PING_INTERVAL);
pingManager.pingServerIfNecessary();
}
Make sure stream_management enabled both in server side and client side. I am here putting a sample code to enable stream_management for android client side-
xmppTcpConnection.setUseStreamManagement(true);
xmppTcpConnection.setUseStreamManagementResumption(true);
When XMPPTcpCOnnection authenticated checking session status send and request all pending streams using the code below-
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
configurePingManager();
if (!resumed) {
try {
xmppTcpConnection.sendSmAcknowledgement();
xmppTcpConnection.requestSmAcknowledgement();
} catch (SmackException.NotConnectedException | StreamManagementException.StreamManagementNotEnabledException e) {
e.printStackTrace();
}
}
}
Hope following all those steps your problem will be solved.
after lots of searching ,finally i upgraded Ejabberd server to the latest version 17.03
where they've added the new module mod_stream_mgmt ,and changed the behavior of stream management , so when i create a new connection it get rebind to the old one and receive the unsent and un-handled messages
to activated the mod_stream_mgmt i used the following configurations :
mod_stream_mgmt :
resume_timeout :60
resend_on_timeout: true
Note :
I have also activated mod_ping on server side ,I don't know if that has a direct effect on this process and case but right now my clients are not missing any messages .
I'm slightly familiar with BLE and I am facing some problem with an inherited code. So the app works like that:
With BLE enabled the app scans for devices
The app displays the devices found
The user selects the device to pair with
The app pairs with the device
The problem I'm facing is that after pairing several times (it varies) the phone is not able to discover devices, hence blocking the user to pair.
I'm using GattServer to connect with the client device, and I'm reseting the services as below:
public void resetBluetoothGattServer() {
Log.i(TAG," resetBluetoothGattServer: bluetoothGattServer: "+ bluetoothGattServer);
if (bluetoothGattServer != null) {
if(!bluetoothGattServer.getServices().isEmpty()){
Log.i(TAG," resetBluetoothGattServer: clearing services on bluetooth Gatt Server");
bluetoothGattServer.clearServices();
}
Log.i(TAG," resetBluetoothGattServer: closing bluetoothGattServer");
bluetoothGattServer.close();
}
bluetoothGattServer = openGattServer();
}
Restarting the phone, turning bluetooth off and then back on, and uninstalling and installing the app won't fix the problem. The only solution is to clear the cache from the Bluetooth Share app on the android apps manager.
This post How to programmatically force bluetooth low energy service discovery on Android without using cache adresses to a similar problem but since we are not using BluetoothGatt to connect it's no a suitable solution. Neither will be to refactor the whole inherited code.
I'm asking you if there is a way to clear the cache programmatically using BluetoothGattServer.
One solution - solve this issue using reflection.
private void refreshDeviceCache(BluetoothGatt gatt) {
try {
Method localMethod = gatt.getClass().getMethod("refresh");
if(localMethod != null) {
localMethod.invoke(gatt);
}
} catch(Exception localException) {
Log.d("Exception", localException.toString());
}
}
Note : I am not recommended this way