2

i have a timer app, which wakes up the device with system alarms (RTC_WAKEUP) and opens my app. after thousands of successful alarms, it just happend, that the set alarm was not completely successful. it died during onReceive() and did not start my app, nor it fired a system notification. here is the BroadcastReceiver's onReceive() method:

public void onReceive(Context context, Intent intent) {
    Log.i("timer", "timer's end broadcast received at: " + (System.currentTimeMillis() / 1000) );
    m_Context = context;

    Bundle extras = intent.getExtras();
    final int id = extras.getInt("timer_id");

    Intent activityIntent = new Intent(m_Context, TinyTimerActivity.class);
    activityIntent.putExtra("timer_id", id);
    activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    m_Context.startActivity(activityIntent);

    m_SharedPrefs = PreferenceManager.getDefaultSharedPreferences(m_Context);

    // start the alarm sound
    final AudioManager localAudioManager = (AudioManager)m_Context.getSystemService("audio");
    final int ringerMode = localAudioManager.getRingerMode();
    final boolean audibleInSilentMode = m_SharedPrefs.getBoolean("audible_in_silent_mode", true);
    final boolean silentAlarm = m_SharedPrefs.getBoolean("silent_alarm", false);

    // and now load the alarm sound and play it for the desired time
    showFinishedNotification(!silentAlarm && (ringerMode != AudioManager.RINGER_MODE_SILENT || audibleInSilentMode));

    // cancel the alarm after some time
    final int duration = Integer.parseInt(m_SharedPrefs.getString("alarm_length", "-1"));
    if (duration > 0 ) {
        (new Handler()).postDelayed(new Runnable() {
            @Override
            public void run() {
                ((NotificationManager)m_Context.getSystemService(Context.NOTIFICATION_SERVICE)).cancel(NOTIFICATION_TIMER_FINISED_ID);
            }
        }, duration * 1000);
    }
}

when the alarm was triggered, i was using gReader app. here is the logcat (my app is sk.martinflorek.TinyTimer):

I(  146) Start proc sk.martinflorek.TinyTimer for broadcast sk.martinflorek.TinyTimer/.timers.TimerReceiver: pid=18307 uid=10070 gids={3003}  (ActivityManager)
I(18307) Pub sk.martinflorek.TinyTimer.providers.TimersProvider: sk.martinflorek.TinyTimer.providers.TimersProvider  (ActivityThread)
I(18307) timer's end broadcast received at: 1333208420  (timer)
I(  146) Starting: Intent { flg=0x30000000 cmp=sk.martinflorek.TinyTimer/.TinyTimerActivity (has extras) } from pid 18307  (ActivityManager)
D(18198) couldn't save which view has focus because the focused view com.noinnion.android.greader.reader.ui.view.ItemWebView@406dd4f0 has no id.  (PhoneWindow)
I(  146) No longer want android.process.media (pid 17918): hidden #16  (ActivityManager)
I(  146) Sending signal. PID: 18307 SIG: 9  (Process)
I(  146) Kill sk.martinflorek.TinyTimer (pid 18307): provider com.android.providers.media.MediaProvider in dying process android.process.media  (ActivityManager)
I(  146) Process sk.martinflorek.TinyTimer (pid 18307) has died.  (ActivityManager)

why did the android.process.media killed my app and how to prevent this? it happend only once...

shelll
  • 3,234
  • 3
  • 33
  • 67
  • It's worth noting that this can happen if your app is holding an open Cursor object for a content provider. Since MediaProvider was involved in your app crash, it's possible that cursor.close() didn't get called somewhere. – acj Oct 03 '12 at 23:33
  • @acj the BroadcastReceiver does not open any cursors (the app itself opens some cursors on start) and to my knowledge app can have multiple opened cursors at the same time. could this still be an issue? – shelll Oct 05 '12 at 06:35
  • It's possible. In the scenario I'm thinking of, you use the app for a little while, thus opening some cursors, and then navigate away to other apps. Your app is stopped but remains in memory. At some point (perhaps when your BroadcastReceiver happens to be running), the MediaProvider happens to get killed. Since you still have the cursors open, your app is killed as well. Closing the cursors _should_ prevent this issue. – acj Oct 05 '12 at 12:33
  • @acj in the app, there is no cursor opened for the MediaProvider, so they should not interfere and crash the app, or? – shelll Oct 05 '12 at 14:23
  • Hard to say, then. Your interaction with MediaProvider might be indirect. If the app's activities don't release everything in onStop, it could be leaking a resource that binds it to MediaProvider or something else that, down the chain, interacts with MediaProvider. I wish that we had better debugging tools for this sort of problem. – acj Oct 05 '12 at 14:48
  • @acj only this receiver is making sound, it shows an audible notification. it happened just once, so it is not a big issue for me, I was just curious. – shelll Oct 05 '12 at 15:00
  • Never again, I hope. :) Thanks for commenting back. This issue has bitten me in the past, and I've seen some recent SO questions about it. Hopefully this discussion will be helpful for someone. – acj Oct 05 '12 at 15:15

1 Answers1

0

A BroadcastReceiver is not meant for long running operations. BroadcastReceivers are suppose to be very short lived. I've read from others that BroadcastReceivers should last for a max of 50 ms, and if it's any longer, you should start a Service.

So you should either just set the alarm to start a Service, or start a Service from within the BroadcastReceiver and move any time consuming code (such as Handler.postDelayed()) to the Service.

Reed
  • 14,703
  • 8
  • 66
  • 110
  • the postDelayed() part was not used in that situation. so the receiver code was fast enough, it should have just started the activity and show a notification, where none of that happened. – shelll Mar 31 '12 at 19:33
  • Okay. If all you did was `startActivity` and show a notification, then there's no explainable reason why it would die. Sometimes there are Android errors that cause the problem. If you're doing nothing else, and it's happening every time, then perhaps you have an error in your code. But if this only happened once, then you just have to shrug it off and hope it doesn't happen again. – Reed Mar 31 '12 at 21:11