androidalarmmanagerandroid-alarms

Alarm is not ringing at the Time


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


Solution

  • 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