Managing state in Android app - java

Ive run into a problem with Android not letting you pass objects around Activities with intent' putExtra. So, if my application needs to make any number of network requests, it would make sense to keep futures in an object and get results as they become needed and block background threads if necessary.
How can you pass an object from one Activity to another without it being static or serialization?

Related

What are the Advantages and disadvantages of AsyncTask in Android framework?

I am learning Android app development from Udacity.com by Google engineers and they said,
"It is not a good idea to use 'AsyncTask' as it is not attached to an activity life cycle. The virtual machine will hold on to the activity object as long as the Asynctask is running, even after Android has called onDestroy( ) method for the activity and expect it to be discarded.
If you rotate your phone, the behavior is to destroy the current activity and instantiate a new one. The naive AsyncTask implementation now has two threads trying to do the same update. So it is not the best pattern for a potentially very long running background operation , such as fetching from web services. If you leave the app, the asyncTask will run as long as as the process is kept alive , but will run at a lower priority, and your process will be the first thing to be killed if the device needs more resources. "
1) If using AsyncTask is disadvantageous why was it created? What would have been the design philosophy or the cause to create it in spite of having services(or something similar to achieve same kind of functionality)?
2) What are the situations where Asynctask should be used for betterment compared to Services/similar options available in Android?
3) What are the situations/places Asynctask should never be used?
Please do not downvote this question. I searched Stackoverflow and I couldn't find a similar question.
Advantages of AsyncTask
Provides generic solution for all network calls
Publish progress to UI while executing.
Run Asynchronously
Easy to maintain and read.
Problems in AysncTask
When you rotate your screen, Activity gets destroyed, so AsyncTask will not have a valid reference to publish data from onPostExecute(). In order to retain it, you need to usesetRetainState(true) if calling from fragment or onConfigChanges() if calling from activity method of an activity.
If activity gets finished, AsyncTask execution will not cancelled automatically, you need to cancel them else they will keep on running in the background.
If any exception occurs while performing network task, you need to handle them manually.
Whereas AsycTask, Services, IntentService, Threads all run on different threads and all serve different purpose.
please read more detail here.
So you need to decide when to use which component while performing non UI operations.

How can I ensure that my Android app doesn't access a file simultaneously?

I am building a fitness app which continually logs activity on the device. I need to log quite often, but I also don't want to unnecessarily drain the battery of my users which is why I am thinking about batching network calls together and transmitting them all at once as soon as the radio is active, the device is connected to a WiFi or it is charging.
I am using a filesystem based approach to implement that. I persist the data first to a File - eventually I might use Tape from Square to do that - but here is where I encounter the first issues.
I am continually writing new log data to the File, but I also need to periodically send all the logged data to my backend. When that happens I delete the contents of the File. The problem now is how can I prevent both of those operations from happening at the same time? Of course it will cause problems if I try to write log data to the File at the same time as some other process is reading from the File and trying to delete its contents.
I am thinking about using an IntentService essentially act as a queue for all those operations. And since - at least I have read as much - an IntentServices handles Intents sequentially in single worker Thread it shouldn't be possible for two of those operations to happen at the same time, right?
Currently I want to schedule a PeriodicTask with the GcmNetworkManager which would take care of sending the data to the server. Is there any better way to do all this?
1) You are overthinking this whole thing!
Your approach is way more complicated than it has to be! And for some reason none of the other answers point this out, but GcmNetworkManager already does everything you are trying to implement! You don't need to implement anything yourself.
2) Optimal way to implement what you are trying to do.
You don't seem to be aware that GcmNetworkManager already batches calls in the most battery efficient way with automatic retries etc and it also persists the tasks across device boots and can ensure their execution as soon as is battery efficient and required by your app.
Just whenever you have data to save schedule a OneOffTask like this:
final OneoffTask task = new OneoffTask.Builder()
// The Service which executes the task.
.setService(MyTaskService.class)
// A tag which identifies the task
.setTag(TASK_TAG)
// Sets a time frame for the execution of this task in seconds.
// This specifically means that the task can either be
// executed right now, or must have executed at the lastest in one hour.
.setExecutionWindow(0L, 3600L)
// Task is persisted on the disk, even across boots
.setPersisted(true)
// Unmetered connection required for task
.setRequiredNetwork(Task.NETWORK_STATE_UNMETERED)
// Attach data to the task in the form of a Bundle
.setExtras(dataBundle)
// If you set this to true and this task already exists
// (just depends on the tag set above) then the old task
// will be overwritten with this one.
.setUpdateCurrent(true)
// Sets if this task should only be executed when the device is charging
.setRequiresCharging(false)
.build();
mGcmNetworkManager.schedule(task);
This will do everything you want:
The Task will be persisted on the disk
The Task will be executed in a batched and battery efficient way, preferably over Wifi
You will have configurable automatic retries with a battery efficient backoff pattern
The Task will be executed within a time window you can specify.
I suggest for starters you read this to learn more about the GcmNetworkManager.
So to summarize:
All you really need to do is implement your network calls in a Service extending GcmTaskService and later whenever you need to perform such a network call you schedule a OneOffTask and everything else will be taken care of for you!
Of course you don't need to call each and every setter of the OneOffTask.Builder like I do above - I just did that to show you all the options you have. In most cases scheduling a task would just look like this:
mGcmNetworkManager.schedule(new OneoffTask.Builder()
.setService(MyTaskService.class)
.setTag(TASK_TAG)
.setExecutionWindow(0L, 300L)
.setPersisted(true)
.setExtras(bundle)
.build());
And if you put that in a helper method or even better create factory methods for all the different tasks you need to do than everything you were trying to do should just boil down to a few lines of code!
And by the way: Yes, an IntentService handles every Intent one after another sequentially in a single worker Thread. You can look at the relevant implementation here. It's actually very simple and quite straight forward.
All UI and Service methods are by default invoked on the same main thread. Unless you explicitly create threads or use AsyncTask there is no concurrency in an Android application per se.
This means that all intents, alarms, broad-casts are by default handled on the main thread.
Also note that doing I/O and/or network requests may be forbidden on the main thread (depending on Android version, see e.g. How to fix android.os.NetworkOnMainThreadException?).
Using AsyncTask or creating your own threads will bring you to concurrency problems but they are the same as with any multi-threaded programming, there is nothing special to Android there.
One more point to consider when doing concurrency is that background threads need to hold a WakeLock or the CPU may go to sleep.
Just some idea.
You may try to make use of serial executor for your file, therefore, only one thread can be execute at a time.
http://developer.android.com/reference/android/os/AsyncTask.html#SERIAL_EXECUTOR

File API is causing ANR's

A small part of my application checks if files exist on the user's device. The list of files is potentially quite long - apparently long enough to cause ANR's with a few users. A thousand files is by no means impossible.
The code is quite simple:
new File(fileUrl).exists()
I'm currently doing it on the main thread, as I need the operations to be blocking. I could do it using an AsyncTask class and then continue the rest of the work once it's done, but I'm wondering if that's a valid cause?
All the work is being done in a background Service, if that changes anything. I'm also potentially going to experience orientation changes, and that might be annoying with AsyncTask. Would a Handler be better?
So, to sum things up: Should I do use an AsyncTask for a potentially long-running operation in a background Service, where orientation changes may occur?
Firstly, a Service isn't affected by orientation change - it's only the currently running Activity class which is destroyed / recreated.
Secondly, an AsyncTask isn't of much advantage in a Service as it's designed to be able to interact with the UI. It would give the advantage of doing work on a separate thread but the rest of the methods would basically be redundant.
I'd recommend using an IntentService which manages its own worker thread to do work. See the IntentService documentation

How to maintain Server Socket through Activities?

In my application I decided to make a server and client through Sockets (just testing my idea for now).
So I made two AsyncTasks (for the server and client) an on my onCreate (depending on user action - as I said I'm just testing, for now just with buttons):
new createServer().execute();
or
new connectClient().execute();
Question is, everything works good, but the app where I want to implement my idea has many activities, so the app that is serving the data, when leave the activity where the createServer Async Task is, the client (obviously) loses the connection.
Is there a way to maintain the server running "all time", and allow the user (with the "server app") to navigate through the app without affecting the connected clients? Because even if everytime I leave an activity I create the Server, the clients will lose connection anyway.
Really appreciate any suggestion.
EDIT: For the purposes of my test application, I need the system to be working only in foreground, no background, so no need of service creation.
Your problem is with correctly managing the lifetime of your server. First you'll have to decide what you want that lifetime to be. Clearly you've figured out that you want it to be broader than just the activity level, but do you want it to run in the background or only when your app is in the foreground? If it is only when in the foreground, you can get away with not creating a service, but instead keeping a reference to a component from your application object. However, if you want to keep your server running even when your app is in the background you do need a Service.
Update:
Here's an example of what I meant by "keeping a reference to a component from your application object":
Create a custom Application class.
Add a field to hold a reference to your server AsyncTask
private AsyncTask mServerTask;
Add a method to it to start your server AsyncTask
public void startServer() {
mServerTask = new createServer();
mServerTask.execute();
}
Probably add another method to stop your server
To start your server from an activity you can now do something like:
CustomApplication app = (CustomApplication) getApplication();
app.startServer();
Of course you'll want to do more to properly manage the server like making sure you don't start it twice, etc. and you might decide to use threads instead of AsyncTasks but this should give you an idea of how you can have an object with a lifetime beyond that of an activity.

How to use Androids location package in a service separate from the User Interface thread?

I have a small Android app that I have been working on that logs GPS data to my SD card in a GPX file. I currently have a main Activity that starts a Service to do all the background work. The service is kept in the foreground in the notification bar to make it the least likely thing to be killed by the OS. Currently I am requesting location updates from the service at the maximum frequency to get the most accurate route. The problem I am having is my User Interface is acting slow/strange. Correct me if I am wrong, but what I have concluded is that I have too much going on in the main thread of the app. My next thought is to try and move the service performing the acquiring and logging of data to a separate thread. I am new to Java/Android so the whole topic of interacting with separate threads is hard for me to wrap my head around. Initially in research I came across IntentServices, which are supposed to make threading easier, but from what I read these don’t seem to mix well with the Android location package because they don’t run long enough. I feel like I am running in circles with internet searches on this topic. I desperately need some guidance on how to achieve the following features for my programs service:
Separate thread from Main Thread
Fetching and storing of data must be the least likely thing to be killed by the OS and run indefinitely once started (don’t worry about battery I will have the device plugged in to power while running the app)
Eventually I will need the ability to interact with the User Interface
Thanks for any help you can offer!
this is a common problem that i have accomplished a lot on
in the launcher or main() ( what Android is calling an Activity ) you do as little as possible ( which amounts to saving the the refs they give you and maybe setting a few other things as long as you are there ) and do ^not^ drop in to a long-running activity
A Service is exactly what you need but instead of trying to pump it into a "hold on to it" state what you do is implement checks for nulls and handle as needed -- trying to "fix" a machine to make it run the way you want here actually involves rescinding you hold on the main thread and letting it go as fast as consistent with the Applicaton's general constraints.
To do this you can simply write a Service - reading everything available - then extend that service and implement Runnable then you run the constructor on that code from the Activity Constructor and do new Thead(yourClass).start(); in the onCreate() checking for Thread.isRunning() before starting it again ...
Service will have an onCompletion() call in it somewhere - it will go through an interface
All this is done in Android in something like start activity for result then you just to the UI stuff in that call or sorta figure out a way for the GUI to get called somehow at some time then check to see if Service is done an so report in the gui

Categories

Resources