I'm trying to create a small alarm android application, I'm new to android developing, sorry in advance if it's a silly question. the problem I am facing is that the alarm doesn't start playing when it reaches the time.
Here's the code of MainActivity.kt
package com.example.a22012011085_pr4
import com.example.a22012011085_pr4.databinding.ActivityMainBinding
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.PendingIntent
import android.app.TimePickerDialog
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.annotation.RequiresApi
import java.util.Calendar
import java.text.SimpleDateFormat
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var selectedAlarmTime:Long = 0
private var remindTime: Long = 0
@RequiresApi(Build.VERSION_CODES.S)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
enableEdgeToEdge()
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
binding.btn1.setOnClickListener{
showTimerDialog()
}
binding.btn2.setOnClickListener{
cancelAlarm()
}
binding.card2.visibility = View.GONE
binding.remainderTime.visibility = View.GONE
val timePicker = binding.remainderTime
timePicker.hour = getHour()
timePicker.minute = getMinute()
}
private fun getHour():Int {
val cal = Calendar.getInstance()
cal.timeInMillis = remindTime
return cal[Calendar.HOUR_OF_DAY]
}
private fun getMinute(): Int{
val cal = Calendar.getInstance()
cal.timeInMillis = selectedAlarmTime
return cal[Calendar.MINUTE]
}
@RequiresApi(Build.VERSION_CODES.S)
private fun showTimerDialog(){
val cldr = Calendar.getInstance()
val hour: Int = cldr.get(Calendar.HOUR_OF_DAY)
val minutes: Int = cldr.get(Calendar.MINUTE)
val picker = TimePickerDialog(
this,
{_, sHour, sMinute -> sendDialogDataToActivity(sHour, sMinute)},
hour,
minutes,
false
)
picker.show()
}
@RequiresApi(Build.VERSION_CODES.S)
@SuppressLint("SimpleDataFormat")
private fun sendDialogDataToActivity(hour: Int, minute:Int){
val alarmCalender = Calendar.getInstance()
val year:Int = alarmCalender.get(Calendar.YEAR)
val month:Int = alarmCalender.get(Calendar.MONTH)
val day: Int = alarmCalender.get(Calendar.DATE)
alarmCalender.set(year, month,day, hour,minute,0)
val alarmTimeText = findViewById<TextView>(R.id.alarmTimeText)
binding.card2.visibility = View.VISIBLE
alarmTimeText.text = SimpleDateFormat("hh:mm ss a dd MMM yyyy").format(alarmCalender.time)
selectedAlarmTime = alarmCalender.timeInMillis
setAlarm(selectedAlarmTime,"Start")
Toast.makeText(this,"Time: hour ${hour}, minutes: ${minute}", Toast.LENGTH_SHORT).show()
}
@RequiresApi(Build.VERSION_CODES.S)
@SuppressLint("ScheduleExactAlarm")
private fun setAlarm(millisTime: Long, str: String){
val intent = Intent(this, AlarmReceiver::class.java)
intent.putExtra("Service1","Start")
val pendingIntent = PendingIntent.getBroadcast(
applicationContext,
2407,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
if(str == "Start"){
binding.remainderTime.visibility = View.VISIBLE
if(alarmManager.canScheduleExactAlarms()){
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
millisTime,
pendingIntent
)
Toast.makeText(this,"Alarm set", Toast.LENGTH_SHORT).show()
}
}
else if(str == "Stop") {
alarmManager.cancel(pendingIntent)
binding.card2.visibility = View.GONE
}
}
private fun cancelAlarm(){
val intent = Intent(this, AlarmReceiver::class.java)
intent.putExtra("Service1","Stop")
val pendingIntent = PendingIntent.getBroadcast(applicationContext, 2407, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
alarmManager.cancel(pendingIntent)
binding.card2.visibility = View.GONE
Toast.makeText(this, "Alarm canceled", Toast.LENGTH_SHORT).show()
}
}
AlarmReceiver.kt
package com.example.a22012011085_pr4
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.media.MediaPlayer
import android.provider.ContactsContract.CommonDataKinds.Note
import android.util.Log
class AlarmReceiver : BroadcastReceiver() {
@SuppressLint("UnsafeProtectedBroadcastReceiver")
override fun onReceive(context: Context, intent: Intent) {
val str1 = intent.getStringExtra("Service1")
Log.d("AlarmBroadcastReceiver", "str1 value: $str1")
val serviceIntent = Intent(context, AlarmService::class.java)
if (str1 == "Start") {
context.startService(serviceIntent)
Log.d("AlarmReceiver", "Starting AlarmService")
serviceIntent.putExtra("Service1", intent.getStringExtra("Service1"))
}
else if (str1 == "Stop") {
context.stopService(serviceIntent)
Log.d("AlarmReciver","Stopping Alarm ")
}
}
}
AlarmService.kt
package com.example.a22012011085_pr4
import android.app.Service
import android.content.Intent
import android.media.MediaPlayer
import android.os.IBinder
import android.util.Log
class AlarmService : Service() {
private var mp: MediaPlayer? = null
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val action = intent?.getStringExtra("Service1")
Log.d("AlarmService", "Received Action: $action")
if(action == "Start"){
if (mp == null){
mp = MediaPlayer.create(this,R.raw.alarm)
mp?.isLooping = true
mp?.start()
Log.d("AlarmService", "Alarm Started")
}
}else if(action == "Stop"){
mp?.stop()
mp?.release()
mp = null
Log.d("AlarmService", "Alarm Stopped")
stopSelf()
}
return START_STICKY
}
override fun onDestroy() {
mp?.stop()
mp?.release()
mp = null
Log.d("AlarmService", "Service Destroyed")
super.onDestroy()
}
}
I tried to check logs also but it seems like it isn't logging the message, I'm completely clueless why this is happening, any sort of help, advice, or tip would be appreciated. Thank you
Anyone facing same problem,and if there's no error in code all you need to do is go to: Settings > Alarms and Reminders > Allow access to your app