Android : การใช้ AlarmManager เตือนการทานยา

สวัสดีผู้อ่านนะครับ บทความนี้ผมมาอธิบายการทำแอพพลิเคชั่นเตือนการทานยาแบบง่ายๆ เขียนแบบค่อนข้างรีบซะด้วย ตัวอย่างในวันนี้ผมมีโค้ดให้ดาวน์โหลดนะครับ และ อธิบายเพิ่มเติมในส่วนที่สำคัญเช่น TimePickerDialog , AlarmManage , BroadcastReceiver รวมถึง  PowerManager  และ KeyguardManager เอาหละไปดูโครงสร้างคร่าวๆกันก่อน

 

โครงสร้างตัวอย่าง

โครงสร้างหลักของตัวอย่างนี้มี 3 ไฟล์คือ

MainActivity ทำหน้าที่ตั้งเวลาทานยาโดย TimePickerDialog (ใช้เลือกเวลา) , บอกให้นาฬิกาเตือนเวลาเท่าไหร่ และ แสดงเวลาเตือนใน listview (สามารถเพิ่มเวลาเตือนได้หลายอัน)

AlarmReceiver ทำหน้าที่รับการเตือนข้อนาฬิกา และเรียก Showevent ให้แสดง

ShowEvent ทำหน้าที่ในการแสดงไดอะล๊อกเตือนพร้อมเสียง

Screenshot from 2014-11-23 17:20:28รูปที่ 1 ภาพขั้นตอนการทำงานข้อแอพพลิเคชั่น

 

โค้ดตัวอย่าง

สามารถ ดาวน์โหลดโปรเจ็คตัวอย่างได้ที่ -> AlarmTest

** โดยตัวอย่างนี้ผมได้นำโค้ดของ android4health มาแก้ไขและอธิบายเพิ่มเติมครับโดยผู้เขียนคือคุณ tehnn

 

อธิบายโค้ดตัวอย่าง

MainActivity.java

ส่วนประกอบที่สำคัญคือส่วนแรกคือ TimePickerDialog คือไดอะล็อกที่สามารถเลือกเวลาได้ ในตัวอย่างนี้ให้เลือกเป็นชั่วโมงและนาที โดยคลาสนี้ (class TimePicker Fragment เป็นคลาสข้างในของ MainActivity อีกทีครับ) มี 2 ฟังก์ชั่นหลักดังนี้

– onCreateDialog ทำการสร้าง TimePickerDialog โดยตั้งค่าชั่วโมงและนาทีเป็นเวลาปัจจุบัน

– onTimeSet ทำเมื่อเราทำการตั่งค่าเวลาเรียบร้อย คือ กดปุ่ม ok

   class TimePickerFragment extends DialogFragment  
       implements TimePickerDialog.OnTimeSetListener {  
     int callCount = 0;  
     @Override  
     public Dialog onCreateDialog(Bundle savedInstanceState) {  
       final Calendar c = Calendar.getInstance();  
       int hour = c.get(Calendar.HOUR_OF_DAY);  
       int minute = c.get(Calendar.MINUTE);  
       return new TimePickerDialog(getActivity(), this, hour, minute,  
           DateFormat.is24HourFormat(getActivity()));  
     }  
     public void onTimeSet(TimePicker view, int hourOfDay, int minute) {  
       if(callCount==0){  
         // Do something with the time chosen by the user  
       }  
       callCount++;  
     }  
   }  

อีกส่วนหนึ่งที่เป็นส่วนสำคัญคือการตั้งค่าเวลาที่จะทำการแจ้งเตือนในฟังก์ชั่น setAlarm โดยวิธีการในขั้นตอนนี้คือเราจะตั้งเวลาให้กับ AlarmManage และ AlarmManage จะเรียกใช้ pendingIntent (ในบรรทัดที่  6) เพื่อบอกให้แอพพลิแคชั่นของเราให้รู้ว่าถึงเวลารัน AlarmReceiver แล้วนะ

1:    private void setAlarm(Calendar targetCal){  
2:      final int _id = (int) System.currentTimeMillis();  
3:      Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);  
4:      PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), _id, intent, 0);  
5:      AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);  
6:      alarmManager.set(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(), pendingIntent);  
7:    }  

 AlarmReceiver.java

คลาสนี้มีหน้าที่ในการรอรับ Broadcast (ในที่นี้คือการเตือนของนาฬิกาครับ) เมื่อคลาสนี้ทำงานจะไปทำงานในฟังก์ชั่น onReceive โดยจะไปทำการเรียกใช้คลาส ShowEvent เพื่อเรียกไดอะล๊อกนั้นเอง

 public class AlarmReceiver extends BroadcastReceiver {  
   @Override  
   public void onReceive(Context context, Intent arg1) {  
     Intent i = new Intent(context, ShowEvent.class);  
     i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
     context.startActivity(i);  
   }  
 }  

ShowEvent.java

คลาส ShowEvent จะถูกเปิดแสดงขึ้นมาในเวลาที่กำหนดโดย AlarmReceiver ส่วนสำคัญส่วนแรกคือ การตั้งค่าให้คลาสนี้สามารถแสดงขึ้นมาได้ขณะที่อุปกรณ์อยู่ในขณะพักจอ และ ทำให้แอพพลิเคชั่นแสดงผลขึ้นมาโดยไม่ต้องใส่คีย์ที่ล๊อกเครื่องครับ สามารถดูรายละเอียดของคลาสที่นำมาใช้เพิ่มเติมได้ที่ PowerManagerKeyGuardManager และ KeyguardLock

      PowerManager pm;  
      WakeLock wl;  
      KeyguardManager km;  
      KeyguardLock kl;           
      
      pm = (PowerManager) getSystemService(Context.POWER_SERVICE);  
      km=(KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);  
      kl=km.newKeyguardLock("ShowEvent");  
      wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP|PowerManager.ON_AFTER_RELEASE, "ShowEvent");  
      wl.acquire(); //wake up the screen  
      kl.disableKeyguard();  

ส่วนสำคัญที่สองคือฟังก์ชั่น onResume จะทำการเรียกเสียงเตือนโดยจะทำการตั้งค่าจากเสียงริงโทนของเราก่อน หากไม่มีรินโทนก็จะใช้เสียงนาฬิกาปลุก และ นอทิฟิเคชั่น ในลำดับถัดไป (เปลี่ยนได้ตามใจนะครับ)

      Uri notif = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);  
      if(notif==null){   
         notif = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);  
         if(notif==null){   
            notif = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);  
         }  
      }  
      r = RingtoneManager.getRingtone(getApplicationContext(), notif);  
      r.play();  

ลายละเอียดอีกนิดหน่อยของคลาส Showevent คือเราจะทำการตั้งค่าใน AndroidManifest.xml ให้คลาสนี้ซึ้งเป็น Activity แสดงเป็นรูปแบบไดอะล๊อก โดยเพิ่มโค้ดข้างล่างนี้เข้าไปใน AndroidManifest.xml ตรงส่วนของ acitivty Showevent

      android:theme="@android:style/Theme.Dialog"  

การขอ permission ที่จำเป็น

ในไฟล์ AndroidManifest.xml เราจะต้องทำการขอ permission ไว้ 2 อย่างคือ WAKE_LOCK และ DISABLE_KEYGUARD โดยการขอใช้ให้นำโค้ดข้างล่างไปเพิ่มใน AndroidManifest.xml

      <uses-permission android:name="android.permission.WAKE_LOCK" />  
      <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />  

รายละเอียดของ permission เพิ่มเติมนะครับ

WAKE_LOCK คือ ขอใช้สิทธิในการใช้ WakeLock ในตัวอย่างนี้เราจะทำให้อุปกรณ์ของเราเปิด (ปลุกให้มันตื่นจาก sleep นั้นเอง)

DISABLE_KEYGUARD คือ ขอให้เมื่อรันแอพพลิเคชั่นนี้ขึ้นมาไม่ต้องป้อนรหัสปลดล๊อค

เอาหละครับอธิบายมายาวพอสมควรซึ้งผมก็คิดว่าครอบคลุมส่วนที่สำคัญทั้งหมดแล้วครับ ไว้พบกันในบทความต่อไป (บทความ Login Facebook)

 

ผลลัพธ์ตัวอย่าง

Screenshot from 2014-11-23 17:09:27

 

About octoboy


Android Developer, Study Master degree of Computer Engineering at Prince of Songkla university.