Android: got CalledFromWrongThreadException in onPostExecute() - How could it be? - android

I have an app in production for a few weeks, using ACRA, and I had zero errors until one strange error reported today.
I've got:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
coming from this method in the stack trace (retraced):
at my.app.CountdownFragment$1.void onPostExecute(java.lang.Object)(SourceFile:1)
And this is the relevant source snippet:
private void addInstructionsIfNeeded() {
if (S.sDisplayAssist) {
new AsyncTask<String, Void, String>() {
#Override
protected String doInBackground(String... params) {
return null;
}
/*
* runs on the ui thread
*/
protected void onPostExecute(String result) {
Activity a = getActivity();
if (S.sHelpEnabled && a != null) {
in = new InstructionsView(a.getApplicationContext());
RelativeLayout mv = (RelativeLayout) a
.findViewById(R.id.main_place);
mv.addView(in.prepareView());
}
};
}.execute("");
}
}
Where addInstructionsIfNeeded() is called from a handler dispatched message (the UI thead).
onPostExecute() runs on the UI thread, so why I've got "wrong thread"?
This code ran already on more than 150 devices, and more than 100000 times (according to Flurry), and never had this error.
The originating device is Samsung SGH-I997 running SDK 4.0.4
My question is: How could it be?
EDIT:
This all happens in a fragment

i was suffering from the same problem, this is another android framework bug...
what is happening:
in certain circumstances an application can have more than one "looper" and therefore more than one "UI thread"
--side note-- i am using the term "UI thread" in the loosest of senses in this answer, since when people say "UI thread" they usually mean main or entry thread, Android like many of other OS before it, allow for for multiple message pumps (called a Looper in Android, see: http://en.wikipedia.org/wiki/Event_loop) for different UI trees, as such android for all intents and purposes is capable of running more than one "UI thread" in certain circumstances and using that term leads to rampant ambiguities... --end side note--
this means:
since an application can have more than one "UI thread" and an AsyncTask always "Runs on the UI thread" [ref], someone decided [poorly] that instead of the AsyncTask always running on its creation thread (which in 99.999999% of cases would be the correct "UI thread") they decided to use hocus pocus (or a poorly crafted shortcut, you decide) to execute on the "main looper"..
example:
Log.i("AsyncTask / Handler created ON: " + Thread.currentThread().getId());
Log.i("Main Looper: " + Looper.getMainLooper().getThread().getId() + " myLooper: "+ Looper.myLooper().getThread().getId());
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
Log.i("doInBackground ran ON: " + Thread.currentThread().getId());
// I'm in the background, all is normal
handler.post(new Runnable() {
#Override
public void run() {
Log.i("Handler posted runnable ON: " + Thread.currentThread().getId());
// this is the correct thread, that onPostExecute should be on
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
Log.i("onPostExecute ran ON: " + Thread.currentThread().getId());
// this CAN be the wrong thread in certain situations
}
}.execute();
if called from the bad situation described above the output will look something like this:
AsyncTask / Handler created ON: 16
Main Looper: 1 myLooper: 16
doInBackground ran ON: 12
onPostExecute ran ON: 1
Handler posted runnable ON: 16
that's a huge FAIL for AsyncTask
as shown this can be mitigated using a Handler.post(Runnable) in my specific case the duality of my "UI thread" situation was caused by the fact that I was creating a dialog in response to a JavaScript interface method called from a WebView, basically: the WebView had its own "UI thread" and that was the one that i was currently running on..
from what i can tell (without really caring about or reading into it too much) it seems that the AsyncTask class' callback methods in general run off a single statically instantiated handler (see: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.3_r1/android/os/AsyncTask.java#AsyncTask.0sHandler), which means that it is always going to execute on the "main thread" or "entry thread" which they incorrectly refer to as the "UI thread" (which is presumed as any thread where UI interactions take place, eg. multiple threads in this case) this is both shoddy craftsmanship and shoddy documentation from the android team... weak sauce, the sauce is weak
hope this helps you -ck

Had the same issue. Solved in my case
Briefly explanation:
Running AsynckTask for the very first time on non UI thread with looper leads to loading AsyncTask.class and initialization sHandler to handler constructed on that non UI looper.
Now sHandler is connected to that non UI thread for ANY instance of AsyncTask subclasses and onPreExecute, onProgressUpdate and onPostExecute methods will be invoked on that non UI thread (unless AsyncTask.class will be unloaded)
Any attempt to deal with UI inside any of the above methods will lead to crash with android.view.ViewRootImpl$CalledFromWrongThreadException
To avoid such situation one should always run (at least for the very first time) AsyncTask on UI thread in order to let AsyncTask's sHandler-field be initialized with UI's looper
The story:
There were two production apps: A - main android app and B - some utilty app.
After integration app B ito app A we received a lot of crashes:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
for method running from AsynckTask.onPostExecute()
After some investigation it appeared that utility app B used AsyncTask within its HandlerThread
The traces was found in AsyncTask's source code:
private static final InternalHandler sHandler = new InternalHandler();
This is the handler which is used to send onPostExecute() to UI thread.
This handler is static and it will be initialized during class loading i.e. first new AsyncTask() appearance
It means that onPostExecute will always be posted to that thread where new AsyncTask() was called for the first time (unless AsyncTask.class will be unloaded and loaded again)
In my case the flow was something like this:
1 - starting app A
2 - initializing B form A
3 - B creates its own HandlerThread and launches AsyncTask <- now onPostExecute wil be posted to this HandlerThread no matter where from an instance of AsyncTask will be launched in future
4 - create AsyncTask in the app A for a long operation and update UI in its onPostExecute
5 - when executing onPostExecute() the CalledFromWrongThreadException is thrown
Then a friend of mine showed me related documentation from android.developers (Threading rules section):
The AsyncTask class must be loaded on the UI thread. This is done
automatically as of JELLY_BEAN. The task instance must be created on
the UI thread. execute(Params...) must be invoked on the UI thread.
Hope it can help to make clear the situation)

Maybe the reason is Flurry?
I had this exception when I used Flurry 3.2.1. But when I went back to Flurry 3.2.0 I didn't have this exception
Use Flurry 3.2.2 and above.

Placing the following line of code in the Application onCreate should solve the problem:
/**
* Fixing AsyncTask Issue not called on main thread
*/
try {
Class.forName("android.os.AsyncTask");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
It seems the issue is created when the AsyncTask class is first initiated on a different main Thread which is not our main Thread, I checked it by adding the code in the bottom, to my Application onCreate
new Thread(new Runnable() {
#Override
public void run() {
Log.i("tag","1.3onPostExecute ran ON: " + Thread.currentThread().getId());
Looper.prepare();
new AsyncTask<Void,Void,Void>(){
#Override
protected Void doInBackground(Void... params) {
Log.i("tag","2onPostExecute ran ON: " + Thread.currentThread().getId());
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
Log.i("tag","1.2onPostExecute ran ON: " + Thread.currentThread().getId());
super.onPostExecute(aVoid);
}
}.execute();
Looper.loop();
Looper.myLooper().quit();
}
}).start();
This code will init the AsynTask in a main Thread which is not the application main, and will cause the application to crash in any other AsyncTask which will do any UI on the post-execute. crashing with the CalledFromWrongThreadException
Hope it cleared things a little bit more.
Thanks all for the great help on this.

Where is
runOnUiThread(new Runnable() {
public void run() { /*code*/ } );
in your code
/*
* runs on the ui thread
*/
protected void onPostExecute(String result) {
Activity a = getActivity();
if (S.sHelpEnabled && a != null) {
in = new InstructionsView(a.getApplicationContext());
runOnUiThread(new Runnable() {
public void run() {
RelativeLayout mv = (RelativeLayout) a
.findViewById(R.id.main_place);
mv.addView(in.prepareView());
}
}
};
Try this code. I think this would fix the problem

I think the problem lies in the line Activity a = getActivity(); I think you should do that before going into the AsyncTask

Related

Android Activity UI Performance (AsyncTask while-loop)

How can I make this more efficient, at the moment it hangs the activity, giving the following information in logcat every time the while-loop completes I assume:
I/Choreographer: Skipped 55 frames! The application may be doing too much work on its
main thread.
Basically on a while-loop it reads a string variable, modifies and splits the string into parts which are then multiplied then divided, these final values are picked up by an interface which changes the custom UI element in the activity.
This seems too heavy on the main UI thread, I was under the impression that handler.post alleviates some of this by adding to the message queue however there are skipped frames.
I've tried to convert this code into an AsyncTask however I don't understand how this code can be converted to work in AsyncTask.
EDIT: AsyncTask custom class replacing old Thread while-loop.
(Old code for reference: http://pastebin.com/Dek6uQTE)
I'm still unsure how this fits in with AsyncTask, I have added the heavy code within the doInBackground() method however readBuf.replace and readBuf.split cannot be resolved. I thought to put the end changed in onProgressUpdate() as opposed to onPostExecute() as this would keep the UI elements updated automatically.
private class PostTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
readBuf = ((MyApplication) getApplication()).getReadBuf();
}
#Override
protected Void doInBackground(Void... readBuf) {
while (readBuf.length > 4) {
readBuf.replace("V", "");
String[] parts = readBuf.split(",");
String part1 = parts[0];
String part2 = parts[1];
speed1 = Float.parseFloat(part1);
speed2 = Float.parseFloat(part2);
finalspeed1 = (speed1 * 102) / div1;
finalspeed2 = (speed2 * 602) / div1;
publishProgress();
}
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
speedometer.onSpeedChanged(speedometer.getCurrentSpeed() - speedcur1);
speedometer.onSpeedChanged(speedometer.getCurrentSpeed() + finalspeed1);
speedometer1.onSpeedChanged(speedometer.getCurrentSpeed() - speedcur2);
speedometer1.onSpeedChanged(speedometer1.getCurrentSpeed() + finalspeed2);
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
You're starting a new thread which is actually just posting a new Runnable to the UI thread (handler is created on the UI thread), so it's not being done in the background. Here are a few tips to help with this:
If you are going to use a background thread to do the "work", then don't post a Runnable which is performing work to the handler, just post the result and update your UI accordingly.
Don't call findViewById() in a loop or any time after creation, if possible. Get a reference to the UI element and stash it off. This method is expensive as it does a search through your view hierarchy for the matching ID.
If you are going to use an AsyncTask just move the "work" part of your Runnable to the doInBackground() method and your UI updates into the onPostExecute() method.
Whether using a custom background Thread or AsyncTask, be sure to shutdown/cancel the work when your Activity leaves the run state, otherwise you will encounter problems as these components are not lifecycle aware.
It's not clear where readBuf is actually pulling data from, so this may also need some work. If this is real-time data coming from some other source, then you may need to have the custom Thread loop with a small yield. If using an AsyncTask, you'll have to create a new one each time as they are one-shot operations and not intended to be used as a long running background thread.
This article on AsyncTask has more details about how it works and pitfalls.

Is this code executing in a different thread to the main UI thread

Ive been struggling with the concept of threads on android. I thought the following code was running on a different thread to the main UI thread but I am not 100% sure so I thought i would come here for clarification as the android docs arent written in any language i understand. below is my code.
public void retrieveImages(final ImagePresenterInt imagepresenter) {
storedImages = new ArrayList<Image>();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
File imagedir = new File("/mnt/shared/images");
File [] myfiles = File.listRoots();
String canread = String.valueOf(imagedir.canRead());
String isfile = String.valueOf(imagedir.isFile());
String isdir = String.valueOf(imagedir.isDirectory());
Log.d("Can Read?","Canread from file :" + canread);
Log.d("is file?","Is a file ? :" + isfile);
Log.d("is dir?","Is a Dir file :" + isdir);
File [] rootfiles =myfiles[0].listFiles();
for (File item : rootfiles)
{
Log.d(item.getAbsolutePath(),item.getName());
}
if(Looper.myLooper() == Looper.getMainLooper())
{
Log.d("main thread ?", "YES");
}
}
}, 2000);
}
my understanding of the above code is that I create a handler. which is associated with the main thread or UI thread. It has a message queue and a looper associated with it. this code is passed to the message queue and run by the looper on a seperate thread to the main UI thread? I could be well wrong here. but mainly I want to know if this is running on the main thread. And how would i get it onto a different thread if not? I tried to verify that the code is running on a different thread using code i found in this question
How to check if current thread is not main thread
this apparently tells me Iam still running in the main thread. thanks for your help
The Handler you create in retrieveImages() is bound to the thread which this function is called from.
The doc on Handler says:
Default constructor associates this handler with the Looper for the current thread. If this thread does not have a looper, this handler won't be able to receive messages so an exception is thrown.
So if retrieveImages() is called from the UI thread, the Handler created in it is also bound to the UI thread.
UPDATE: If you want your code to be executed in different thread, the easiest way is to use AsyncTask.
The Handler is created in the calling thread, which is probably the UI-Thread in your case. If you like to start a new Thread, there are three possibilities I know of: the first is to simple start a new thread:
thread = new Thread() {
#Override
public void run() {
//Do your thing here
}
};
thread.start();
The thread will die, if your Activity gets killed.
The second is to define an IntentService:
public class SimpleIntentService extends IntentService {
public SimpleIntentService() {
super("SimpleIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
//Do your thing here
}
and start it via
Intent intent = new Intent(this, SimpleIntentService.class);
intent.putExtra("SomeString", "SomeValueYouNeed");
startService(intent);
The IntentService will run on, until onHandleIntent() is done and than close itself.
The third possibility is an AsyncTask:
private class TestTask extends AsyncTask<Datatype1, Datatype2, Datatype3>{
protected Long doInBackground(Datatype1... params) {
// Do your thing here
}
protected void onProgressUpdate(Datatype2... progress) {
//Do a Progress-Bar or something like that
}
protected void onPostExecute(Datatype3 result) {
//Do something, when your work is done
}
}
And in your Activity:
new TestTask().execute(params);
The docs state you shouldn't use Async-Tasks for very long calulations, but I'm not shure why. It might be easier to get your data back to the UI-Thread if you use an Asynctask instead of the Intentservice, but I for myself don't use them very often, so I'm maybe not the best person to ask here.
Edit: I forgot this:
IntentService is executed once for every ntent you pass, the Asynctask will be callable just once.
Furthermore the IntentService has to be declared in the Manifest.

When to use AsyncTask and When to use Thread in Android

When to use AsyncTask and When to use Thread as both do work in background and both can manipulate controls in UI Thread by some mechanism..
May this help you:
For long-running tasks, we use Java threads, and Android's native AsyncTask.
Basically Use AsyncTask for:
Simple network operations which do not require downloading a lot of data
Disk-bound tasks that might take more than a few milliseconds
And Use Java threads for:
Network operations which involve moderate to large amounts of data (either uploading or downloading)
High-CPU tasks which need to be run in the background
Any task where you want to control the CPU usage relative to the GUI thread
For more information refer
Mohit's answer Click Here
Edit:
Service is like an Activity but has no interface. Probably if you want to fetch the weather for example you won't create a blank activity for it, for this you will use a Service. Service is access to a Context object which has an independent life cycle. This allows for reuse of common code by many activities and, in the case of public or exposed services in many applications.
A Service runs on the main thread of the calling Component’s process by default (and hence can degrade responsiveness and cause ANRs), hence you should create a new Thread to perform long running operations.
A Thread is a Thread, probably you already know it from other part. You need to know that you cannot update UI from a Thread. You need to use a Handler for this and stopping a thread sometime become problematic also. A thread is a mechanism for doing work without blocking other work...
A service does not imply a thread and a thread does not imply a service. Both are different from eachother..
An AsyncTask is an intelligent Thread that is advised to be used. Intelligent as it can help with it's methods, and there are two methods that run on UI thread, which is good to update UI components.
AsyncTask is just a "helper" class provided with Android SDK to make it easier to skip to the UI thread after the background task is finished. It is built over the standard Java threading API. It does not give antyhing that cannot be done with Threads only. It addresses the common scenario of switching between the short task run background thread and UI thread.
Generally it is convenient to use AsyncTask when you must "skip back" to UI thread when the background task is done or when you have to give some feedback to UI thread during task execution. Otherwise it's just overhead.
You are not forced to use AsyncTask. If you as a developer prefer using Threads directly or Futures you may use it and skip to UI thread on your own manually after the background task is done.
EDIT:
Some other answers here suggest that using AsyncTask should be limited to short tasks. Allegedly because it uses a common pool. However it is no longer true since API Level 11 (so, for quite a long time). You can use executeOnExecutor instead of execute to execute AsyncTask's in dedicated thread pool. See http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor%28java.util.concurrent.Executor,%20Params...%29
Because examples are usually more communicative look at the example below.
Let's assume that we have a static function to do some heavy task and a TextView which we want to display progress and final status of the task declared as below:
static Object doHeavyTask(String string) throws Exception;
TextView progressInfo;
Execution of the task in background thread using async task would look like:
new AsyncTask<String, Integer, Exception>() {
#Override
protected Exception doInBackground(String... params) {
for (int i = 0; i < params.length; i++) {
try {
doHeavyTask(params[i]);
} catch (Exception e) {
return e;
}
publishProgress(i, params.length);
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressInfo.setText("Executed " + values[0] +
" of " + values[1] + " tasks.");
}
#Override
protected void onPostExecute(Exception result) {
if (result == null) {
progressInfo.setText("Heavy background job done successfully!");
}
else {
progressInfo.setText("Heavy background job failed!" +
"Exception message: " + result.getMessage());
}
}
}.execute("input1", "input2", "input3");
Exactly the same can be achieved with Thread:
final Handler handler = new Handler(Looper.getMainLooper());
final String[] params = { "input1", "input2", "input3" };
new Thread() {
#Override
public void run() {
for (int i = 0; i < params.length; i++) {
try {
doHeavyTask(params[i]);
} catch (final Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
progressInfo.setText("Heavy background job failed!" +
"Exception message: " + e.getMessage());
}
});
return;
}
final int currentIndex = i;
handler.post(new Runnable() {
#Override
public void run() {
progressInfo.setText("Executed " + currentIndex +
" of " + params.length + " tasks.");
}
});
}
handler.post(new Runnable() {
#Override
public void run() {
progressInfo.setText(
"Heavy background job done successfully!");
}
});
}
}.start();
As you see above using the AsyncTask is simply a bit more convenient. But there is no other advantage, just this convenience :).
If you prepared your own task encapsulating Thread (and a Handler to skip back to the UI thread) then maybe your class will be more efficient/comfortable for you to use.
That's all :).
You can run multiple threads concurrently. But asynctask is queued, meaning it is running one task at a time.

AsyncTask Not Updating on UI thread

I have an AsyncTask updating an ActionBarSherlock progress implementation. Somehow the onProgressUpdate is throwing a threading error though it claims to execute on the UI thread.
protected void onProgressUpdate(Integer... values)
{
setSupportProgress(values[0]);
}
The error is:
03-06 00:13:11.672: E/AndroidRuntime(4183): at com.anthonymandra.framework.GalleryActivity$ShareTask.onProgressUpdate(GalleryActivity.java:476)
Only the original thread that created a view hierarchy can touch its
views.
As far as I can tell I should be accessing the UI thread for this...
I have many working AsyncTasks in my app, but as requested here's the doInBackground (simplified):
for (MediaObject image : toShare)
{
BufferedInputStream imageData = image.getThumbStream();
File swapFile = getSwapFile(...);
write(swapFile, imageData);
++completed;
float progress = (float) completed / toShare.size();
int progressLocation = (int) Math.ceil(progressRange * progress);
onProgressUpdate(progressLocation);
}
Okay so the problem is you are calling onProgressUpdate when you should call publishProgress. The OP figured out this himself/herself so I just copy pasted it so he/she does not need to wait to accept the answer. Below is information how AsyncTasks works and it is good knowledge.
Are you creating the AsyncTask on the UI thread? If you are not that is the problem. onProgressUpdate will be run on the thread that created the AsyncTask.
Update: Let us have some code digging time (API 15 source code)!
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
This fellow will call it's static Handler sHandler. The documentation says:
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
Thanks to Bruno Mateus with his documentation look-up skills:
Look that, i found at documentation page: Threading rules - There are
a few threading rules that must be followed for this class to work
properly: - The AsyncTask class must be loaded on the UI thread. This
is done automatically as of JELLY_BEAN. - The task instance must be
created on the UI thread. execute(Params...) must be invoked on the UI
thread. - Do not call onPreExecute(), onPostExecute(Result),
doInBackground(Params...), onProgressUpdate(Progress...) manually. -
The task can be executed only once (an exception will be thrown if a
second execution is attempted.)
You can declare your AsyncTask as a innerclass of your activity like that:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
I was manually calling:
onProgressUpdate
You should call
publishProgress
Easy mistake, but great info. Simon and Bruno deserve the credit, post the answer if you like. Thanks for the fast and extensive response!

Android ANRs from code running in a Handler?

A game I wrote some time ago has a problem with ANRs, and debugging suggests they're down to HTTP requests taking a long time (and thus causing the ANR).
I'd thought that by assigning the HTTP code into a Runnable called from within a Handler, I'd could avoid the ANR - but it seems this isn't the case?
The stack dumps suggest the runnable/handler code is still running within the 'Main' thread and thus still causes ANRs??
The task it's doing is asynchronous (uploading highscores and achievements) and so can be started and left to it's own devices entirely - what is the best way to implement this so that ANRs aren't going to become a problem?
One topic suggested that the Handler should be created in the Application class and not within the Game's Activity - but I can't find any detail on the differences between those cases??
All ideas greatly apprec.
p.s. extending this to ask - I assume an ANR relating to HTTP comes down to the phone being out-of-service/network/WiFi, because I've set a SHORT timeout for these requests (they're non-essential and can be retried later!?)
A Handler will execute code / handle messages per default (any constructor without Looper e.g. new Handler()) in the current thread. That is in almost every case the main thread. If you want it to execute in a different thread you have to tell it which Looper thread it should use.
Android has a utility class called HandlerThread that creates a Thread with a Looper.
Short example:
public class MyActivity extends Activity {
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
HandlerThread handlerThread = new HandlerThread("background-handler");
handlerThread.start();
Looper looper = handlerThread.getLooper();
mHandler = new Handler(looper);
mHandler.post(new Runnable() {
public void run() {
// code executed in handlerThread
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
// stops the HandlerThread
mHandler.getLooper().quit();
}
}
In case your task needs only a some information and does not need to report back, I'd go with an IntentService. Those don't go mad if your Activity-lifecycle recreates the Activity.
You would create a small Service in it's own file
public class SaveService extends IntentService {
public SaveService() {
super("SaveService");
}
#Override
protected void onHandleIntent(Intent intent) {
if ("com.example.action.SAVE".equals(intent.getAction())) {
String player = intent.getStringExtra("com.example.player");
int score = intent.getIntExtra("com.example.score", -1);
magicHttpSave(player, score); // assuming there is an implementation here
}
}
}
Add it to the AndroidManifest.xml
<application ....
<service android:name=".SaveService" />
</application>
And in your code start it with
Intent intent = new Intent(this /* context */, SaveService.class);
intent.setAction("com.example.action.SAVE");
intent.putExtra("com.example.player", "John123");
intent.putExtra("com.example.score", 5123);
startService(intent);
IntentService#onHandleIntent() runs on a background thread already so you don't have to bother about that.
Your Handler runs on the main thread. That is what causes ANR.
Even if you create it in the Application, by default (no parameters given to Handler) will be created on the main thread. You have to create a Looper, with its own Thread. See here.
A Handler initialized with your own Looper, that is a viable option to solve ANR...
A more simple alternative solution can be, if you place your async network operation into an AsyncTask. A simple approach is to place the AsyncTask into your Activity. A somewhat more complex could be to create a Service (holder for non-ui related functionality), that does the communication, and cleans itself from memory, once the communication is over...
I'd use AsyncTask and place it into the Activity / fire it up from the Activity...
Finally, HERE you can find a nice tutorial on threads in android.

Categories

Resources