I made a RSS reader app for android and it gets the latest news from a RSS feed. I want to show a Notification to the user when a news is published to the website or the RSS feed. How can I check for new data?
You can create something which is called polling. Actually many rss reader apps using polling technique in which their
service wakes up at a regular interval to contact a server to see if new data needs to be processed.
This means that the application needs to wake up to look for new data even if none is
available to be processed. Read about IntentService and AlarmManager. Basically you can create AlarmManager which is going to start every amount of time that you want for example every hour. Than you can start a service which is going to check is new data available. If it is new data for processed available raise a notification on user phone. Set AlarmManager to fires up again for an hour and the service should shutt down itself. Hope this will help.
Related
I have a task to fetch data from server at start if application. For purpose i am calling an api by asynctask for notification codes and parse data. The data can go upto 60000 notification codes.
For each notification code i have to call different apis to get data. After performing operation i need to again call an acknowledge api to tell server notification has been acknowledged. So next time when getting notification code it dont repeat.
So in the case i have to call approximately 60000 asynctask for operation and 60000 for acknowledgement. Do each operation for different api urls and then Acknowledge each operation for different url simultaneously
My app is working when notifications are below 1000 but for more than that notification it stucks.
Please anyone can guide what's the best way to implement this.
The PeriodicTimeRequest has a minimum periodic time of 15 minutes. But I see, that for example Google Maps location sharing can update more frequently than that, and facebook messenger can also receive messages almost instantly.
I would like to send a notification to the user, when it got a new message. My application has to work on local network, so Firebase is not an option. I have to send a json request to the server, and if there is a new message, I show a notification to the user.
Regarding FCM:
FCM, which is available in all devices with Google Play takes the weight of subscribing to and receiving push events, under all the resource constraints Android has been ever introducing.
It's tightly coupled with the OS and is unified (one entity, one persistent connection for all apps in your device), which is why it works :)
Regarding Frequency of your Work:
Given your requirement of more frequent pings to the server, you'd need to have a service which runs all the time, i.e. A Foreground Service.
It is resource consuming though, so good luck convincing the user with a good reason why it should stay alive all the time.
I think you've managed to make the client-server interaction possible, since identifying a server in a local network is a huge task in itself.
use this in your service.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
CountDownTimer timer = new CountDownTimer(15 * 60 * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
// execute your task here, every sec
//if you want increase the count down interval from 1000 to what you want
}
#Override
public void onFinish() {
this.start();
// it will start again.
}
};
timer.start();
return START_STICKY;
}
I am afraid it is not going to be possible without using a set of workarounds. Which means you might not get a consistent behavior.
#Arvind has done a very good job explaining the benefits of a Firebase Service and it is the recommended approach for achieving such task.
First I'd like to point out that such restrictions on the WorkManager exist because Android has been suffering (between other things) of developers trying to abuse some mechanisms to get their software working and at the end of the day, the battery of the users had been suffering from such abuses and since Android 6 Google has started trying to address these issues. There's a good read for you over here about Doze mode and how to work with it
I am pointing this stuff out because I've been trying to build a chat service that wouldn't rely on Firebase and I really don't want you to waste as much time as me banging your head against a wall. There are things that you simply can't fight. That means that if the device enters in a "deep-sleep" mode sometimes you can only accept it.
My approach
Please
keep in mind the user interests and the life of their batteries and try to be as smooth as you can with their devices and this is just a workaround over the restrictions that have been imposed upon us. And that I discourage this approach due to the amount of work that it takes to pull off and for how misused it can be.
My solution
Essentially, to get notified (ie getting your code running) in an Android App you're going to be wanting to receive system events or Broadcasts. This is where you set up a BroadcastReceiver and you get Intents delivered to it and you can act upon them accordingly. BUT YOU HAVE TO BE QUICK BECAUSE YOU HAVE ONLY 10 SECONDS OF RUNTIME BEFORE THE OS KILLS THE PROCESS AGAIN. Ideally you would have a really quick server so you can have very little IO times to ensure you can be within 10 second restriction as frequently as possible.
So essentially you would be using a combination various of services that you would like to be monitoring in order to get notifications (aka Broadcasts) whenever the state of those changes. Here are a few ideas:
WiFi state (which will also be useful to see if you can reach your local server)
Bluetooth Low Energy packets (or Nearby which may solve the entirety of your problem depending on Nearby's capabilities)
WorkManager as you already pointed out.
AlarmManager to schedule a broadcast of intents every so often.
Geofencing (although it involves reading the user's location; you can set really small geofences around the office building and get notified by a Broadacast when users go through that geofence)
So whenever you receive a Broadcast of these sources you would handle such notifications from within the same BroadcastReceiver
From the implementation body of this Broadcast receiver you would poll the local network's server to check whether if your user has new messages or not and lift up a notification. And it's important to keep the amount of work and IO times the app has to do at a minimum since those add up and you've got only 10 seconds.
You can get around the 10 second mark if you launch a ForegroundService. Then, that period of time is going to be extended until a 10 minute mark and you will need a visible notification for the user stating something that you're checking if it's got any new messages.
Keep in mind
Don't stress the user's battery too much. Or Android will penalise your app and you'll end up notified less often or even completely not notified.
Be gentle with the user. If the user has to force-kill your app at some point it will stop receiving any sort of Broadcasts or running any sort of WorkTasks.
This solution can behave differently accross devices. Since the decisions of notifying your app are made by the OS, different OS (redmi, samsung, meizu...) you are likely to not end up with a consistent behavior across all devices
You don't have control over things, the OS does
Within measure, try to time your Broadcasts to your BroadcastReceiver within spans of 3 minutes or so; so you are always receiving a Broadcast below the 15 minute mark.
I am trying to implement a background service that makes an HTTP request to an API every 15mins for the whole day, starting when a certain activity is started. I need the service to be started every 15 minutes even if my application is not running or I am in another activity of that application. I've searched for an example for how to proceed an have looked at some Stackoverflow questions and answers for example: Start Android Service after every 5 minutes. which linked to this page : http://code4reference.com/2012/07/tutorial-on-android-alarmmanager/
From the discussion I know that I need to use an alarm manager, however all the implementations do not have this being done in the same activity they have broadcast receiver. The reason I would want to have the implementation in the same activity is because the results of the request is what I want to display on the UI.
Is there a way of implementing an alarm manager in this type of situation
however all the implementations do not have this being done in the same activity they have broadcast receiver
That is because that is your only viable option, and even that will not work well on Android 6.0+. The recipe for using AlarmManager for this sort of scenario is to have it start a WakefulBroadcastReceiver, which in turn will work with an IntentService to do the work and go away when the work is completed.
On Android 6.0+, courtesy of "Doze mode", your AlarmManager events will not fire every 15 minutes, if the device is not charging and not moving. Also, courtesy of "app standby" on Android 6.0+, your AlarmManager events will not fire every 15 minutes, if the user has not been in your application's UI for some time and the device is not charging.
The reason I would want to have the implementation in the same activity is because the results of the request is what I want to display on the UI.
This runs counter to an earlier statement that you made:
I need the service to be started every 15 minutes even if my application is not running
If your application is not running, then you do not have an activity.
You are welcome to have your IntentService post a message on an event bus, such as greenrobot's EventBus, to let your activity know about the results of the work... if the activity happens to be around (otherwise, the message will be ignored).
tl;dr: my app doesn't update my SharedPreferences with the last value from the server because sometimes the phone is sleeping.
Explanation:
I'm new in this android world, and I've been working on my first "real" application but I'm having a few issues right know...
Here's how I need my application to work:
Check every 30 minutes for new data (data is pulled from a json file on my server)
If the data is different from the stored on the phone, then store the new data and send a notification to the user. (I'm using SharedPreferences for the "storage")
Here's what I used to try to achieve that:
MainActivity.java / Activity (my main activity, duh')
cargarJson.java / AsyncTask (a class that pulls json data and returns a jsonobject). Cargar = Load (in spanish)
DolarService.java / IntentService (The service creates a loadJson object and execute it, then sends the notification).
AlarmReceiver.java / BroadcastReceiver (It's a receiver that has an AlarmManager that executes my DolarService every 30 minutes and runs everytime the phone boot up and when the user runs the app for the first time).
I kind of managed to do it, but the problem is that I don't want to use wakelocks because it drains the battery really fast.
My AlarmManager doesn't use wakelocks so when it sends the notification every 30 minutes it contains the last value stored in the SharedPreferences when the phone was "awake" and not the new data from the server.
Here's my source:
https://gist.github.com/anonymous/d5cccf5ba331f041630e
My question: how do I keep my up-to-date data in my SharedPreferences (updating it every 30 minutes) without using wakelocks. Also, is something wrong with my approach to do this app ?
Thank you in advance and sorry for my poor english, I tried my best to explain my situation!
It doesn't look like you're using wake locks. You can make sure of this, however, by removing your <uses-permission android:name="android.permission.WAKE_LOCK" /> from your manifest, and then you'll know for certain that your application isn't acquiring a wakelock, because it doesn't have permission.
Edit:
You're using your IntentService incorrectly. See the documentation on how to implement an IntentService. An IntentService already creates it's own worker thread, similar to an AsyncTask, so executing an AsyncTask within an intent service is unnecessary in your case. Instead, you should pull out everything in your AsyncTask and implement it in your IntentService's onHandleIntent(), rather than it's onCreate() and onDestroy() methods.
The other option would be to use a normal Service, and stop it in your AsyncTask's onPostExecute() method.
Also, this is a little off topic, but when passing a context to another object, you should use a WeakReference<T>:
WeakReference<Context> context;
public cargarJson(String jsonUrl, Context context) {
this.jsonUrl = jsonUrl;
this.context = new WeakReference<Context>(context);
}
All things are fine. But its good if you use a backgorund service for your server operations and start this service through the AlarmManager followed by PendingIntent in every 30 minutes.
For my app, I have about 15Mb (which can be compressed with some processing power to about 5Mb) of audio+video+image data that I need to save to disk. For instance, I need to save this when user is interrupted with a phone call (because the activity might get killed after this) and when the user leaves the app.
I can save the data to SD card in about 10 seconds if I don't compress it and something like 20 seconds if I do compress it, where I'd like it compressed. What options to I have for saving my data when onPause is called such that I can be sure the data has been saved?
From some basic experiments, my activity gets killed if onPause hasn't finished after 5 seconds. Some ideas I've had:
Starting a new Thread in onPause and saving the data there. This seems to work fine but seems like something I shouldn't be doing.
Starting a service, copying the data to the service somehow (would this be slow?) and then getting the service to save the data. I think this puts a notification icon at the top of the phone, but I don't think it's awful for a user to see the "Saving data..." task here.
Can I put the data in a SQL database quickly and then save it later when the user returns to the app?
(Due to the nature of the app, there really isn't any practical way I can save the data as I go because the user can transform the data in destructive ways with time consuming operations (e.g. 10 seconds for some operations). Even if I stored the original data and a list of the actions performed to recreate the data, the user would have to wait a minute or two when the app is next started up to process this.)
What options to I have for saving my data when onPause is called such that I can be sure the data has been saved?
Technically, what you want is impossible. There are no guarantees after onPause().
The best answer is what #Viktor Lannér suggested. To phrase it another way, don't wait until onPause() to need to do 10-20 seconds of I/O. Devise some mechanism to allow you to save incrementally as the user performs operations, as a fallback mechanism if nothing else. This is akin to how a database maintains a transaction log.
Starting a new Thread in onPause and saving the data there. This seems to work fine but seems like something I shouldn't be doing.
This is dangerous, because if the activity is closing (e.g., onDestroy() will be called momentarily), Android might terminate your process before your thread is completed.
Starting a service, copying the data to the service somehow (would this be slow?) and then getting the service to save the data. I think this puts a notification icon at the top of the phone, but I don't think it's awful for a user to see the "Saving data..." task here.
Make this be an IntentService, so it automatically shuts down when the work is complete. I wouldn't "copy the data to the service", but rather make the data centrally available, by a static data member if needed. This will not automatically put "a notification icon at the top of the phone", and for something of this duration, that is probably not needed.
Can I put the data in a SQL database quickly and then save it later when the user returns to the app?
Flash I/O is not faster for a SQL database than for anything else.
Due to the nature of the app, there really isn't any practical way I can save the data as I go because the user can transform the data in destructive ways with time consuming operations (e.g. 10 seconds for some operations
Then this probably isn't designed for a mobile platform. Consider whether this app is an appropriate use of the technology.