Để thực hiện việc nạp chương trình cho điện thoại, ta cần kích hoạt điện thoại vào chế độ giành quyền admin theo bước sau:
- Thực hiện theo từng bước như sau: Mở màn hình android, vào cài đặt
tùy chọn nhà phát triển chạm tay nhanh hai lần là kích hoạt quyền admin cho máy.
- Giao diện hẹn giờ và điều khiển thiết bị bao gồm: có thể điều khiển tùy biến theo nhiều chế độ, nhiều khung giờ, tác động trực tiếp vào thiết bị qua chạm vào biểu tượng.
- Tạo project Android cho điện thoại tương tự như các bước tạo project trên , sau đó ta sử dụng FrameLayout. FrameLayout là loại layout đơn giản mà các view con chứa bên trong xếp chồng lên nhau và định dạng bằng thuộc tính layout_gravity.
Hình 4. 20 Màn hình khi mở ứng dụng
Giao diện hiển thị thời gian ngày, tháng, năm, giờ, phút giây để người dùng có thể dễ dàng quan sát được thời gian hiện tại.
Khi thời gian hiện tại rơi vào ngày lễ thì thời gian báo tiếp theo sẽ hiển thị cho ta biết được là đang trong thời gian nghỉ lễ “nghỉ lễ => tắt chuông”. Khi rơi vào thời gian thi học kì thì thời gian báo tiếp theo sẽ hiển thị thời gian báo tiếp theo của ca thi. Còn đối với ngày bình thường thì thời gian báo tiếp theo sẽ hiển thị thời gian tiếp theo của tiết học.
Khi mở ứng dụng thì mặc định Radiobutton bật sẽ được chọn vì Radiobutton bật cho phép chuông sẽ bật trong chế độ tự động, rơi vào ngày học bình thường và ngày thi học kì thì chuông sẽ reo. Khi ta muốn tắt chuông toàn hệ thống thì chọn Radiobutton tắt.
Checkbox ưu tiên bấm chuông bằng tay sẽ được chọn khi chế độ tự động gặp vấn đề hoặc có sự thay đổi đột xuất.
Chế độ ưu tiên bấm chuông bằng tay
Khi chọn checkbox ưu tiên bấm chuông bằng tay thì sẽ hiện ra giao diện như hình 4.21. Gồm hai Button: Button 1 hồi (5s) và Button 2 hồi (10s).
Khi ta chọn Button 1 hồi thì sẽ tiến hành gởi giá trị lên firebase mothoi = 1 chuông sẽ reo sau khi đã reo đúng 5s thì mothoi = 0 thì chuông sẽ tự động tắt.
Khi ta chọn Button 2 hồi thì sẽ tiến hành gởi giá trị lên firebase haihoi = 1 chuông sẽ reo sau khi đã reo đúng 10s thì haihoi = 0 thì chuông sẽ tự động tắt.
Hình 4. 21 Màn hình điều khiển bằng chuông
private val onRun5s = View.OnClickListener {
Timber.d("Button onRun5s Click")
//xử lí run chuông 5s bằng tay
chuong5s.setValue(0)
chuong5s.setValue(1)
Handler().postDelayed({
chuong5s.setValue(0)
Toast.makeText(activity, "Đã reo 5s", Toast.LENGTH_LONG).show()
}, 5000)
}
Timber.d("Button onRun10s Click")
//xử lí run chuông 10s bằng tay
chuong10s.setValue(0)
chuong10s.setValue(1)
Handler().postDelayed({
chuong10s.setValue(0)
Toast.makeText(activity, "Đã reo 10s", Toast.LENGTH_LONG).show()
}, 10000)
}
Khi ta chọn biểu tượng thì giao diện màn hình Navigation gồm “Trang chủ”, “Cài đặt”, “Giới thiệu” và “Ghi chú”
Hình 4. 22 Màn hình Navigation
Khi ta chọn cài đặt thì màn hình sẽ chuyển qua giao diện cài đặt.
Hình 4. 23 Màn hình cài đặt
Khi chưa chọn chế độ ngày lễ và ngày thi thì giao diện sẽ như hình 4.23 Khi ở chế độ này thì chế độ tự động sẽ hiểu là đang ở ngày bình thường, chuông sẽ reo theo 12 tiết học hình 4.25.
public static ArrayList<GioPhut> getGioHocMacDinh() { ArrayList<GioPhut> gio = new ArrayList<>();
gio.add(new GioPhut(7, 0)); gio.add(new GioPhut(7, 50));
gio.add(new GioPhut(8, 40)); //Ra Chơi
gio.add(new GioPhut(8, 50)); gio.add(new GioPhut(9, 40));
gio.add(new GioPhut(10, 30)); //Ra Chơi
gio.add(new GioPhut(10, 40)); gio.add(new GioPhut(11, 30)); gio.add(new GioPhut(12, 30));
gio.add(new GioPhut(13, 20));
gio.add(new GioPhut(14, 10)); //Ra Chơi gio.add(new GioPhut(14, 20));
gio.add(new GioPhut(16, 0)); // Ra Chơi gio.add(new GioPhut(16, 10)); gio.add(new GioPhut(17, 0)); gio.add(new GioPhut(17, 50)); return gio; } else { // Ngày Thường
Timber.i("--- Ngày Thường ---") Timber.i("Đặt alarms theo ngày thường")
Timber.i("Thời gian hiện tại: $thoiGianHienTaiString") trangthai.setValue("Ngày Thường - 12 tiết")
// Ngày thường lấy giá trị mặc định val gioMacDinh: ArrayList<GioPhut> = SharedPreferenceManager.getGioHocMacDinh() gioMacDinh.forEachIndexed { index, gioPhut ->
calendar.set(Calendar.HOUR_OF_DAY, gioPhut.hour) calendar.set(Calendar.MINUTE, gioPhut.minute) calendar.set(Calendar.SECOND, 0)
var rachoi = false
if (index==0 || index == 2 || index == 5 || index == 10 || index == 13) {
rachoi = true }
scheduleOneTimeAlarm(context, index, calendar.timeInMillis, rachoi)
}
}
Vào đúng thời gian giờ ra chơi thì sẽ tiến hành gửi giá trị lên firebase haihoi = 1 khi đó chuông sẽ reo 10s, reo xong 10s thì haihoi = 0 chuông tắt. Ngược lại không phải giờ ra chơi thì chuông sẽ reo 5s.
val batChuong = SharedPreferenceManager.getChuongDangBat() val chuongTay = SharedPreferenceManager.getCheckBoxTay() if (batChuong && !chuongTay) {
thoi_gian_bao.setValue(thoiGian) if (gioRaChoi) {
// Ra Chơi nên bật chuông 10s Timber.d("Ra chơi bật chuông 10s") haihoi.setValue(0)
haihoi.setValue(1) Handler().postDelayed({ haihoi.setValue(0)
}, 10000) } else { Timber.d("Bật chuông 5s") mothoi.setValue(0) mothoi.setValue(1) Handler().postDelayed({ mothoi.setValue(0) }, 5000) } } Khi chọn chế độ ngày lễ
Hình 4. 24 Màn hình chính hiển thị ngày lễ Hình 4. 25 Màn hình cài đặt hiển thị ngày lễ
Ngày lễ gồm ngày bắt đầu và ngày kết thúc. Khi thời gian rơi vào trong khoảng ngày bắt đầu và ngày kết thúc thì khi đó chuông sẽ tắt, sẽ không gửi giá trị lên firebase. Nếu thời gian không rơi vào ngày lễ thì sẽ là ngày học bình thường. Chuông sẽ reo tự động theo 12 tiết.
if (dauLe > 0 && ketLe > 0 && dauLe <= thoiGianHienTai && thoiGianHienTai <= ketLe) {
// Ngày lễ
trangthai.setValue("Ngày Lễ - tắt chuông") textGioTiepTheo = "Ngày lễ -> tắt chuông" }
Chế độ ngày thi cũng gồm ngày bắt đầu và ngày kết thúc, chế độ này có thêm hai chế độ mặc định và điều chỉnh. Khi thời gian hiện tại rơi vào khoảng thời gian của ngày bắt đầu và kết thúc thì chế độ tự động sẽ reo chuông theo giờ của các ca thi mặc định hoặc điều chỉnh. Nếu thời gian không rơi vào khoảng thời gian thi thì sẽ là ngày học bình thường. Chuông sẽ reo tự động theo 12 tiết. else if (dauThi > 0 && ketThi > 0 && dauThi <= thoiGianHienTai &&
thoiGianHienTai <= ketThi) { // Thi Học Kì
if (dieuchinh) {
trangthai.setValue("Ngày Thi - điều chỉnh") ngayThi?.let {
for ((index, value) in it.listGio.withIndex()) {
val calendar2: Calendar = Calendar.getInstance().apply { timeInMillis = value
}
val hour = calendar2.get(Calendar.HOUR_OF_DAY) val minute = calendar2.get(Calendar.MINUTE) calendar.set(Calendar.HOUR_OF_DAY, hour) calendar.set(Calendar.MINUTE, minute) calendar.set(Calendar.SECOND, 0)
val thoiGianBaoThuc = calendar.timeInMillis if (thoiGianHienTai < thoiGianBaoThuc) {
val different = thoiGianBaoThuc - thoiGianHienTai if (different > 0 && different <= smallest) {
smallest = different gio = value } } } if (gio > 0) {
textGioTiepTheo = "Ngày thi ->" +
Util.millisecondsToStringDate(gio, Util.formatTime) }
} } else {
Timber.d("Đặt alarm thi mặc định")
trangthai.setValue("Ngày Thi - mặc định") val gioMacDinh: ArrayList<GioPhut> = SharedPreferenceManager.getGioThiMacDinh() gioMacDinh.forEachIndexed { index, gioPhut ->
calendar.set(Calendar.HOUR_OF_DAY, gioPhut.hour) calendar.set(Calendar.MINUTE, gioPhut.minute)
calendar.set(Calendar.SECOND, 0)
val thoiGianBaoThuc = calendar.timeInMillis if (thoiGianHienTai < thoiGianBaoThuc) {
val different = thoiGianBaoThuc - thoiGianHienTai if (different > 0 && different <= smallest) {
smallest = different
gio = calendar.timeInMillis }
} }
if (gio > 0) {
textGioTiepTheo = "Ngày thi ->" + Util.millisecondsToStringDate(gio, Util.formatTime)
} } }
Hình 4. 26 Màn hình chính hiển thị ngày thi mặc định
Hình 4. 27 Màn hình cài đặt hiển thị ngày thi mặc định
Chế độ mặc định sẽ được cài sẵn thời gian các ca thi cố định. Khi rơi vào các thời gian này thì sẽ tiến hành gửi giá trị lên firebase chuông reo.
public static ArrayList<GioPhut> getGioThiMacDinh() { ArrayList<GioPhut> gio = new ArrayList<>();
gio.add(new GioPhut(7, 15)); gio.add(new GioPhut(8, 15)); gio.add(new GioPhut(8, 45)); gio.add(new GioPhut(9, 45)); gio.add(new GioPhut(10, 45)); gio.add(new GioPhut(11, 15)); gio.add(new GioPhut(13, 0)); gio.add(new GioPhut(14, 0)); gio.add(new GioPhut(14, 30)); gio.add(new GioPhut(15, 15)); gio.add(new GioPhut(16, 15)); gio.add(new GioPhut(16, 45));
return gio; }
Khi chọn Switch thì sẽ chuyển sang chế độ ngày thi điều chỉnh
private val swThi =
CompoundButton.OnCheckedChangeListener { _, checked: Boolean -> if (checked) {
layoutDefault.visibility = View.GONE layoutAdjust.visibility = View.VISIBLE Timber.d("Điều chỉnh")
} else {
layoutDefault.visibility = View.VISIBLE layoutAdjust.visibility = View.GONE Timber.d("Mặc định")
} }
Hình 4. 28 Màn hình chính hiển thị ngày thi tùy chỉnh
Hình 4. 29 Màn hình cài đặt hiển thị ngày thi tùy chỉnh
Chế độ này thì ta có thể điều chỉnh được thời gian của các ca thi khi mà lịch thi cố định có sự thay đổi.
private fun chonGio(edt: TextInputEditText) { val calendar = Calendar.getInstance()
val gio = calendar.get(Calendar.HOUR_OF_DAY) val phut = calendar.get(Calendar.MINUTE)
val timePickerDialog = TimePickerDialog(context,
TimePickerDialog.OnTimeSetListener { _, hourOfDay, minute -> calendar.set(Calendar.HOUR_OF_DAY, hourOfDay)
calendar.set(Calendar.MINUTE, minute)
val formatDate = Util.dateToString(calendar.time, Util.formatTime) edt.setText(formatDate)
when (edt.id) {
R.id.chongio1 -> timeGio1 = calendar.timeInMillis R.id.chongio2 -> timeGio2 = calendar.timeInMillis R.id.chongio3 -> timeGio3 = calendar.timeInMillis R.id.chongio4 -> timeGio4 = calendar.timeInMillis R.id.chongio5 -> timeGio5 = calendar.timeInMillis R.id.chongio6 -> timeGio6 = calendar.timeInMillis R.id.chongio7 -> timeGio7 = calendar.timeInMillis R.id.chongio8 -> timeGio8 = calendar.timeInMillis }
}, gio, phut, true)
timePickerDialog.show() }
Khi chọn cả 2 chế độ ngày lễ và ngày thi
Khi chọn cả 2 ngày này thì lúc này chế độ tự động sẽ có 3 khoảng thời gian đó là khoảng thời gian nghỉ lễ, thời gian thi học kỳ và ngày học bình thường. Khi rơi vào khoảng thời gian nào thì khoảng thời gian đó sẽ hoạt động.
Nếu trường hợp người dùng lỡ chọn trùng ngày bắt đầu và ngày kết thúc của ngày lễ và ngày thi học kỳ thì lúc này ứng dụng sẽ ưu tiên ngày lễ.
Button Lưu và Xóa
Khi ta chọn dữ liệu xong thì cần phải chọn nút nhấn lưu để lưu lại dữ liệu đã chọn bao gồm checkbox, switch và các dữ liệu thời gian, còn nút nhấn xóa thì ta sẽ xóa toàn bộ dữ liệu đã lưu.
Hình 4. 30 Màn hình giới thiệu
Khi ta chọn ghi chú thì màn hình sẽ chuyển qua giao diện ghi chú
Ghi chú này giúp cho người dùng có thể ghi chú lại những việc cần thiết, quan trọng,vv.