Android C2DM sleeping phone - android

According to this Android C2DM keeps a socket alive with a heartbeat mechanism, making it able to receive push messages. This made me hope I could deliver messages to sleeping phones with an active wifi connection.
I've made an implementation setting the "delay_while_idle" to '0'. The message is delivered if my phones' screen is powered off, but not if the phone goes to sleep (tested with intervals 20mins, 1-6 hours).
I have acquired a partial cpu lock + a full wifi lock just in case.
Have I simply made something fundamentally wrong or did I misunderstand the C2DM push functionality?
Can I send messages to sleeping phones or not?

Using alarmmanager instead of wakelocks could keep your phone alive just enough. See this implementation. Will test a variant of this.

Related

Android: Delay in Receiving message in FCM(onMessageReceived)

In Test app, I have implemented FCM for sending notification messages using
https://github.com/firebase/quickstart-android/tree/master/messaging
For testing I sent the message(8:42 PM) from firebase console using the "New Message" under Notification.
But in my emulator, I have received the message at 9:06 PM
Please let me know if there is anything to do reduce the delay.
Thank you.
This could be caused by the unrealistic heartbeat intervals in Firebase Cloud Messaging.
FCM works by maintaining an idle socket connection from an Android device to Google’s servers. This is great because it barely consumes battery power (contrary to polling), and it allows the device to be woken up instantly when a message arrives.
To make sure that the connection remains active, Android will send a heartbeat every 28 minutes on mobile connection and every 15 minutes on WiFi. If the heartbeat failed, the connection has been terminated, and FCM will re-establish it and attempt to retrieve any pending push notifications. The higher the heartbeat interval, the less battery consumed and the less times the device has to be woken up from sleep.
However, this comes at a great price: the longer the heartbeat interval, the longer it takes to identify a broken socket connection. Google has not tested these intervals in real-life situations thoroughly enough before deploying FCM. The problem with these intervals is caused by network routers and mobile carriers, who disconnect idle socket connections after a few minutes of inactivity.
More info is available on my blog:
http://eladnava.com/google-cloud-messaging-extremely-unreliable/
As a workaround, please consider Pushy (https://pushy.me), a drop-in replacement for GCM/FCM which greatly improves notification speed & reliability (Full disclosure - I founded Pushy).
My best guess is that this has to do with the message priority.
From the docs:
Setting the priority of a message
You have two options for assigning delivery priority to downstream messages on Android: normal and high priority. Delivery of normal and high priority messages works like this:
Normal priority. This is the default priority for data messages. Normal priority messages won't open network connections on a sleeping device, and their delivery may be delayed to conserve the battery. For less time-sensitive messages, such as notifications of new email or other data to sync, choose normal delivery priority.
High priority. This is the default priority for notification messages. FCM attempts to deliver high priority messages immediately, allowing the FCM service to wake a sleeping device when possible and open a network connection to your app server. Apps with instant messaging, chat, or voice call alerts, for example, generally need to open a network connection and make sure FCM delivers the message to the device without delay. Set high priority if the message is time-critical and requires the user's immediate interaction, but beware that setting your messages to high priority contributes more to battery drain compared with normal priority messages.
I am not certain, but I believe that normal priority is used when you send a message to "All Android devices", which it seems you are doing in the question above. It is also possible that it is being sent to a FCM topic, which is optimized for throughput rather than latency
So, setting the priority to high, or sending to one specific device rather than a topic, should reduce the delay you are seeing.
Also; Be aware that push messages are based on best effort. There are no guarantees that the message will be delivered by a given time, or at all.
This issue tracker is dedicated to issues related to the Android Quickstart. The gurus working on this project don't have access to any diagnostics to help troubleshoot FCM issues. Please contact support . https://firebase.google.com/support/

Android wearablelistenerservice not listening when phone asleep

I have a small home automation application running on my phone which listens for the 'command' from a wearable and sends a get request.
When the phones screen is on (i.e. the device is awake) these messages are received by my WearableListenerService however when the phone goes to sleep the messages are not passed from the Wear device to the phone.
If I send a message from the wearable to the phone when the phone is asleep, and then I wake up the phone manually within the message timeout period, the message is received and the get request subsequently fired.
I was wondering if there is any way to keep the WearableListenerService listening even when the device is locked, I am aware of WakeLocks but these seem to be terrible for battery life.
I am struggling to see if this is the defined behaviour of an AndroidWearableService or whether some external factors are at play (I am using an xperia z5)
The send message does not gaurantee the message will be delivered. I would suggest you try data api. and monitor the changes through onDatachanged

Android bluetooth wake up device

I bought myself a smartwatch that has Android KitKat running.
I have connected it to my HTC m9 smartphone using Bluetooth.
I have created an application that is running on both smartwatch(client mode) and smartphone(server mode).
The applications are talking each other over a Bluetooth Socket connection.
When I get a phone call on my phone, I am sending a Bluetooth notification over the Bluetooth socket to the watch and make it vibrate.
All is good as long as the watch's CPU is up and running.
When the watch goes to sleep, and I get a phone call on the smartphone, the notification is not processed by the watch because watch's CPU is sleeping.
Using a partial lock on the watch does the thing but it consumes the battery to fast.
I don't need a partial lock on the phone, because when the phone receives a call, the phone is "magically" awaken, so my application's service is able to send the notification.
I also can't use AlarmManager on the watch, because I need the watch to wake up when I get a bluetooth socket notification, not on regular intervals.
A WakefullRecevier is also not solving the problem because my watch needs to wake up first so that the WakefullReceiver puts the power lock (or have I got this wrong ?!) and runs its code.
So the question is: How does the phone wake up on incoming call? Or on SMS received? It is a hardware thing..an interrupt?
Is there any way of waking up the watch when a bluetooth message is received?
Thank you
For the past few days I've been playing around with the watch making different tests.
I am not answering the original question but since nobody else answered the question I will just write down my own conclusions which are good enough for my application and maybe help others with similar problems.
1. When the paired watch is in Bluetooth range of the phone, a power lock is not needed on the watch.
Any messages sent by the phone are received by the watch.
If the watch stays idle for some time, the 1st Bluetooth message sent by the phone is received with about 1 second delay. Probably Android watch goes into some kind of low power mode but is able run my code when Bluetooth message is received. Of course Bluetooth messages are received almost immediately by the watch while the watch is not idle.
2. Best way to find out if a Bluetooth socket is still connected, is to write into it.
Socket read is a blocking call but it does not throw IOException when watch goes out of Bluetooth range. I wasn't able to find a read timeout property I can change.
So I am just writing a byte into the socket every 60 seconds to detect if socket is not connected anymore. Battery impact is minimum while socket down detection timing is acceptable.
3. When the paired watch is NOT in Bluetooth range of the phone anymore, Bluetooth socket re-connect strategy is required.
Using a partial lock in this case does not seem like a good approach since it keeps the CPU awake. Also trying to re-connect to often to the phone kills the battery.
The re-connect strategy is based on application needs.
I ended up using WakefulBroadcastReceiver and AlarmManager to make a socket connect attempt with a given period.
4. Every now and then, when the watch goes out of Bluetooth range, then comes back into range, then again and again the Bluetooth socket seems to go in some kind of 'zombie' state. Sometimes the socket.connect call just blocks without succeeding or throwing error, some other times the socket.connectcall does not throw error given the impression that connection has been established, but a subsequent write always throws IOException.
Whenever I encounter these kinds of situations I just stop/start Bluetooth adapter which seems to solve the problem.
5. Pay attention to stop/start the Bluetooth adapter. During Bluetooth restart attempt Android can put the CPU to sleep. I wasn't expecting this behavior but it really happens. So if you want to do this as fast as possible without any delay, make sure the application acquires a PARTIAL_WAKE_LOCK during the re-start attempt. Of course don't forget to release the lock as soon as possible.

How to receive call on android + pjsip when phone in deep sleep

I'm trying to build voip app based on PJSIP on Android. I decided to use TCP for connection to make the connection be persistent. And app right now has background service (same process) which is responsible for all interactions with SIP server. TCP keep alive timeout is set to 1 minute (just for testing purposes). Everything works fine until the moment when phone goes into a deep sleep mode. From logs I see that phone still sends TCP KA but with 4 minutes interval (why???). But the main issue is if I try to call from another phone to this one the phone keeps sleeping and skips all INVITE messages. Appreciate any help.
When the Android device goes into deep sleep, the CPU throttles down and almost all OS services are suspended. See for example:
Android Sleep/Standby Mode
what is the difference between Sleep mode and Deep sleep mode?
If this were not the case, the OS and most other components would still be on, which would drain battery extremely fast, and most users would uninstall your app.
In order to receive incoming messages (such as the INVITE), it's recommended to use GCM. In this, you need to implement a server piece that is essentially handling the client's responsibilities while the client device is asleep.

How to wake up an Android on incoming data

I want an Android service, which is listening for data (I have tried TCP and UDP) to wake up the service/phone when data arrives.
Currently the phone stays asleep when IP data arrives and that data is lost. Is this normal for Android? I see sleeps of 2+ hours several times a day, and 7+ hour sleeps when I am asleep.
Does GCM provided a solution which wakes up a service/phone when a message arrives.
I need messages to be displayed within a few seconds of them being sent from the server.
Can this only be achieved by keeping the CPU running all day long? Is there no interrupt from the GSM modem on the arrival of data?
As I understand it, if you have an outstanding socket connection over mobile data to a server, that socket connection is maintained while in sleep mode, and incoming packets will wake up the phone out of sleep mode (briefly) to deliver the data.
The same is not true of WiFi (and presumably not for hardwired Ethernet, either). You would need to hold a WakeLock and a WifiLock.
Does GCM provided a solution which wakes up a service/phone when a message arrives.
Yes, but...
I need messages to be displayed within a few seconds of them being sent from the server.
First, GCM has no service-level guarantee. I am not aware of any solution that does, including anything that you might roll yourself (e.g., MQTT).
Second, you have no idea if the device is capable of receiving any such messages (GCM or otherwise), as the device may be turned off, in airplane mode, etc.

Categories

Resources