2017-01-23 8 views
6

解決策の背後にあるロジックが正しいかどうかは正確には分からないので、ここに完全な問題の説明を含めますが、私はこの不正確さを引き起こしているアラーム自体を設定しています。まれに純粋なフォールト(アラームはまったくトリガーしません)。複数のリマインダーを追加すると、同時にそれらがトリガーされます


ユーザーは、投薬リストから新しい投薬を追加することができます。

画面1

特定の薬剤が発見された場合、それをクリックすると、画面が薬の名前が含まれており、「薬量学」タイトル(緑のバー)の下にあることをhttp://imgur.com/nLC9gTG

この画面が表示されますその薬のリマインダを追加することができます。

「単位」フィールドは忘れてください。

「頻度」フィールドは数字を受け取り、「頻度」フィールドの右側のラベルはクリック可能で、ドロップダウンメニューが表示され、そこからユーザーは「時間帯」または「時間帯」を選択できます週間"。

「曜日」のラベル(スクリーンショットではラベルが空です)もクリック可能です。ユーザはドロップダウンメニューを表示し、そこからユーザは曜日から複数の日を選択できます。

「治療期間」フィールドは数値を受け取り、「治療期間」フィールドの右側のラベルはユーザーの「頻度」の選択を反映します(「週当たりの回数」の場合は「週」 "、それが" 1ヶ月に1回 "の場合、そのラベルは"月 "と表示されます)。


この第二のスクリーンショットhttp://imgur.com/AcUmlHHの画面2

- ユーザーが、彼が追加しようとしていますことを、この薬(項目、例えば、など)のためのリマインダを有効にすることを可能にするスイッチがあります。

上記の[頻度]フィールドに0より大きい数値(たとえば、2)が設定されている場合、リマインダスイッチは「通知を取得する」緑色のバーのすぐ下に表示されるリマインダーフィールドのリストを作成します。

最終的に「Add Medication」を押すと、このMedicationオブジェクトに追加する「Frequency」(リマインダの数)とともに、新しいMedicationオブジェクトがデータベースに作成されます。


薬のテーブルを作成します。

id 
name 
description 
dosage 
frequency 
frequencyType 
treatmentDuration 
ForeignCollection<MedicationReminder> 
ArrayList<DayChoice> (DayChoice is a class with "Day Name" and "Selected") 
when 
whenString 
units 
unitForm 
remarks 
remindersEnabled 

はMedicationReminderテーブルを作成します。

Medication (foreign key for the Medication table) 
Calendar 
int[] days_of_week 
totalTimesToTrigger 
この新しい薬オブジェクトを作成する際

Medication medication = new Medication(); 
medication.setFrequency() 
medication.setName().setDosage().setRemindersEnabled().... 

assignForeignCollectionToParentObject(medication); 

assignForeignCollectionToParentObject(薬)

private void assignForeignCollectionToParentObject(Medication medicationObject) { 
    medicationDAO.assignEmptyForeignCollection(medicationObject, "medicationReminders"); 

    MedicationRemindersRecyclerAdapter adapter = 
     (MedicationRemindersRecyclerAdapter) remindersRecyclerView.getAdapter(); 

    //Clear previous reminders 
    medicationObject.getMedicationReminders().clear(); 

    for (int i = 0; i < adapter.getItemCount(); i++) { 
     int realDaysSelected = 0; 

     MedicationReminder medReminder = adapter.getItem(i); 
     medReminder.setMedication(medicationObject); 
     medReminder.setDays_of_week(daysOfWeekArray); 

     //These days are populated when the user selected them from the "Days of Week" clickable label 
     for (int aDaysOfWeekArray : daysOfWeekArray) { 
     if (aDaysOfWeekArray != 0) realDaysSelected++; 
     } 

     medReminder.setTotalTimesToTrigger(
      Integer.parseInt(treatmentDurationET.getText().toString()) * realDaysSelected); 
     medicationObject.getMedicationReminders().add(medReminder); 
    } 

    setupMedicationReminders(medicationObject.getMedicationReminders().iterator()); 
} 

setupMedicationReminders()

public void setupMedicationReminders(Iterator<MedicationReminder> medicationRemindersIterator) { 
    PendingIntent pendingIntent; 
    AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 

    while (medicationRemindersIterator.hasNext()) { 
     MedicationReminder medReminder = medicationRemindersIterator.next(); 

     for (int i = 0; i < medReminder.getDays_of_week().length; i++) { 

     int dayChosen = medReminder.getDays_of_week()[i]; 

     if (dayChosen != 0) { 
      medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis()); 
      medReminder.getAlarmTime().set(Calendar.DAY_OF_WEEK, dayChosen); 

      Intent intent = new Intent(AddExistingMedicationActivity.this, AlarmReceiver.class); 
      intent.putExtra(Constants.EXTRAS_ALARM_TYPE, "medications"); 
      intent.putExtra(Constants.EXTRAS_MEDICATION_REMINDER_ITEM, (Parcelable) medReminder); 

      pendingIntent = PendingIntent.getBroadcast(this, medReminder.getId(), intent, 
       PendingIntent.FLAG_UPDATE_CURRENT); 

      int ALARM_TYPE = AlarmManager.ELAPSED_REALTIME_WAKEUP; 

      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      am.setExactAndAllowWhileIdle(ALARM_TYPE, medReminder.getAlarmTime().getTimeInMillis(), 
       pendingIntent); 
      } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
      am.setExact(ALARM_TYPE, medReminder.getAlarmTime().getTimeInMillis(), pendingIntent); 
      } else { 
      am.set(ALARM_TYPE, medReminder.getAlarmTime().getTimeInMillis(), pendingIntent); 
      } 
     } 
     } 
    } 
} 

問題は、薬剤リマインダが追加されたとき、彼らはいつもすぐに追加された後にトリガされ、すべてが同時にされています。

私は土曜日と金曜日に頻度2を1週間の治療期間で選択します。つまり、金曜日に2つ、土曜日に2つ、合計4つのアラームが追加されます。

これを行うと土曜日になると、土曜日に同時にアラームがトリガーされます。

どういうところが間違っていますか?

答えて

3

を設定するための行を逃しました。現在の日が月曜日で、Calendar.THURSDAYset(Calendar.DAY_OF_WEEK)と呼んでいる場合、日付を前の木曜日に変更する必要がありますか?次の木曜日ですか?あなたは知らない。

アラームがすべてすぐに消えている場合は、DAY_OF_WEEKを変更するとカレンダーが転送されずに後ろに移動していることを示します。 DAY_OF_WEEKを設定した後、getTimeInMillis()と呼び出して、現在の時刻と比較することを確認します。それが小さければ、カレンダーは元に戻ります。これを修正するには、カレンダーに7日間追加してください。


また、この種類のアラーム:AlarmManager.ELAPSED_REALTIME_WAKEUPを使用しています。このタイプは、デバイスのブート以降に経過した時間を表す値をとります。

ただし、時間値(つまり、Calendar.getTimeInMillis())にRTCを使用しています。これらの2つの値は互換性がありません。 RTCを使用する場合は、AlarmManager.RTC_WAKEUPを使用する必要があります。

+0

あなたはsetTimeInMillis(System.currentTimeInMillis)の行については正しいですが、チェックするときには、デバッグ中にそれを削除してからずっと時間がかかっているようですが、それは間違っています。賞金は40分で有効期限が切れます。私は今すぐ確認し、これに戻ります – Odaym

+0

あなたはDAY_OF_WEEKを任意に指定することで、カレンダーの日付が前後になるようにすることもできます。今私は7を追加する方法に頼るつもりはありませんが、私はカレンダーを完全に避け、JodaTimeのLocalDateTimeを使用しますので、私はこの不一致にぶつからないでしょう、あなたはどう思いますか? – Odaym

+0

JodaTimeを使用する利点は何ですか?あなたは曜日をどのように設定しますか?あなたのコードに何も問題はありません。フォワードの代わりにカレンダーが設定される可能性を考慮する必要があります。どのようにJodaTimeを使用してこの問題を解決しますか? –

2

投薬リマインダーが追加され、追加された直後に常にトリガーされ、同時にすべてがトリガーされるという問題があります。

これは、あなたが求めている理由です。あなたは、常に現在の時刻を読み取り、アラーム時間にそれを設定している:

medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis()); 

あなたはthis screenに、ユーザによって提供される時間を読んだことがない、あなたのリマインダーのすなわちCalendarフィールドが設定されることはありません。ここにあなたのコードは次のとおりです。

medReminder.getAlarmTime().setTimeInMillis(System.currentTimeMillis()); 
medReminder.getAlarmTime().set(Calendar.DAY_OF_WEEK, dayChosen); 

結果は予測できません:あなたはこれを行うと

MedicationReminder medReminder = adapter.getItem(i); 
    medReminder.setMedication(medicationObject); 
    medReminder.setDays_of_week(daysOfWeekArray); 

    for (int aDaysOfWeekArray : daysOfWeekArray) { 
    if (aDaysOfWeekArray != 0) realDaysSelected++; 
    } 

    medReminder.setTotalTimesToTrigger(...); 

は、あなたが実際にリマインダ時間

+0

私は実際にアラーム行に対応するアダプタの内部に時間を追加します。各行がクリックされると時間ピッカーが表示され、そのピッカーから時間と分などを設定しますmedication.setAlarmTime()を呼び出し、アクティビティiからそれらのオブジェクトを取得して使用します。 – Odaym

0

これはあなたの質問には答えられないかもしれませんが、あなたはこれを考慮する必要があります。

私はこれが悪いUXだと主張します。このアプリケーションのユーザーは、時間だけに基づくリマインダーの時刻(、日付なし、)を混乱させる可能性があります。だから、ユーザーが編集できるリマインダーの横に日付を追加する方がいいかもしれない。初めて生成するときは、正しい順序で設定します。

Reminder 1: 2/2/2017 13:04 

Reminder 2: 9/2/2017 13:04 

Reminder 3: 16/2/2017 13:04 

Reminder 4: 25/2/2017 13:04 

これは現実世界の方が優れています。このユースケースを考えてみましょう。ユーザーは彼と電話を持っていますが、彼は投薬を忘れています。彼は適切な時にそれを取ることができないので、彼は後でそれを取る(おそらくは時間をとる)。これは計画を台無しにしますが、この場合、彼は実際に投薬を受けた日付に日付を編集することができます。次に、times_per_week、times_per_monthに基づいて間隔を追うように編集した後に、すべてのリマインダーの日付と時刻を調整します。彼は過去の日付に変更することはできません。

Reminder 1: 2/2/2017 13:04 // He took medication on time 

Reminder 2: 9/2/2017 13:04 // He missed this one and changed to date bellow 
      10/2/2017 12:22 // This is when he actually took the medication 

Reminder 3: 16/2/2017 13:04 // This is no longer valid 
      17/2/2017 12:22 // You adjust reminder to this date and time 

Reminder 4: 25/2/2017 13:04 // This is no longer valid 
      26/2/2017 12:22 // You adjust reminder to this date and time 

各リマインダーのユーザーは、特定の範囲の日付に制限する必要があります。彼はちょうど任意の日付を選択させることはできません。これは彼の計画の設定と現在の日付に基づいていますが、私はそれに取り掛かりたくありません。それはたくさんの仕事です。

これらの変更をデータベースに書き込むと、データが失われないはずです。後で、アプリケーションに機能を追加することができます。これは、ユーザーが何回遅れていたか、ユーザーが時間通りに薬を服用した回数をレポートします。それは、モバイルアプリケーションのための素晴らしい小さな機能です。

関連する問題