I'm working on an application that handles text messages. This is a personal application and I do not plan to release it, however it's basically going to allow me to share my text messages (and phone number) between numerous devices through the internet. It's a fun learning project too as a first application, and I've done quite a lot.
However the annoying part is the text-message popup that my device gets when receiving a message. I love it when I'm using the device, and I could always just go into the options and disable the popup when I'm not planning on using the device, but I'm a very, very forgetful person and turning it back on wont always happen. Then I'll never reply to messages.
Basically I want to programmatically interrupt (or not even notify) my default messaging application of the text message, however I still want it to be logged in my messaging history. So the message can't just be "discarded". This should only happen of-course while my applications service is running.
I've been searching through the android API for quite some time and I just can't seem to figure this out, is it possible and if so can you link me to the proper place in the API to begin?
Basically I want to programmatically interrupt (or not even notify) my default messaging application of the text message...
This isn't possible.
Assuming by "interrupt" you mean to prevent the default SMS app from issuing its Notification, you can no more do this with the default app than you could with any other app that you don't control.
Additionally, as the default SMS app responds to the SMS_DELIVER_ACTION broadcast, and it is the only app to receive this broadcast, it wouldn't be possible to "not...notify" the default app of an incoming message. Your app wouldn't even have a chance to abort the broadcast, even if it were possible to do so.
(In versions prior to KitKat, it was oftentimes possible to register a Receiver with a high priority for the SMS_RECEIVED_ACTION broadcast, and then abort the broadcast before the native SMS app received it. This is what rajan ks's answer refers to.)
...however I still want it to be logged in my messaging history.
The default SMS app is responsible for writing all incoming messages to the Provider. Even if you were able to prevent the default app from receiving the incoming message, your app would then have to write the message itself. This isn't really possible, either, as the default app is the only one with standard write access to the Provider.
Related
Currently the Android application I have taken in charge performs a "pull" on the server every minute to recover data and update a fragment with this data. Obviously this does not work when the device switches to doze mode. So I decided to use FCM as Google recommends.
Constraints :
The user needs to know that new data is available even in doze mode.
To not change the application too much, I do not want to send the data in the firebase message but rather send an https request to the server when I receive the fcm message.
The fcm message must:
Advise the user that new data is available with a notification.
If the user presses the notification OR returns to the application after turning the screen on, the https request must be triggered and fragment has to be updated.
I will add that it must be triggered at the latest when the user returns to the application.
My solution for now
I used a data message with a high priority instead of a notification message because a notification message need the user to tape the notification to trigger action.
In onMessageReceived :
I send the notification that redirects to my application.
I send my request to the server and update my application.
Disadvantage of my solution :
If my app is killed by the system while the screen was off what's going on?
My request has a time limit to complete when the phone come out of doze mode.
Questions :
Is this solution the best possible ?
Is there another way to proceed?
Perhaps could i schedule a task that runs immediately when user resume my app in onMessage received ? But i dont know how to do that.
Use WorkManager to schedule the background work to run immediately. It will also retry until your code indicates that it's successful.
I answer myself to close the subject and hope it can help someone !
After a night ... I definitely do not like the workmanager solution. Even if in practice it can work I do not like to use APIs for unplanned uses. If google tells me that it is not garanty to launch task immediately, they are (much :)) better than me and I believe them!
In this case, I think that my task may be postponed, for example because the OS wants to group calls with other apps. There may be internal conditions i dont know about.
Especially since I found a much simpler solution.
In onMessageReceived, I use a simple boolean indicator.
In the onResume of the activity I want to update I read this indicator and I launch my request if true for example.
I no longer need a scheduler, and after all if it is not done 100% reliable, it does not matter :
If fcm could send me a message there is a lot of chance there is a network when the user turn on the screen.
Even if there is none it is not very serious since I can warn the user who can proceed otherwise (by phoning for example !!!!)
Good evening!
I'm developing a chat application that looks like WhatsApp. I need the received messages to be saved on the user's mobile device. Until then everything was ok, because I was saving the messages when the user received the push notification on the mobile, but the problem happens when the application is closed because when the application is closed the push notification does not trigger the received push event (I am using the Onesignal to send the push).
I'd like to know how I can do this, ie get a notification and process it even with my closed application. I think it has to do this because Whatsapp does this and also Spotify also does it when I connect the Spotify to another device it automatically forces the opening of the application on my cell phone.
So my question is, how do I handle an event with the application closed or even force it to open according to a particular event?
I'm using the technology of Ionic 1 and Angular.js. For push notification I am using the OneSignal provider.
Thanks in advance for your attention and hope someone can help me. Thank you!
I'm fairly sure you won't be able to do what you're describing. There is a 'background push' feature introduced in iOS 9 that lets an app receive a payload triggered via push even when it is closed, but that's more for downloading (for example) a new edition of an online magazine, rather than lots of messages.
The difference betwen those two use cases is that if you're subscribed to a magazine, you might want the latest issue to download automatically whilst you have an internet connection, so that you have the issue to read when you're flying/on the train or whatever. A chat app... is pretty useless if you're not connected to the internet anyway, so there's no urgent need to have new messages 'pre-downloaded'
Even if you could do it, I don't think it would be best practice as there's too many scenarios where people won't have internet anyway so you're going to be left without the full message history when a user opens the app (not to mention push notification delivery is not tracked or guaranteed), so you're going to have to do some sort of query when the app launches to download new messages anyway.
If you've got code already that checks and downloads new messages while the app is open, that's great. But if its closed, you'll just need to run some sort of query on launch to download unread messages or something like that
When I create/update a Google Event from my app using java client:
events
.insert(originalCalendarId, googleEvent)
.setSupportsAttachments(true)
.execute()
I'm still getting push-notifications about event creation/update.
I don't want to get them since I'm the one who did these changes. The changes are applied on the app in a different way and additional push notifications are useless in this case.
However, I need to get new changes when they are made somewhere else(another app or Google Web UI).
Is there a way to handle this case? Maybe there is an approach to make Google know that push-notifications for specific queries aren't needed.
I also see that there is a property:
com.google.api.services.calendar.Calendar.Events.Insert#sendNotifications
But, no matter what I set here, notifications are still sent.
I think you have subscribed for a resource and you expect do not receive push notifications if your application have just done some changes. So you should use:
.insert(originalCalendarId, googleEvent)
.setSupportsAttachments(true)
.setSendNotifications(false)
.execute()
If you receive any way push notifications please check in your push notification X-Goog-Channel-ID with your own to be sure that is Google issue. I believe you have some old subscriptions that was not handled correctly and this is reason why do you receive the changes over push notifications.
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.
If I am developing an Android application, what is the most feasible way to get near real-time notifications about an incoming email? Is there a push-like mechanism, or can I hold my IMAP connection for a long time, or do I use IDLE command?
Consider that user is authorized to use GMail services via OAuth and I don't want to poll IMAP server madly.
Update:
I'm not using the phone's configured-in Google account. There is another account set up using OAuth.
I'm using Apache Commons Net to connect to IMAP/SMTP in my app. It's a bare-bone library for IMAP, but I can perhaps modify it to add IMAP commands/extensions.
You can register a ContentObserver with GMail, anytime something changes in GMail, the observer will be called.
contentResolver.registerContentObserver(Uri.parse("content://gmail-ls"), true, myContentObserver );
Override onChange in your ContentObserver to do stuff when something in GMail changes.
Since IMAP does natively provide any sort of push notifications and the Google extensions don't either, you have to implement it yourself.
One way is to use IDLE requests, which is still a cheap way to do polling. Of course, you can't expect your app to be running all the time, so you need to use a background service. An 'always-on' service is however an anti-pattern on Android and will drain the battery quickly and likely get you many 1-stars. Additionally the system may decide to kill it at any time. The other alternative is to use AlarmManager to start the service periodically, but starting it every couple of seconds or so is just as bad. So you are basically back to square one: polling.
The other way is to get push notifications using GCM or a similar service. This does require you to have a server, and the server needs to have the authentication info for the user (which might be a problem), but there are no real constraints concerning keeping open connections and sending IDLEs each second, etc. On the Android side, if you want to implement push yourself, you need to keep an open socket to get notifications. This is not very easy to do if you are not a system app (see above), so that leaves GCM. The connection it uses is manged by the system (Google Services framework), it can do things a regular app cannot, and you basically get it for free, since it's already there. It receives small pieces of data when there is something to do, called 'tickles'. Those in turn trigger broadcasts, Google Play updates, etc.
So, take your pick. Or just give up, register the account and use GMail and its labels Android API.
I'd check out Google Cloud Messaging (GCM):
http://developer.android.com/training/cloudsync/gcm.html
My understanding is that this works without requiring the user's Google account, and lets you handle authentication.
See a tutorial here:
http://www.techrepublic.com/blog/app-builder/implementing-googles-cloud-to-device-messaging/428
You would need additional server-side code running to do this though.