Reputation: 20420
My app downloads and unzips some data from raw file at first launch. All long-running processes are performed in service in background thread so i believe there is no obvious reason for ANR (correct me).
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
ResultReceiver receiver = intent.getParcelableExtra(RECEIVER);
job = extractJob(intent);
InstallResultSender sender = new InstallResultSender(receiver);
// add one more receiver
synchronized (senders) {
senders.add(sender);
}
if (thread == null) {
thread = new InitThread(job);
thread.start();
}
// no need to restart service or redeliver intent
return Service.START_NOT_STICKY;
}
The progress and status messages are sent to activity using android ResultReceiver
:
private ResultReceiver receiver;
public void sendProgress(int percent) {
Bundle data = new Bundle();
data.putInt(InstallResultReceiver.DATA_PROGRESS, percent);
receiver.send(InstallResultReceiver.RESULT_PROGRESS, data);
}
The activity just shows ProgressDialog and updates percentage and status message.
The problem is that while downloading/installing ANR happens and then Android sends signal 6 (abort). How can i prevent/walk-around this?
ANR reason is amazon in-app purchase billing receiver, but it does not matter i believe.
Log:
04-04 13:01:51.016: DEBUG/ActivityInstallListener(1912): on started INSTALL ArmstrongNumber c (1)
04-04 13:01:53.695: DEBUG/ActivityInstallListener(1912): saved repository (9233 bytes)
04-04 13:01:53.695: DEBUG/ActivityInstallListener(1912): on started INSTALL HarmonicNumberSeries c (1)
04-04 13:01:53.885: ERROR/ActivityManager(275): ANR in name.mycompany.android.myapp
Reason: Broadcast of Intent { act=com.amazon.inapp.purchasing.NOTIFY flg=0x10000010 pkg=name.mycompany.android.myapp cmp=name.mycompany.android.myapp/com.amazon.inapp.purchasing.ResponseReceiver (has extras) }
Load: 6.71 / 6.75 / 3.23
CPU usage from 0ms to 5942ms later:
59% 1912/name.mycompany.android.myapp: 50% user + 8.4% kernel / faults: 809 minor
24% 275/system_server: 18% user + 6.3% kernel / faults: 1131 minor
4% 29/mmcqd: 0% user + 4% kernel
0.6% 505/com.android.phone: 0.4% user + 0.2% kernel / faults: 150 minor
1% 47/adbd: 0% user + 1% kernel
0% 519/com.amazon.tcomm: 0% user + 0% kernel / faults: 135 minor
0% 1715/com.amazon.client.metrics: 0% user + 0% kernel / faults: 236 minor
0% 12/pdflush: 0% user + 0% kernel
0.8% 40/mediaserver: 0.1% user + 0.6% kernel
0% 552/com.amazon.imp: 0% user + 0% kernel / faults: 123 minor
0.1% 909/com.android.systemui: 0% user + 0% kernel / faults: 104 minor
0% 459/com.lab126.softkeybar: 0% user + 0% kernel / faults: 110 minor
0% 539/com.android.providers.downloads: 0% user + 0% kernel / faults: 99 minor
0.3% 545/android.process.media: 0.1% user + 0.1% kernel / faults: 167 minor
0% 988/com.nuance.swype.input: 0% user + 0% kernel / faults: 97 minor
0.5% 13/kswapd0: 0% user + 0.5% kernel
0.1% 319/logcat: 0% user + 0.1% kernel / faults: 20 minor
0.3% 1343/com.amazon.ags.app: 0.3% user + 0% kernel / faults: 174 minor
0% 1//init: 0% user + 0% kernel / faults: 85 minor
0% 1944/com.amazon.mas.test: 0% user + 0% kernel / faults: 19 minor
100% TOTAL: 73% user + 25% kernel + 0.1% irq + 0.1% softirq
CPU usage from 5132ms to 5817ms later:
62% 1912/name.mycompany.android.myapp: 56% user + 6.4% kernel / faults: 12 minor
35% 1912/ndroid.myapp: 35% user + 0% kernel
33% 1957/Thread-208: 22% user + 11% kernel
1.6% 1919/Compiler: 1.6% user + 0% kernel
15% 275/system_server: 5.7% user + 10% kernel / faults: 1 minor
11% 293/ActivityManager: 4.3% user + 7.2% kernel
13% 29/mmcqd: 0% user + 13% kernel
0.7% 12/pdflush: 0% user + 0.7% kernel
1.4% 40/mediaserver: 0% user + 1.4% kernel
1.4% 40/mediaserver: 0% user + 1.4% kernel
0.4% 47/adbd: 0% user + 0.4% kernel
0.4% 47/adbd: 0% user + 0.4% kernel
100% TOTAL: 62% user + 35% kernel + 1.4% irq
04-04 13:01:53.925: INFO/ActivityManager(275): Tablet:Platform:package=name.mycompany.android.myapp;DV;1,event=app-anr;DV;1:NR
04-04 13:01:53.925: INFO/Process(275): Sending signal. PID: 1912 SIG: 6
Upvotes: 0
Views: 972
Reputation: 20420
Sorry for not publishing the full source code and the reason was in it:
i was handling the results from the service right in ResultReceiver.onReceiveResult()
. The problem was resolved by using Handler, so i just had to put processing in runnable queue. Also i reduced state saving invocations count after each intent is received (which reduced invocations count on ui thread) and saved it once in the end.
private Handler handler = new Handler();
/**
*
*/
private class ReceiveResultRunnable implements Runnable {
private int resultCode;
private Bundle resultData;
public ReceiveResultRunnable(int resultCode, Bundle resultData) {
this.resultCode = resultCode;
this.resultData = resultData;
}
public void run() {
switch (resultCode) {
case RESULT_STARTED:
listener.onStarted();
break;
case RESULT_MESSAGE:
String message = resultData.getString(DATA_MESSAGE);
listener.onMessage(message);
break;
case RESULT_PROGRESS:
int progress = resultData.getInt(DATA_PROGRESS);
listener.onProgress(progress);
break;
case RESULT_ERROR:
Throwable t = (Throwable) resultData.getSerializable(DATA_ERROR);
listener.onError(t);
break;
case RESULT_OK:
int version = resultData.getInt(DATA_REPOSITORY_VERSION);
listener.onFinished(version);
break;
// ...
}
}
}
@Override
protected void onReceiveResult(final int resultCode, final Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
handler.post(new ReceiveResultRunnable(resultCode, resultData));
}
Upvotes: 0
Reputation: 3075
onStartCommand is called in your application's main thread. Have a look at this. Instead, if you use an IntentService, you should override onHandleIntent (Intent intent), which actually gets called in the worker thread.
Upvotes: 0
Reputation: 3253
The documentation http://developer.android.com/guide/components/services.html states
Caution: A services runs in the same process as the application in which it is declared and in the main thread of that application, by default. So, if your service performs intensive or blocking operations while the user interacts with an activity from the same application, the service will slow down activity performance. To avoid impacting application performance, you should start a new thread inside the service.
Furthermore, you can check the state of threads in eclipse by opening the Debug view and seeing the status of your threads.
I'm a little confused as to why you have chosen to use a service over an AsyncTask
or IntentService
, which handles creating a non-ui thread for you.
Upvotes: 1