Hello, I am so confused with this. I clicked the Start Button to run the service, and then I clicked Stop Button to stop the service and broadcast data back to MainActivity. The first click of the Stop Button resulted in the Toast only displayed null value, but when I clicked it again (without reclicking Start Button), it displayed the correct broadcasted text. Why? Please help. Thank you.
My codes:
in MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val start: Button = findViewById(R.id.startButton)
val stop: Button = findViewById(R.id.stopButton)
start.setOnClickListener {
NewService.startService(this, "My application")
}
var testData: String? = null
stop.setOnClickListener {
val tokenPassingReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val bundle = intent.extras
if (bundle != null) {
if (bundle.containsKey("testData")) {
testData = bundle.getString("testData")!!
}
}
}
}
NewService.stopService(this)
LocalBroadcastManager.getInstance(this)
.registerReceiver(tokenPassingReceiver, IntentFilter("dataBroadcast"))
Toast.makeText(this, testData, Toast.LENGTH_SHORT).show()
}
}
}
in NewService.kt
.class NewService : Service() {
private val CHANNEL_ID = "My Application"
// declaring object of MediaPlayer
private lateinit var alarmSound: Ringtone
private lateinit var timer: CountDownTimer
private lateinit var pendingIntent: PendingIntent
private var alarmOn: Boolean = false
private var timerOn: Boolean = false
companion object {
fun startService(context: Context, message: String) {
val startIntent = Intent(context, NewService::class.java)
startIntent.putExtra("inputExtra", message)
ContextCompat.startForegroundService(context, startIntent)
}
fun stopService(context: Context) {
val stopIntent = Intent(context, NewService::class.java)
context.stopService(stopIntent)
}
}
// execution of service will startz
// on calling this method
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
//do heavy work on a background thread
val input = intent?.getStringExtra("inputExtra")
createNotificationChannel()
val notificationIntent = Intent(this, MainActivity::class.java)
pendingIntent = PendingIntent.getActivity(
this,
0, notificationIntent, 0
)
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("My Application timer: ")
.setContentText(input)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setTicker(input)
.setOnlyAlertOnce(true)
.build()
startForeground(1, notification)
countDown(60000, this)
return START_STICKY
}
// execution of the service will
// stop on calling this method
override fun onDestroy() {
super.onDestroy()
// stopping the process
val intent = Intent("dataBroadcast")
intent.putExtra("testData", "This string is passed from service to MainActivity")
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
if (timerOn) {
timer.cancel()
}
if (alarmOn) {
if (alarmSound.isPlaying) {
alarmSound.stop()
alarmOn = false
}
}
}
override fun onBind(intent: Intent): IBinder? {
return null
}
private fun countDown(start: Long, context: Context) {
timer = object : CountDownTimer(start, 1000) {
override fun onTick(millisUntilFinished: Long) {
var ms = millisUntilFinished + 1
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("My Application timer: ")
.setContentText("Countdown: " + (ms / 1000).toString())
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setTicker("Countdown: " + (ms / 1000).toString())
.build()
startForeground(1, notification)
}
override fun onFinish() {
val alarm = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
alarmSound = RingtoneManager.getRingtone(applicationContext, alarm)
alarmSound.isLooping = true
alarmSound.play()
alarmOn = true
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("My Application timer: ")
.setContentText("Alarm on")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setTicker("Alarm on")
.build()
startForeground(1, notification)
}
}
timerOn = true
timer.start()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val serviceChannel = NotificationChannel(
CHANNEL_ID, "Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
)
val manager = getSystemService(NotificationManager::class.java)
manager!!.createNotificationChannel(serviceChannel)
}
}
}