stopservice does not work after ondestroy

22 views Asked by At

I am developing an application that listens to a streamed audio. In the following code, when I first open the application, the stop and start service functions work fine, but when I exit the application using the back button and return, the stop and stop service functions do not work. Actually, the notification disappears and reappears correctly, but the audio stream continues. Additionally, when I checked with logs, there is no problem here, onDestroy in the service class is triggered when I press the stop button, but it continues to listen to the audio. Here is my codes:

MainActivity:

class MainActivity : ComponentActivity() {
    private var isListening = false
    private lateinit var audioTrack: AudioTrack
    private var sampleRate = Constants.SAMPLE_RATE
    private val channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO
    private val audioFormat = AudioFormat.ENCODING_PCM_16BIT
    private var bufferSize = (sampleRate / 10.0).roundToInt()
    private lateinit var listenButton: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS), 0)
            return
        }

        initializeListenButton()

        TouristService.isServiceRunning.observe(this, Observer { isRunning ->
            updateBroadcastButtonText(listenButton, isRunning)
            isListening = isRunning
            Log.d("Mesaj: ", "observe isListening: $isListening")
            Log.d("Mesaj: ", "observe isRunnnig: $isRunning")
        })
    }

    private fun initializeListenButton() {
        listenButton = findViewById(R.id.listen_button)
        listenButton.setOnClickListener {
            isListening = !isListening
            Log.d("Mesaj: ", "setOnClick isListening: $isListening")
            initializeAudioTrack()
            if (isListening) {
                startService(Intent(this, TouristService::class.java))
                GlobalScope.launch(Dispatchers.Default) {
                    try {
                        withContext(Dispatchers.IO) {
                            val group: InetAddress = InetAddress.getByName(Constants.HOST)
                            val socket = MulticastSocket(Constants.PORT)
                            socket.joinGroup(group)

                            audioTrack.play()
                            Log.d("Mesaj: ", "audioTrack.play")

                            val buffer = ByteArray(bufferSize)
                            var lastChecksum: Int? = null
                            while (audioTrack.playState == AudioTrack.PLAYSTATE_PLAYING) {
                                val packet = DatagramPacket(buffer, buffer.size)
                                socket.receive(packet)

                                val checksum = packet.data.sumOf { it.toInt() }
                                if (checksum == lastChecksum) {
                                    continue
                                }
                                lastChecksum = checksum

                                audioTrack.write(packet.data, 0, packet.length)
                            }

                            socket.leaveGroup(group)
                            socket.close()
                        }
                    } catch (e: Exception) {
                        Toast.makeText(this@MainActivity, getString(R.string.error_while_listening) + e.message, Toast.LENGTH_SHORT).show()
                    }

                    audioTrack.stop()
                    Log.d("Mesaj: ", "audioTrack.stop")
                    audioTrack.release()
                }
            } else {
                audioTrack.stop()
                Log.d("Mesaj: ", "audioTrack.stop on else")
                stopService(Intent(this, TouristService::class.java))
            }
        }
    }

    private fun initializeAudioTrack() {
        audioTrack = AudioTrack.Builder()
            .setAudioAttributes(
                AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                    .build())
            .setAudioFormat(AudioFormat.Builder()
                .setEncoding(audioFormat)
                .setSampleRate(sampleRate)
                .setChannelMask(channelConfig)
                .build())
            .setBufferSizeInBytes(bufferSize)
            .setTransferMode(AudioTrack.MODE_STREAM)
            .setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY)
            .build()
    }

private fun updateBroadcastButtonText(button: Button, isRunning: Boolean) {
    button.text = if (isRunning) getString(R.string.stop_listening) else getString(R.string.start_listening)
}

Service:

class TouristService : Service() {

companion object {
    val isServiceRunning = MutableLiveData<Boolean>()
}

override fun onBind(intent: Intent?): IBinder? {
    return null
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    createNotificationChannel()
    val notificationIntent = Intent(this, MainActivity::class.java)
    val pendingIntentFlags =
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, pendingIntentFlags)
    val notification = NotificationCompat.Builder(this, CHANNEL_ID)
        .setContentTitle(getString(R.string.app_name))
        .setContentText(getString(R.string.receiving_audio))
        .setSmallIcon(R.drawable.ic_launcher_foreground)
        .setContentIntent(pendingIntent)
        .build()
    startForeground(1, notification)
    Log.d("Mesaj: ", "startForeground")

    // Start recording audio

    isServiceRunning.postValue(true)
    return START_NOT_STICKY
}

override fun onDestroy() {
    super.onDestroy()
    Log.d("Mesaj: ", "Service ondestroy")

    // Stop recording audio
    isServiceRunning.postValue(false)
    stopForeground(true)
}

override fun onTaskRemoved(rootIntent: Intent?) {
    super.onTaskRemoved(rootIntent)

    // Stop recording audio

    Log.d("Mesaj: ", "Service onTaskRemoved")
    isServiceRunning.postValue(false)
    stopForeground(true)
}

private fun createNotificationChannel() {
    val serviceChannel = NotificationChannel(
        CHANNEL_ID,
        "Tourist Service Channel",
        NotificationManager.IMPORTANCE_DEFAULT
    )
    val manager = getSystemService(NotificationManager::class.java)
    manager.createNotificationChannel(serviceChannel)
}
}
0

There are 0 answers