2014-10-01 6 views
1

Android의 알람 관리자에 문제가 있습니다. 그래서 내가하려고하는 일은 매일 12.01AM 정도의 DB 삽입을 실행하기 위해 반복되는 알람을 설정하는 것입니다.Android 알람 관리자 설정을 특정 타이밍에서 반복

Calendar calendar = Calendar.getInstance(); 
    calendar.setTimeInMillis(System.currentTimeMillis()); 
    calendar.set(Calendar.HOUR_OF_DAY, 0); 
    calendar.set(Calendar.MINUTE, 1); 
     notificationCount = notificationCount + 1; 
     AlarmManager mgr = (AlarmManager) context 
       .getSystemService(Context.ALARM_SERVICE); 
     Intent notificationIntent = new Intent(context, 
       ReminderAlarm.class); 

     notificationIntent.putExtra("NotifyCount", notificationCount); 
     PendingIntent pi = PendingIntent.getBroadcast(context, 
       notificationCount, notificationIntent, 
       PendingIntent.FLAG_UPDATE_CURRENT); 
     mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, 
       calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi); 

그래서 기본적으로 나는이 코드를 생각해 냈습니다. 그러나 알람 관리자는 설정 한 후 다시 실행합니다.

2011 년 1 월 10 일 5.48PM에 앱을 실행한다고 가정 해 보겠습니다. 나는 이것을 12.01M 주위에서만 설정 한 후 매일 onReceive 할 때 DB 삽입을 실행하기를 원했습니다. 하지만 어쨌든 알람 관리자는 2014 년 1 월 10 일 5.49PM에 실행합니다. 설정한지 1 분 후 작동이 멈췄습니다.

내가 잘못한 부분이 궁금합니다.

미리 감사드립니다.

이 클래스의 편집

반복 클래스 , 그것은 알람 매니저의 일상을 트리거하고 DB 삽입에 대한 알림 경보 클래스에 따라 변수를 전달합니다.

public void onReceive(Context context, Intent i) { 
    if (i.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { 
     Recurring.scheduleAlarms(context); 
    } 
} 

ReminderAlarm 클래스

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.recurring); 
    context = this; 
    buildListView(); 
    if(!alarmInitialized(this)) { 
     scheduleAlarms(this); 
    } 
} 

// And the few methods you suggested to schedule the alarm 
public static void scheduleAlarms(Context context) { 
    Calendar calendar = Calendar.getInstance(); 
    if (hasRunnedToday(context)) { // if the alarm has run this day 
     calendar.add(Calendar.DATE, 1); // schedule it to run again starting 
             // tomorrow 
    } 

    long firstRunTime = calendar.getTimeInMillis(); 
    AlarmManager mgr = (AlarmManager) context 
      .getSystemService(Context.ALARM_SERVICE); 
    Intent notificationIntent = new Intent(context, ReminderAlarm.class); 
    PendingIntent pi = PendingIntent.getActivity(context, 0, 
      notificationIntent, 0); 
    mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstRunTime, 
      AlarmManager.INTERVAL_DAY, pi); 

    ComponentName receiver = new ComponentName(context, BootReceiver.class); 
    PackageManager pm = context.getPackageManager(); 

    pm.setComponentEnabledSetting(receiver, 
      PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
      PackageManager.DONT_KILL_APP); 
} 

BootReceiver 클래스는 기본적으로이 클래스 단지 반복 클래스로부터 전달 된 변수를 잡아서 DB 삽입을 수행한다. 내가 그것을 검색하여 운이 아니지만 검색하는 경우 테스트 Toast.makeText 일부를 삽입 않았다.

이 코드는 BootReceiver 클래스를 호출하도록 알람을 예약하도록 제안 된 부분에 추가되었습니다. 그런 다음 BootReceiver 클래스에서, 나는 반복 클래스와 알림 알람 클래스에 다시 호출합니다 :

ComponentName receiver = new ComponentName(context, BootReceiver.class); 
    PackageManager pm = context.getPackageManager(); 

    pm.setComponentEnabledSetting(receiver, 
      PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 
      PackageManager.DONT_KILL_APP); 
+0

** "... 알람 매니저가 내가 설정 한 후 1 분 2014년 1월 10일 오후 5시 49분에서 실행하고 작동을 멈췄습니다. "** Calendar.HOUR_OF_DAY'를 0으로 설정하여 시간을 뒤로 설정하고 있습니다. 그러면 즉시 경보 트리거가되고 그 다음날 00:01까지 다시 트리거되지 않습니다. – Squonk

+0

@Squonk 그래서이 문제를 해결하는 방법에 대한 아이디어가 있습니까? 내 연구 결과, 특정 시간에 경보를 울릴 수 있다고 생각했기 때문입니다. –

+0

@Squonk 그래서이 코드를 어디에 넣어야합니까? 전체 부품을 답변으로 게시 하시겠습니까? –

답변

5

을 문제는

mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, 
      calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi); 

setInexactRepeating의 두 번째 인수는 문서

를 인용에 calendar.getTimeInMillis()

triggerAtMillis 알람 유형에 따라 적절한 시계를 사용하여 알람이 먼저 울리는 시간 (밀리 초)입니다. 이는 정확하지 않습니다.이 시간 전에는 알람이 울리지 않지만 알람을 처음 호출하기 전에 거의 모든 알람 간격이 지연 될 수 있습니다.

calendar.setTimeInMillis(System.currentTimeMillis()); 
calendar.set(Calendar.HOUR_OF_DAY, 0); 
calendar.set(Calendar.MINUTE, 1); 

당신이 다음 날이 달력을 할 수 알람의 첫 번째 실행을 wan't 경우 때문에 당신이 그것을 설정 한 후 aproximally 1 분 처음 실행을 의미

. add (Calendar. DATE, 1); '

작동이 중지됨에 따라 장치를 다시 부팅 했습니까? AlarmCalendar 경보 장치 재부팅에 유지되지 않습니다, 당신은 BroadcastReceiverBOOT_COMPLETED 이벤트를 수신하고 알람이 다시 does Alarm Manager persist even after reboot?

업데이트를 확인 등록을 등록 할 수 있습니다 : 당신이 여기의 요청에 따라 당신의 코드를 검토 한 후 몇 가지 도움이됩니다

에서 당신의 BOOT_COMPLETED수신기 클래스 : 당신의 ReminderAlarm CIA 요원에서

public void onReceive(Context context, Intent i) { 
    if (i.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { 
     ReminderAlarm.scheduleAlarms(this); 
    } 
} 

SS

protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.recurring); 

if(!alarmInitialized(this) { 
    scheduleAlarms(this); 
} 

}

public static void scheduleAlarms(Context context) { 

    Calendar calendar = Calendar.getInstance(); 

    if(hasRunnedToday(context)) {  //if the alarm has run this day 
     calendar.add(Calendar.DATE, 1); //schedule it to run again starting tomorrow 
    } 

    long firstRunTime = calendar.getTimeInMillis(); 

    AlarmManager mgr = (AlarmManager) context 
      .getSystemService(Context.ALARM_SERVICE); 
    Intent notificationIntent = new Intent(context, ReminderAlarm.class); 
    PendingIntent pi = PendingIntent.getActivity(context, 0, 
      notificationIntent, 0); 

    mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, 
      firstRunTime, AlarmManager.INTERVAL_DAY, pi); 
} 

public static boolean alarmInitialized(Context context) { 
    SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE); 

    long alarmLastRun = preferences.getLong("AlarmLastRun", -1); 


    return alarmLastRun != -1; 

} 

public static void updateAlarmLastRun(Context context) { 
    SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE); 


    preferences.edit() 
      .putLong("AlarmLastRun", new Date().getTime()) 
     .apply(); 
} 

public static boolean hasRunnedToday(Context context) { 
    SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE); 

    long alarmLastRun = preferences.getLong("AlarmLastRun", -1); 

    if(alarmLastRun == -1) { 
     return false; 
    } 

    //check by comparing day, month and year 
    Date now = new Date(); 
    Date lastRun = new Date(alarmLastRun); 


    return now.getTime() - lastRun.getTime() < TimeUnit.DAYS.toMillis(1); 
} 

알람으로 일정을 수 있기 때문에 당신의 알림 클래스 알람은 알람이 실행 된 마지막 시간을 업데이트 할 updateAlarmLastRun를 호출해야 실행하는 각 시간이 필요하다 하루에 실행하고 사용자가 알람을 실행하기 전에 장치를 다시 부팅하면 calendar.add(Calendar.DATE, 1);을 사용하지 않으려 고하므로 하루를 건너 뛸 수 있습니다. 당신의 Manifest.xml

<receiver android:name=".BootReceiver" android:enabled="true" android:exported="false" android:permission="android.permission.RECEIVE_BOOT_COMPLETED"> 
    <intent-filter> 
     <action android:name="android.intent.action.BOOT_COMPLETED" /> 
    </intent-filter> 
    </receiver> 

노트에

: 문맥 클래스 필드의 경우 개체가 해당 분야 contextcontext 필드에 대한 참조를 보유하고 있기 때문에 당신은 context = this을하지 말아야

  1. 은 참조를 보유하고 누수가 될 객체에
  2. Receiver 'onReceive`에는 "notificationCount"onRec와 같은 권한이 없습니다. 장치가 부팅을 마칠 때 시스템에 의해. 알람이 실행 updateAlarmLastRun

희망 호출이의 도움이되면

  • +0

    그래, 코드를 추가하여 재부팅 할 때까지 알람이 계속 유지되도록하십시오. 하지만 어디에서 instance.add()를 추가해야합니까? –

    +0

    나의 나쁜 나는 캘린더를 의미했다. 나는 awnser를 업데이트했다. – forcewill

    +0

    그래서 나는 내 수업 모두에서 그 라인을 추가해야합니까? 편집 된 부분을 확인하도록 도와 줄 수 있습니까? –