为什么在AndroidStudio中使用Pending Intent调用AlarmManager会有延迟?

时间:2017-07-13 13:42:53

标签: android android-intent timer android-pendingintent countdowntimer

我真的在任何地方搜索,但却找不到解决这个问题的方法!

所以我正在构建一个倒计时器应用程序。但我面临的问题是,每次计算到00:00.0时,它会等待大约5秒才会发出警报声。如果我碰巧在那段时间点击任何东西它会崩溃应用程序,但是如果我等到它发出警报并重复该过程它将再次等待〜5秒但是这次如果我按下Reset(在那些5秒内或之后)例如,它工作得很好!这是错误:

07-13 14:51:08.838 8808-8808/tech.dronerace.productivitytimer D/AndroidRuntime: Shutting down VM
07-13 14:51:08.838 8808-8808/tech.dronerace.productivitytimer E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                Process: tech.dronerace.productivitytimer, PID: 8808
                                                                                java.lang.RuntimeException: Unable to start service tech.dronerace.productivitytimer.Ringtone@11d1fec with Intent { cmp=tech.dronerace.productivitytimer/.Ringtone (has extras) }: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaPlayer.stop()' on a null object reference
                                                                                    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3027)
                                                                                    at android.app.ActivityThread.-wrap17(ActivityThread.java)
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1442)
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                    at android.os.Looper.loop(Looper.java:148)
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                    at java.lang.reflect.Method.invoke(Native Method)
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                                                 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.media.MediaPlayer.stop()' on a null object reference
                                                                                    at tech.dronerace.productivitytimer.Ringtone.onStartCommand(Ringtone.java:52)
                                                                                    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3010)
                                                                                    at android.app.ActivityThread.-wrap17(ActivityThread.java) 
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1442) 
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                    at android.os.Looper.loop(Looper.java:148) 
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                                                    at java.lang.reflect.Method.invoke(Native Method) 
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
07-13 14:56:09.149 8808-8808/tech.dronerace.productivitytimer I/Process: Sending signal. PID: 8808 SIG: 9

这是我的方法代码:

public void countDone() {
    ((Button) findViewById(R.id.b_start)).setVisibility(View.GONE);
    ((Button) findViewById(R.id.b_reset)).setVisibility(View.VISIBLE);
    ((Button) findViewById(R.id.b_stop)).setVisibility(View.GONE);
    ((TextView) findViewById(R.id.timer_id)).setText("00:00");
    ((TextView) findViewById(R.id.timerMs_id)).setText(".0");

    //----------------Alarm && Vibration && Progress----------------\\

    final Intent i = new Intent(SecondStep.this, Alarm.class);
    i.putExtra("extra", "soundOn");
    PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
    } else {
        am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
    }


    Button b = (Button) findViewById(R.id.b_reset);
    b.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {

            updateTimer(startTimeInitialG);
            i.putExtra("extra", "soundOff");
            PendingIntent.getBroadcast(getApplicationContext(), 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
            sendBroadcast(i);

            clickReset(v);

            ((Button) findViewById(R.id.b_start)).setVisibility(View.VISIBLE);
            ((Button) findViewById(R.id.b_reset)).setVisibility(View.GONE);
        }
    });
}

现在我选择了Pending Intent,因为我可以通过按下重置按钮来确定音乐已关闭的天气,或者它仍在播放。所以明知它是一个Pending意图我立即启动它以及确切报警(参见上面的代码)以及Update的标志。但似乎没有任何帮助。然后我也从我的自定义构建计时器切换到CountDownTimer类,认为可能存在用于Timer的AlarmManager中的继承错误,但同样的问题再次出现。

为什么要延迟拨打我的闹钟?我究竟做错了什么? :P

PS这是我的铃声类(由于错误)。

public class Ringtone extends Service {

MediaPlayer alarmPlayer;
boolean isRunning;

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    //get info on weather the reset was pressed and convert it to int so you can see weather you play or stop the music
    String state = intent.getExtras().getString("extra");
    assert state != null; //prevents app from crashing
    switch (state) {
        case "soundOn":
            startId = 1;
            break;
        case "soundOff":
            startId = 0;
            break;
        default:
            startId = 0;
            break;
    }



    Log.e("Is the state = 1 or 0?", state);
    System.out.println(startId);

    //we pressed reset or ('soundOff' ->extra) then cut it off
    if(startId == 0 ) {

        alarmPlayer.stop();
        alarmPlayer.reset();
        isRunning = false;
    }
    //we pressed nothing and is automatically ('soundOn' ->extra) so let it play
    else if(startId == 1) {

        alarmPlayer = MediaPlayer.create(this, R.raw.imperialmarch);
        alarmPlayer.start();
        isRunning = true;
    }




    return START_NOT_STICKY;
}

@Override
public void onDestroy() {
    Log.e("On Destroy called..", "yes");
    super.onDestroy();
}

}

1 个答案:

答案 0 :(得分:0)

为什么要创建PendingIntent并设置一个警报,该警报应该立即关闭以触发BroadcastReciever?您可以自己发送广播Intent,如下所示:

final Intent i = new Intent(SecondStep.this, Alarm.class);
i.putExtra("extra", "soundOn");
sendBroadcast(i);

这会立即触发,您不需要PendingIntent,也不需要警报管理员的参与。