Services, AsyncTasks and the CalledFromWrongThreadException - android

I have a very strange issue in an application I'm writing. It may be as simple that I am misunderstanding something about Services, AsyncTasks and when I have access to the UI thread again.
The application consists of a main activity through which you navigate to multiple other activities. The app has two Services, one that sits in the background and periodically polls while the application is in foreground, and another that runs "AACPlayer" to stream a live radio stream.
One of the activities, the one that has the UI controls for the radio, starts the service for the radio. To do this an AsyncTask is fired to grab and parse the PLS file, and finally start the Service with the proper URL of the stream. The service is started that also initiates the AACPlayer. Once the stream has started playing, a broadcast is issued that says the stream has started playing. The broadcast receiver in the activity that holds the radio controls handles the intent and updates the UI.
This works great except for one race condition where through a seemingly random combination of leaving the app or backing out of the radio screen, before the Service has broadcasted its intent to update the UI, all other activities now seem to run outside of the UI thread. Every other activity fired up during this condition receives an exception that it's in an illegal state and can not modify do anything UI related as we're not running on the UI thread. The usual culprit exception message is: W/System.err( 3818): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Has anyone else encountered that suddenly the entire application no longer is running on its usual UI Thread, and all other activities report this exception? I don't think I have any code that's doing anything illegal that would trigger this error. No UI related things inside AsyncTasks. The callback that's triggered by the broadcast receiver (receiving from the radio Service) does touch UI, but I can't think of a different way to do this?
The problem is not fixed even when the application force quits itself, but gets remedied when the application is either force quit or has its data cleared from the Android Settings.
EDIT - As requested here's some code that outlines the service being started and the activity that starts the service / controls the UI: https://gist.github.com/1080797
Any thoughts would be appreciated. Thanks.

Try moving the initialization of your PlayerServiceUpdateReceiver to onCreate(). I don't think you need to reinitialize it on every onResume(), you just need to re-register it. Do you know what I mean?
I think what is happening is that you're getting callbacks to receivers that you've overwritten with new instances.
Or I might be completely wrong and it's the correct way to do it. Correct me if I'm wrong.

Related

Where is the best place to start a long running, application-wide, background task

I have a long running background task that I would like to start when the app launches and shutdown when the application shuts down. I'm already quite aware of the activity life cycle and what gets called when an activity gets created and destroyed.
I'm coming from an iOS background, and over there we have some calls that are made during application startup and shutdown. Is there something similar in the android world? I've searched a lot and all I'm finding are answers relating to an activity, not the entire application.
(Android is relatively new to me, so I may just not know the correct terminology to search for.)
EDIT:
I'll try an be a bit more specific. I have a background task that needs to be continuously running while the user is using the application. It will be streaming data from a server continuously while the application is active. It does not need to run when the application is in the background. It doesn't seem to make sense to me to tie the startup / shutdown of this background process to any one single activity since it may not be the same one activity that starts up when the application becomes active.
I am (possibly mistakenly) assuming that the OS takes care of starting / stopping background threads when the application resumes and pauses. If that is, in fact, the case, then all I really need to do is spin up the background task when the application first launches, i.e. when it is loaded into memory and becomes active for the first time that session.
It doesn't seem to make sense to me to tie the startup / shutdown of this background task to any one single activity since it may not be the same one activity that starts up when the application becomes active.
That's reasonable. It is somewhat difficult to implement, though.
I am (possibly mistakenly) assuming that the OS takes care of starting / stopping background threads when the application resumes and pauses.
You have it exactly backwards. Android pays not one whit of attention to any threads that you fork yourself, directly or via thin wrappers like AsyncTask.
In addition to that point of confusion, you appear to be equating "user switching to another app" with "app shutdown". Those may be the same thing in single-tasking operating systems. They are not the same thing in Windows, OS X, Linux, Android, etc.
So, what you seem to be seeking is having a background thread running doing this streaming work while your UI is in the foreground, and then stop when your UI is in the background. The problem is that there really isn't a straightforward way of accomplishing that in Android.
One close approximation would be to create and register a custom Application class, where you override onTrimMemory(), and stop your background work when you get to TRIM_MEMORY_UI_HIDDEN, TRIM_MEMORY_BACKGROUND, TRIM_MEMORY_MODERATE, or TRIM_MEMORY_COMPLETE -- whichever of those that you encounter first. If, when one of those arrives, you determine that your streaming thread is still outstanding, shut it down.
In terms of startup, you could use onCreate() on that same Application singleton. The problem is that this will be called on any process creation, which may include scenarios in which you do not have UI (e.g., you are responding to some system broadcast, like ACTION_BOOT_COMPLETED), or possibly your process is going to parts of your UI that do not depend on the streaming. If you have none of those scenarios, then onCreate() in Application would be fine. Otherwise, kick off the streaming in onCreate() of whatever activities need it.
While normally we manage long-running threads with a Service, that is for cases where we explicitly want the thread to continue after our UI is in the background. Since you do not want that, you could skip the service.
It depends on what you want to do exactly. When you're just interested in the app starting for the first time you could #Override onCreate().
Or maybe you want to use onResume() as this will get called whenever a user brings the app to the foreground.
But this really depends on what exactly your background task is doing and what you want to do with it, to get an exact answer you need to provide more details.
Here is an overview for the actiity life cycle that should help you:
You can extend the default Application class and implement it's onCreate() method to detect when the app is launched. There is no corresponding method for when the app gets closed though.
Do not forget to specify it in the Manifest file.
In Android the application isn't shut down unless the system runs low on memory. You won't get a warning about that, it will just call your Service's onDestroy lifecycle method. If you want to do it when the Activity is visible on screen, use onStart and onStop. If you want to do it when the Activity is resident in memory, use onCreate and onDestroy.

Android threads and timer slow down running when lockscreen

First sorry for my english.
I have a problem, and i can't find a solution, it sounds like:
i'm developping an app that's getting my location from gps and send it to a tcp server on pc , and store the data into a listview (for example). I have set a timer that send the location every 2 seconds. Everything works fine even if i connect two clients to server, until the phones gets locked .. then my server receive ugly string ..it seems like the sent-strings it straddles (the string contains parts of data from bought clients, parts are concatenated) .. but when i unlock the phones the server receive normal strings again..
I want to know how to make my app run in the same parameters when lock screen occurs .. Any ideas?
If you are doing this inside an activity or a fragment you are probably having an issue with the lifecycle of your app. If you want to understand the lifecycle, read this documentation article: http://developer.android.com/training/basics/activity-lifecycle/index.html
Doing nothing on your onPause method won't prevent your activity from sleeping, Android can kill your activity anytime.
The proper way to do this would be inside a Service, a service is a special component on Android that is executed independently of what the user is doing or not doing, and in this case, you could create a service that holds a wake lock in order to prevent it from sleeping for the couple of seconds you need to send your data.
An easier solution would be to use something like this Location polling library and suit it to your needs.
When the screen locks your activity is either paused on stopped and it is important you handle these methods so that any interuptions are handled elegantly and without error. Or so the app will continue to run in the background.
If you read up about the activity lifecycle.
During normal app use, the foreground activity is sometimes obstructed by other visual components that cause the activity to pause. For example, when a semi-transparent activity opens (such as one in the style of a dialog), the previous activity pauses. As long as the activity is still partially visible but currently not the activity in focus, it remains paused.
However, once the activity is fully-obstructed and not visible, it stops (which is discussed in the next lesson).
Activity Lifecycle from android.com

Android: background computation options

I am new to Android application development. My first project is to create a tuner, which requires to record audio and analyse it in real time.
I have read a lot on background operations in Android, but I am having trouble deciding what to use:
Asynctask : Android documentation says it should be kept for short computations, but I need to analyse data for more than a few seconds.
Intentservice : Better suited for long computations, but it can't be stopped whenever I want with a button.
Worker thread : The limitations seem to be similar to that of Asynctask.
On the following link is an example I found that is similar to what I want to do. Can a worker thread still be a good choice for long computations ? Is it thread safe to use a while loop with a flag to stop the computation ?
http://developer.samsung.com/android/technical-docs/Displaying-Sound-Volume-in-Real-Time-While-Recording
Edit: I have successfully created a bound service. Inside this service, a new thread is created to update a value in a loop, which is then broadcast. But when I unbind from the service, the thread continues to run. The value will still be updated even if I close the app and restart it.
So I am back to my initial problem. How is such a thread stopped ?
Edit: Problem solved with a simple flag activated in onUnbind() that stops the loop inside the thread.
You actually want a Service, but not an IntentService. You want a Service that will run in the background and which can be controlled through Activity (and will keep working after Activity is closed). This is a common architecture for such tasks. Here is an example of open source music player for Android:
https://github.com/kreed/vanilla/blob/master/src/org/kreed/vanilla/PlaybackService.java

service doesn't keep constant control of main thread on UI

I have a service in my Android application that has a UI its running. The problem I am running into, it that on various devices, it doesn't seem to maintain control of the main thread. For instance, it does not ALWAYS respond to the back button being pressed. Is there a way to ensure that the service always has control of the UI?
Thanks.
Solved it! For anyone that cares, I need to called the startForeground method for the Service.

Force close on second start of application

I am developing an Android application, and when I start my application 2nd time I am getting force close error. Following is my logcat:
06-07 16:08:12.763: ERROR/AndroidRuntime(3293): Uncaught handler: thread exiting due to uncaught exception06-07
16:08:12.773: ERROR/AndroidRuntime(3293): java.lang.NullPointerException06-07
16:08:12.773: ERROR/AndroidRuntime(3293): at com.androidpeople.tab.MobiintheMorningActivity$t2.run(MobiintheMorningActivity.java:209)06-07
16:08:12.773: ERROR/AndroidRuntime(3293): at java.lang.Thread.run(Thread.java:1060)
Your logcat capture is telling you that in your source file MobiintheMorningActivity.java, at line 209, you're using an object which is null. Seems pretty straight forward.
To prevent the application from crashing place try{//insert code} catch(Exception e){//todo when something fails}
On the NullPointer, try debugging your program and locating the null
Huh, I feel that I should give some more useful comments than those stupid answers from Captain Obvious fellows. Usually such problems happen because developer doesn't fully understand Android Application life cycle. When you start application second time, actually you re-starting an Activity, not whole Application, so for example static data may remain from previous activity launch, even you received onDestroy() event for that activity. If you created any threads, they may remain alive (if you don't take special actions to stop them gracefully, which is not often a trivial thing - for example in my case a thread was reading data from InputStream.read(), a blocked call ending somewhere in native code, and it was not possible to interrupt it, either via Thread.interrupt() or via InputStream.close() called in other thread. But it is another story).
So, from design point of view, if you're using threads, you must keep in mind that you may be attempting to start a new thread while the old one hasn't finished yet.
Whole application will be fully destroyed when OS decides so, when it will need to recycle memory. If your app is running some threads in background, the app may be considered alive, even you do not have open activities at the moment, and the app may avoid recycling, causing some sort of memory leak. This is considered as a bad coding style.
In your case the thread seems to reuse some old data, which you probably expected to be re-initialized by Activity re-start. Or you may have another thread concurrently running from previous launch and sharing data with Activity being started second time, and it reads/writes data while you're initializing them in the second start of the Activity, for the second start of the thread.
So you need to make sure that you do not start another thread before the first one quits. You may consider using a Local Service for such purposes, but you would need to launch threads for background activities (to not perform them in main event thread of the application, which is common for services and activities in the same Application instance), or in AsyncTask. A Service simplifies things a bit because it is not interrupted by Activities start/end, so you can somehow handle an async process (in your thread) between activities restarts. So activities should put requests to service to perform long jobs, and query its state from service (or receive notifications, for example via listeners, which quite OK for local services). So, starting an activity, you should check what the server is doing - probably it already performs a job from previous activity start. Your activity may request to stop the job (if you already didn't do so when previous activity finished), and wait for job cancelation, which generally may be not a quick thing, and should be made asynchronously). Of course you may implement the same approach without a service, just in that thread.

Categories

Resources