我应该如何将BroadcastReceiver类代码放在Service类中,以便我可以在服务类中注册和注销它?

时间:2017-05-18 06:55:45

标签: java android android-service alarmmanager

我正在制作 Countdown Timer Android应用,其中我正在启动一个名为TimerService的服务,以便即使将应用发送到后台也能保持计时器正常运行。我想在启动计时器时在服务中设置计时器持续时间。当触发警报时,我想通过通知通知用户。我正在使用处理程序运行计时器。 目前我已经尝试在我将counDownDuration传递给setAlarm(long)的服务中设置警报。当触发警报时,接收器类会显示一个toast。但问题是,警报在随机时间时触发。(主要在3-5秒内)

这是我的代码:

TimerService.java

private long countDownDuration = 25000;//25 sec timer   
public void startTimer(){
    mIsTimerRunning = true;
    startTime = SystemClock.elapsedRealtime();
    setAlarm(countdownTimer);
    Log.i(TAG,"Timer Started");
}
private void setAlarm(long countDownDuration){
    mAlarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this, TimerExpiredReceiver.class);
    PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        mAlarmManager.setExact(ELAPSED_REALTIME_WAKEUP, countDownDuration, sender);
    } else {
        mAlarmManager.set(ELAPSED_REALTIME_WAKEUP, countDownDuration, sender);
    }
    Log.i(TAG,"Alarm Set of " + countDownDuration/1000 );
}

private void cancelAlarm(){
    Intent intent = new Intent(this, TimerExpiredReceiver.class);
    PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    mAlarmManager.cancel(sender);
    Log.i(TAG,"Alarm Cancelled");
}

TimerExpiredReceiver.java

public class TimerExpiredReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
   // context.mIsTImerRunning = false;
    Toast.makeText(context,"Time's Up!!",Toast.LENGTH_LONG).show();
}}

更新1: 找出随机触发的原因。在TimerService的startTimer()和setAlarm(long)中进行了更改。 这是更新的TimerSerive代码:

public class TimerService extends Service {

protected static final String TAG = "TimerService";
private long startTime, endTime;
private boolean mIsTimerRunning;
private final IBinder mBinder = new TimerBinder();
private static int count = 0;
private long countDownDuration = 25000;//25 sec timer
private long wakeUpTime;
private AlarmManager mAlarmManager;
private BroadcastReceiver mAlarmReceiver;
public TimerService() {
    count++;
    Log.i(TAG,"TimerService Object No. " + count);
}

@Override
public void onCreate() {
    Log.i(TAG, "Service Created");
    startTime = 0;
    endTime = 0;
    mIsTimerRunning = false;
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.i(TAG,"Service Started");
    return Service.START_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
    Log.i(TAG,"Service Bound");
    return mBinder;
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.i(TAG,"Service Destroyed");
}

public void startTimer(){
    mIsTimerRunning = true;
    startTime = SystemClock.elapsedRealtime();
    wakeUpTime = startTime + countDownDuration;
    setAlarm(wakeUpTime);
    Log.i(TAG,"Timer Started");
}

public void stopTimer(){
    mIsTimerRunning = false;
    endTime = SystemClock.elapsedRealtime() - startTime;
    cancelAlarm();
    Log.i(TAG,"Timer Stopped : endtime = " + endTime);
}

public int getElapsedTime(){
    return (int)TimeUnit.MILLISECONDS.toSeconds(SystemClock.elapsedRealtime() - startTime);
}

public boolean isTimerRunning() {
    return mIsTimerRunning;
}

private void setAlarm(long wakeUpTime){
    mAlarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this, TimerExpiredReceiver.class);
    PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        mAlarmManager.setExact(ELAPSED_REALTIME_WAKEUP, wakeUpTime, sender);
    } else {
        mAlarmManager.set(ELAPSED_REALTIME_WAKEUP, wakeUpTime, sender);
    }
    Log.i(TAG,"Alarm Set of " + wakeUpTime/1000 );
}

private void cancelAlarm(){
    Intent intent = new Intent(this, TimerExpiredReceiver.class);
    PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    mAlarmManager.cancel(sender);
    Log.i(TAG,"Alarm Cancelled");
}

public class TimerBinder extends Binder {
    TimerService getService() {
        return TimerService.this;
    }
}}

问题: 现在正在寻找一种方法将 TimerExpiredReceiver 代码置于 Timerservice中,以便它可以注册取消注册服务。除了接收器可以访问 TimerService类的成员,并且可以显示通知而不是 toast 。 任何帮助,将不胜感激。 谢谢!

1 个答案:

答案 0 :(得分:0)

在你的计数器到期后启动闹钟服务,并将时间设置为0,以便它开始响铃

Intent intent = new Intent(DashboardScreen.this, ServiceClass.class);
PendingIntent pintent = PendingIntent.getService(DashboardScreen.this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 0*1000, pintent);

希望这可以帮到你!