I am trying to implement a RESTful API in which I have to upload files that are relatively large for a mobile platform. The upload could take anywhere from 30 seconds to 5 minutes.
I would like my application to be completely usable while the upload takes place. I've been doing some research and I've come across a few methods from which I can't decide which is the correct solution to my problem.
These are the two things I have come across.
Using an IntentService -- handles the worker thread so I don't have to.
Using my own type of Service-- still need to implement an AsyncTask to handle the large process.
Implement an AsyncTask in a singleton file that would allow me to do all the work there but without using the service class.
My question is which method is the best -- if one isn't listed but is a more apt solution to my problem then I would appreciate suggestions.
After researching all these methods I am still also confused on one thing. Lets say I upload a 2MB files, but I want to know when it is done. For example, lets say I have a service that uploads an image and returns and imageID -- I need to be able to know when that service returns an imageID -- process that and then move on to the next upload until the rest are finished.
As always, thanks in advance.
EDIT: I forgot to specify that while uploading I want the app to be usable-- that means that I can switch activities and still have the same service run.
I used IntentService. It extends service so it basically has all the functions of the normal service, expect that it handles the threading for me so I don't have to worry about that. Its working very well at the moment.
Related
I have an IntentService for downloading files in the background. All it does is download a file and stash it on disk. The App flow involves starting bunch of these download tasks through this service through one Activity and a bit later on, retrieving these downloads through another Activity. For retrieval, I shall be facilitating the download Id and a location of the download to the receiver.
When it comes to retrieval, I am ready to busy-wait until all the downloads have completed because I will be depending on them for moving on further. That is fine except I have found no way to facilitate the following:
A mechanism where I am able to busy-wait for these downloads(like until count of these downloads at the receiver doesn't equal to the total count of downloads). How do I deliver these downloads?
Note: Broadcasting doesn't seem to be the solution as what will I do with these downloads until I don't have the Activity that doesn't actually require these downloads?
In my opinion there are multiple ways to achieve this. One way would be the already suggested
1) EventBus Sticky
EventBus Sticky technic, but this needs a new library that increases your App size. I would recommend this approach if you use it multiple times and not just once. An additional plus to EventBus is that it takes care of multithreading in an easy manner.
2) Only SharedPreferences
Use SharedPreferences to keep track of what has been downloaded and if it's finished already when you are starting the 'Show'-Activity. This approach is somehow limited to a certain amount that you can save. You probably should use that if you don't have to save a lot of file paths and you don't need to keep track of older data.
3) Database and SharedPreferences
Use a database like Room to save file paths and associate it with an integer as a serial. This integer could be used to describe groups of downloads. And every file path can be later on fetched with the appropriate download group number. You'll want this approach if you also want to show older download groups. In that case the groups 'serial'-integer and 'has finished'-boolean can be saved in SharedPreferences and checked when 'Show'-Activity is created.
4) Custom Controller Singleton
Build a Controller class that is a Singleton and is attached to your Application. It can be retrieved in your Activities and your IntentService by
((MyApplication) getApplicationContext()).getDownloadController()
and it can be observing the downloading process.
...
There are multiple ways I can think of e.g. a RxJava approach just to name it ;)
Hope you got a little overview of the possibilities.
If I understand you right I think you can use the
Greenrobot EventBus sticky-events Technic.
In short, the Service can propagate a sticky-event when all download are done.
If you now maybe 5 minutes later start your Activity that show the downloads, this Activity if it´s listening for this sticky-event, will get the now 5 minute old message.
Hope it helps
What would be the best approach for download on Android. You would be using AsyncTask or Service. I see several example being made of two ways, but what would be the best approach?
That's not the right question to ask, and the answer may be both. An AsyncTask is a separate thread of execution. A Service is just a piece of your app that runs in the background and can live past the end of an Activity.
You need to download any files on a non-UI thread, so either a Thread or AsyncTask is necessary whether you use a Service or not. So you'll always use one of those two. The question of whether or not to also use a service is a question of whether you need the file downloaded even if the user goes to another Activity (there's a few other reasons why you may want to use a Service, but this is the main one).
i suggest ,it depends upon the size of file.for small content file ,asynch is great but if is gonna be a longer task then you can go for service because service also comes with restart feature (start_sticky) in case user kill your app or your app got killed by the android os(LMK : low memory killer) in case of memory crises
I am a Java developer with no Android experience, and I am trying to quickly put an app together. It seems that what I would normally do in Java isn't helping.
At this stage, ease of implementation is more important than efficiency or style - I will sort the latter out when there is more time and I will have educated myself properly when it comes to Android.
People can use the app to ask for support, or offer it to those who need it. Asking for support posts a request with the details to the server, and that's done.
Now I would like the app to post an asynchronous request to the server, to be notified of outstanding support requests once a minute. I guess it's the same principle of WhatsApp checking if there is any new message on the server.
I tried doing that in a separate thread with an infinite loop which sleeps for 60 seconds but for some reasons that stops the UI from working.
From what I now understand, I should use a service with a Looper, a Timer and a Handler. Is that correct?
Could anybody point me to a tutorial which explains exactly what to do, step by step? Or at least suggest keywords I should look for?
All I found so far are snippets of code which don't work together when I try to assemble it. Possibly because I am not searching for the right terms?
Thanks, Dan
You could try the following approach:
Create a service that runs in the background to check for newly added data in the server.
If you prefer to make it user-driven, you can let users refresh the list on the device to actually trigger the requests to the server.
Libraries like Retrofit can make your life easier when it comes to making http requests - always avoid the main UI thread when doing this.
Another library that you could use to decouple your application using Events is EventBus. Assuming you are running a background service to check for updates, you can use EventBus to update your User Interfaces when something new is retrieved from the server through a GET request.
I hope this gives you an idea on how to proceed with the solution. Good luck!
I already know that using Services/Intent services we download multiple files in background. But this problem have one more complexity to solve.
I have to download multiple videos/images in different activities in parallel like whats app. I have seen in whats app that we can start download and then we can moves on different screens or press home button etc. But when we move back on that screen again the downloading is still continue with and showing the updated progress.
Like above there is 4 activities and user started downloading of ABC.mp4 on activity and A and then moves on to Activity B. Then moves on to C and started downloading of video/image. If user moves back on to the A and I want to show the progress of that ABC.mp4 file that how much downloaded and same case for the other activities.
Please let me know to you Services or any other way to do, so I can update the UI as well with the updated value of the downloading file. Any help is appreciated.
Well here's my piece of advice:
I did the same thing but with Pdf files a while a ago. First you need to choose a good Http client library to perform the downloads and forget about all the issues related to the downloads that you'll have if you perform this operations by yourself. I recommend you use the Ion librabry has a lot of useful features like cancel the downloads, attach callbacks to have an eye in the download progress, known if the download succeded, failed, etc.
Second, you obviously need a Service running in background, always, you can do this by making your own service, and It's very important that the Service process name in the android manifest is like android:name="com.company.app.services.MyService" and not like android:name=":MyRemoteService" doing so you'll make sure that the service will be running in background all the time (keep in mind that the OS can and will kill the service if It's neccesary, but the service will be restarted when the resources will made available again).
Third, to keep all the views, custom views, activities, fragments, etc. that display those files updated, you need trigger BroadcastReceivers from your Service. Keep in mind that doing so you can't use the LocalBroadcastReceiver, because your Service has its own process indipendent from your application.
Keep in mind that:
1) Theres no need to explicitly use an Activity, you can register your broadcasts anywhere where you see It fit. A RecyclerAdapter (most likely), a Fragment, or an Activity.
2) The communication App/Service is done through Intents so all data that you send to and from the Service must be Serializable.
3) You can use several different types of broadcast each one for differents situations (error, fail, success, progress, etc.) or you can use only one an send a enum that describe this kind of status through the Bundle of the Intent when you fire the broadcasts from your service
Hope this helps you, If you have any doubt, let me know.
I would like to have all my Activities (7 to 10 different screens) submit data to a "controller" (sorry if I'm miss using the term).
Inside said controller data would either be uploaded or saved to data for uploading when no internet.
The controller would do checks and processing such as:
Checking for valid session.
Attach other needed credentials before
upload etc.
Session/User data would be stored in a Shared Preferences file the controller has reference to.
My goal is to have Activities do nothing more than collect the data and call the appropriate method (with a data object) asynchronously. The controller would know how to process the data for uploading or saving in the database.
Would placing these methods in an extension of Application be a bad idea?
It was mentioned that depending on application size this is feasable, but there could be better solutions.
Depending on the size of your project, that would be a suitable idea. However, there are some other ways you should know before choosing the method you're actually implementing:
Using a ContentProvider for your data, an AccountAuthenticator and then sync to the server using an SyncAdapter. Advantages are a good abstraction, independence from activities and many built-in features (for example: Android executes your code without a big battery life impact). However, implementing all the stuff is quite much work at first. If you don't want to use the ContentProvider, the same technique works with a stub implementation as well, the same goes for the AccountAuthenticator.
Using a Service, probably IntentService, for your uploading needs. Advantage is that the Service has an independent lifecicle and thus is not directly related to your Activity; a Service can get restarted if it has been killed by the system. Still more work than just using some static methods.
Using a static method as you're proposing it (in your case, the Application object; not completely static, but compareable). Quite easy to implement, probably the best way if there are similar tasks in multiple activities; your AsyncTasks can send their result directly to the activitiy that started it. However not suitable for long-running tasks.
Implementing within the Activity; If code is only used once; listed for completeness only, not for your case. Basically the same as using a static method.
These are the ones that popped into my mind, there might be some others, too. Feel free to add/suggest additonal ones.