android alarm died during onReceive

2019-07-16 03:05发布

问题:

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...

回答1:

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.