Android Peripheral BluetoothGattServerCallback onServiceAdded() not getting called - java

So I have a simple Peripheral application that I am coding in Android Studio running on my Samsung S8 mobile phone. I can setup all my BLE Advertisements and Characteristics just fine but when I add my services. I am not seeing expected results when connected from a another Central device (ie. another mobile phone that has an app to discover bluetooth advertisements).
LogCat output from Android Studio:
As per the Log, I can only see 2 default services that are Generic Attribute(1800) and Generic Access (1801) which are the default services for any Gatt server. I feel that I am missing the "onServiceAdded()" callback that is supposed to tell whether the service was indeed added and discoverable.
My code has no errors and the addService() call is successful. My question is why am I not able to get a response back from onServiceAdded()? While other Override functions like onConnectionStateChange() seem to work fine. This seems to be very basic and I looked at tons of examples but cant seem to get this last bit to work. Anyone with a solution or some good references to look at would be greatly appreciated.

I had the same issue (Nokia 6.1) where onServiceAdded was called only once although I was adding 2 services and I was getting randomly
onCharacteristicReadRequest() no char for handle nnn
when trying to connect from another device.
I found a relevant point in the documentation https://developer.android.com/reference/android/bluetooth/BluetoothGattServer.html#addService(android.bluetooth.BluetoothGattService)
The BluetoothGattServerCallback.onServiceAdded(int,
BluetoothGattService) callback will indicate whether this service has
been added successfully. Do not add another service before this
callback.
The reliable solution I found was to add one service, wait for onServiceAdded to be called, then add the second service, wait for onServiceAdded again and then I call startAdvertising.

I had the same issue, and it seems like callback is not called when a client(Center) was previously connected when the GATT server was restarting.
If you disconnect all the clients and restart the server(peripheral) from clean state, you will see the callback working(in my case, even with 2 services added).
My server is Samsung Galaxy S7(Android 8.0) as well. Client was Android 7 devices.
(In addition to this callback issue:)
There is some caching or strange thing going on, and if you had previous connection it does not work well with multiple services(one predefined and one custom). In my case, when a client was already connected and if I add more than 1 service to the server when starting, gattServer.getService(uuid) was returning null. Adding one service was ok.

Related

Android: have app send request to another app over network (on other phone)

I have two apps: "app" and "receiver", the latter of which also runs as a service on the phone. These are designed to be run on two separate phones - only one receiver will ever exist, which will be on my phone.
I'll try to make the problem as simple as I can: from the app, I'd like to be able to press a button saying 'hello', which would then load up an activity on the receiver's phone (from the service) also saying 'hello'. Pretty much I just don't know how to get the two devices to talk to each other. This will only be used over the same Wi-Fi connection. Would a broadcast be a suitable way to do this?
I've just started Android development a few days ago so I'm not sure how to do it - it's probably simple - and any help will be massively appreciated!
Many thanks!
Would a broadcast be a suitable way to do this?
No. Broadcasts can be used for inter-app communication, not inter-device communication.
Instead, devices on the same LAN can adress each other using their local IPs (usually 192.168.x.x).
One option would be to open a socket connection, see how to create Socket connection in Android?

Android/Smack: Keep XMPP connection alive in sleep mode

I have an Android application that has a chat client as one of its features. The chat client uses XMPP based on the Smack library for Android and running Openfire as XMPP server in the background. The connection is established using BOSH The whole XMPP connection handling is implemented as a service to run and listen in the background for incoming messages even if not activity of the app is in the foreground. So far, everything works perfectly fine.
The only problem seems to be the sleep mode. In the emulator (when set to "Stay Awake") or with the phone in use, the XMPP connections is holding and the app can send and receive messages. However, once the phone goes into sleep mode, the XMPP connection breaks down -- I can see it in the Admin Console of the Openfire server that the user is offline. Intuitively, I want to receive messages all the time like, e.g., WhatsApp.
Of course, I've searched online including Stackoverflow, but I couldn't get a definitive answer. Often the use case seems to be that a task has to be performed periodically, say, once every hour. But this doesn't seem to fir in case of a chat client. Since I assume this is a common use case -- after all, there a so many chat apps or apps with chat features out there -- these are my question:
How to I have to change / extend the app that I can receive chat message while the phone is sleeping?
I've stumbled upon WakeLock. Is this the way to go or are these not suitable for my use case?
Since Lollipop, there's also the JobScheduler API which itself uses WakeLock. Any better?
How does, for example, WhatsApp handles this case?
On a side note: I have problems with the sleep mode using the emulator for debugging. When I switch off "Stay Awake" in the emulator, the screen goes black after 1+ min and the XMPP connection breaks. But I somehow have no idea how to wake up / switch the emulator back on once it went black. Android Studio actually tells me at some point that the device or something is gone, and I have to restart the emulator again.
The exact way to resolve this issue is by using push notification.
It is the natural behavior of XMPP connection to get disconnected after the specified idle interval i.e when the device goes to sleep.
Coming to the case of WhatsApp, it also uses the same XMPP and maintains a server which acts as a wrapper class on the messages exchanged. This server checks the message status whether it is delivered or not. If not delivered, it sends a push notification, now at the device end in the push service when a message is received, it checks if the connection is active and is authenticated or not.
If not authenticated, it re-establishes the connection. In this way, the most chat apps manage this timeout exception.
Hope this helps :)
You don't need push notifications, you don't need WakeLocks. Instead simply
Whitelist your app from doze mode
Use a sticky (START_STICKY) background service
Use Smack's ServerPingWithAlarmManager
Act on CONNECTIVY_CHANGED intents send by Android, and use XMPPTCPConnection's instantShutdown() in that case.

What is the established way to request data from an android device

I currently have an small application that I have been using to learn java/android programming. Right now I have a setup were the app on one phone sends a request (via sms) to another phone running the same app. The remote phone receives the request and sends back some info. Next I would like to try this from the web. Is there an established "best" way to to this?
I was thinking I would have a web server send requests to the device via google cloud messaging and then have the device return the data directly to the web server. (Not that I really know how to do any of that just yet).
I see that there is a google cloud messaging return path (send messages from the device to the google cloud server, but it seems very new, do I need something like that? The main thing I want is to be able to ask the phone to do something when I want, not have it poll to see if there is a request, or just periodically update some status.
UPDATE:
Thanks to the answers below for confirming to me that I was on the right track.
I now have some basic functionality.
I started out using this gcm android demo code
https://code.google.com/p/gcm/source/browse/#git%2Fgcm-client%2Fsrc%2Fcom%2Fgoogle%2Fandroid%2Fgcm%2Fdemo%2Fapp%253Fstate%253Dclosed
and this ruby gem
https://github.com/spacialdb/gcm/blob/master/README.md
between the above two I was able to send a message to my phone pretty easily.
To get the round trip working, I setup a very simple rails app on heroku.
I included a modified version of the sample code in the gcm gem in a controller and then used
HttpPatch (needed for rails 4) to send a post/patch from my phone to my web app, the controller then echoes the message back to my phone.
I guess it would be nice to get the two way gcm stuff to work, but I am not sure there are any gems that handle that, and I am not qualified to handle a task like that :)
I would say it's the right call: Google Cloud Messaging for Android
From the site Android Developer:
This could be a lightweight message telling your app there is new data
to be fetched from the server (for instance, a movie uploaded by a
friend), or it could be a message containing up to 4kb of payload data
(so apps like instant messaging can consume the message directly).
In this case you don't want to fetch data from the server but you want to send them.
You can send them in different ways. I would suggest, since you are learning, to try a RESTful solution using one of the implementation of JAX-RS.
As a short and direct answer for beginner : GCM (Google Cloud Messaging) would solve your issue. However, if your app turned out to be something bigger, other more technical and complicated solutions are present too.
see this link.

Google play game services invitations get lost

I am using the new Google Play Game Services to develop my game on Android and I am now trying to include the invitation system.
Have have 3 Google+ accounts that I use to try the invitations with 2 Android devices and 1 Android emulator.
My problem is that the invitations are not always received when they are sent. Sometimes it works fast and perfectly, sometimes it won't work. Just cancelling the invitation and trying again can change the result.
Here a 3 tests I did just to make it clearer :
Test 1: Emulator was inviter, Nexus 4 didn't receive and Optimus One received
Test 2: Nexus 4 was inviter, Emulator received and Optimus One received
Test 3: Optimus One was inviter, Emulator received and Nexus 4 didn't receive
From those results we can see that my Nexus 4 received no invitation, but it worked several times before those tests.
Furthermore, sometimes I receive the invitation notification (on the status bar), but most of the time I don't receive it.
Did someone experienced the same abnormalities as I did?
It may be to do with the accounts you are signed in on.
I've found that I can send invites fine from my dev account to the 'test' account but not the other way around.
If you are using a Wi-Fi hotspot (wireless router) for testing and there are other Wi-Fi hotspots in the vicinity, they can interfere with your Wi-Fi signal and block game invitations. Although there are 11 channels available on the 2.4 GHz band that most routers use, most wireless routers default to using the same channel (6). If you are in this situation, try changing the channel your router uses.
This problem kept me flummoxed for several weeks.
Some pointers:
Check that all the test accounts have one another in their circles. So, if your test accounts are A, B and C, then A should have B and C in their circles, B should have A and C, and C should have A and B.
The time it takes for an invitation to be delivered may vary; network connectivity is a large factor in that. Don't give up too early -- wait up to 1 minute without quitting the handshake process, and the invitation should appear.
If the game is unpublished, make sure that all test accounts are listed in the Testing section of the application's settings on Developer Console. If a tester is not listed, they will not get an invitation popup. Note: even the developer who created the app on Developer Console must be listed as a tester.
If you are using Games.Invitations.registerInvitationListener() your code is expected to handle the invitation and you will not get a standard android notification. Now, if you are not calling Games.Invitations.unregisterInvitationListener() at the appropriate times, maybe your code is not handling the invitation properly and it is consuming it without your will.

Android c2dm push notifications after app reinstall

I have the following question:
I've successfully implemented C2DM in my application. I'm registering to both google c2dm cloud and a custom server that "creates" notification contents. Everything is working fine.
My question is : what happens when i uninstall my app and then reinstall it on the same device? I've noticed that C2DM is sending me back the same app_key, so apparently there's no way to determine my app installation status change. And i keep on receiving old push notification (they're customized by user preferences in the app).
I won't be able to test with a google play published app until final release, so i would like to know if there's a chance that google itself could notify c2dm that the app was uninstalled on my device and force it to change my app_id at next restart.
Thanks in advance
Stefano
From what I understand in C2DM, you shouldn't depend on Google's registration ID by itself. They "promise" nothing - you might even get a new registration ID without a clear reason (might be their own vrsion upgrades, etc.).
If you want to follow installation - you should do it with your own server - create a unique identifier whenever the app asks for registration, and use it and not the Google's registration ID.
Regarding to Google Play - couldn't find a difference between published app and unpublished one - the behavior seems to be the same.
Hope this helps somehow.
Shushu

Categories