Chirag Patel
Chirag Patel

Reputation: 467

forground service destroy on minimize app

I am developing an audio player app that works well but I am facing one problem if I minimize the app it kill my foreground service. I don't know why it's happening can anyone suggest me any solution

MainActivity

import android.Manifest
import android.app.PendingIntent
import android.content.*
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.support.v4.media.MediaDescriptionCompat
import android.support.v4.media.MediaMetadataCompat
import android.support.v4.media.session.MediaSessionCompat
import android.text.Html
import android.util.Log
import android.view.WindowManager
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.brahmakumaris.fragment.*
import com.brahmakumaris.model.getDashboard.RecentSong
import com.brahmakumaris.service.MusicPlayerService
import com.brahmakumaris.service.MyService
import com.brahmakumaris.util.*
import com.google.android.exoplayer2.DefaultLoadControl
import com.google.android.exoplayer2.ExoPlaybackException
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
import com.google.android.exoplayer2.source.ConcatenatingMediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
import kotlin.collections.ArrayList

class MainActivity : AppCompatActivity(), OnFragmentInteractionListener {

    override fun onFragmentInteraction(screen: String, model: RecentSong, songList: ArrayList<RecentSong>, position: Int) {
        MyLog.e(TAG, screen)
        when (screen) {
            getString(R.string.speakers) -> {
                bottom_navigation.selectedItemId = R.id.nav_speaker
                supportFragmentManager.switch(
                    newFrag = SpeakerPageFragment.newInstance(),
                    tag = getString(R.string.speakers)
                )
            }
            getString(R.string.classes) -> {
                bottom_navigation.selectedItemId = R.id.nav_class
                supportFragmentManager.switch(
                    newFrag = ClassesPageFragment.newInstance(),
                    tag = getString(R.string.classes)
                )
            }
            getString(R.string.songs) -> {
                bottom_navigation.selectedItemId = R.id.nav_song
                supportFragmentManager.switch(
                    newFrag = SongsPageFragment.newInstance(),
                    tag = getString(R.string.songs)
                )
            }
            getString(R.string.play_song) -> {
                if(!model.name.isNullOrBlank()) {
                    songPosition = position
                    mSongList = songList
                    MyLog.e(TAG, "======= ${getString(R.string.play_song)} ${model.name}")
                    isPlaying = false       // to start new song
                    // play song
                    if (!lnPlayer.isVisible) {
                        lnPlayer.isVisible = true
                    }

                    titleTxt.setHtmlText(model.name)

                    if(mBound) {
                        startService()
                        mMusicPlayerService.playSong(mSongList,songPosition)
                        media_button.setImageResource(R.drawable.ic_pause_black_24dp)
                    }
                    setPlayPause(!mMusicPlayerService.isPlaying())
                    initSeekBar()
                }
            }
            else -> {
            }
        }
    }
    private val TAG = javaClass.simpleName
    private var isPlaying = false
    private var mediaSource: ProgressiveMediaSource? = null
    // notification
    private lateinit var mediaSessionConnector: MediaSessionConnector
    private lateinit var mediaSession: MediaSessionCompat
    private lateinit var playerNotificationManager: PlayerNotificationManager

    private var handler: Handler? = null
    private val dashUrl = "http://www.panacherock.com/downloads/mp3/01_All_Tangled_Up.mp3"
    var mSongList: ArrayList<RecentSong> = ArrayList()
    var songPosition = 0


    val MESSAGE_KEY = "message_key"
    private lateinit var mMusicPlayerService:MusicPlayerService
    private lateinit var mPlayer: SimpleExoPlayer
    private var mBound = false

    private val mServiceConnection: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
            val binder = iBinder as MusicPlayerService.MyServiceBinder
            mMusicPlayerService = binder.getService()
            mPlayer = mMusicPlayerService.getPlayerInstance()!!
            mPlayer.addListener(playerListener)

            mBound = true
            MyLog.e(TAG,"onServiceConnected: ")
        }

        override fun onServiceDisconnected(componentName: ComponentName) {
            mBound = false
            MyLog.e(TAG,"onServiceDisconnected: ")  // calles only in rare case if service destroy unexpectedly
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        if (savedInstanceState == null) {

            supportFragmentManager.switch(
                newFrag = DashboardPageFragment.newInstance(),
                tag = getString(R.string.home)
            )
        }
        getIntentData()
        bottom_navigation.setOnNavigationItemSelectedListener { item ->
            hideKeybord()
            when(item.itemId) {
                R.id.nav_home -> {
                    checkFragment()
                    supportFragmentManager.switch(
                        newFrag = DashboardPageFragment.newInstance(),
                        tag = getString(R.string.home)
                    )
                    true
                }
                R.id.nav_song -> {
                    checkFragment()
                    supportFragmentManager.switch(
                        newFrag = SongsPageFragment.newInstance(),
                        tag = getString(R.string.songs)
                    )
                    true
                }
                R.id.nav_speaker -> {
                    checkFragment()
                    supportFragmentManager.switch(
                        newFrag = SpeakerPageFragment.newInstance(),
                        tag = getString(R.string.speakers)
                    )
                    true
                }
                R.id.nav_class -> {
                    checkFragment()
                    supportFragmentManager.switch(
                        newFrag = ClassesPageFragment.newInstance(),
                        tag = getString(R.string.classes)
                    )
                    true
                }
                R.id.nav_search -> {
                    checkFragment()
                    supportFragmentManager.switch(
                        newFrag = SearchPageFragment.newInstance(),
                        tag = getString(R.string.search)
                    )
                    true
                }
                else -> false
            }

        }

        bottom_navigation.setOnNavigationItemReselectedListener {  }    //disable reselection tab

        media_button.setOnClickListener {
           // startService()
            setPlayPause(!isPlaying)
        }

        imgClose.setOnClickListener {
            isPlaying = true       // to stop song
            playerNotificationManager.setPlayer(null)
            setPlayPause(!isPlaying)
            if (lnPlayer.isVisible) {
                lnPlayer.isVisible = false
            }
        }
    }

    private fun getIntentData() {
        if (intent!=null && intent.hasExtra("internet") && !intent.getBooleanExtra("internet", false)) {
            this.changeFragment(
                DownloadPageFragment.newInstance(), Constants.DOWNLOAD_TAG
            )
        }
    }



    private fun checkFragment() {
        val fragment = getSupportFragmentManager().findFragmentByTag(Constants.SUB_CATEGORY_TAG)
        if (fragment != null) {
            getSupportFragmentManager().beginTransaction().remove(fragment).commit()
        }
        val fragment2 = getSupportFragmentManager().findFragmentByTag(Constants.DOWNLOAD_TAG)
        if (fragment2 != null) {
            getSupportFragmentManager().beginTransaction().remove(fragment2).commit()
        }
    }

    private val playerListener by lazy {
        object : Player.EventListener {
            override fun onPlayerError(error: ExoPlaybackException) {
                super.onPlayerError(error)
                //onError(error)
            }

            override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
                super.onPlayerStateChanged(playWhenReady, playbackState)
                when (playbackState) {
                    Player.STATE_BUFFERING -> Log.e(TAG,"STATE_BUFFERING")
                    Player.STATE_ENDED -> Log.e(TAG,"STATE_ENDED")
                    Player.STATE_IDLE -> Log.e(TAG,"STATE_IDLE")
                    Player.STATE_READY -> {
//                        setPlayPause(playWhenReady)
                        isPlaying = playWhenReady
                        mPlayer.setPlayWhenReady(playWhenReady)
                        if (!isPlaying) {
                            media_button.setImageResource(R.drawable.ic_play_arrow_black_24dp)
                        } else {
                            setProgress()
                            media_button.setImageResource(R.drawable.ic_pause_black_24dp)
                        }
                        if (playWhenReady) {
                            Log.e(TAG, "PlaybackStatus.PLAYING")
                        } else {
                            Log.e(TAG, "PlaybackStatus.PAUSED")
                        }
                        titleTxt.setHtmlText(mSongList[mPlayer.currentWindowIndex].name)
                        MyLog.e(TAG, "====== " + mSongList[mPlayer.currentWindowIndex].name)
                        MyLog.e(TAG, "======111 " + mSongList[mPlayer.currentWindowIndex].descripation)
                    }
                    else -> Log.e(TAG, "PlaybackStatus.IDLE")
                }

            }
        }
    }

    private fun startService() {
        val myService = Intent(this, MusicPlayerService ::class.java)
        Util.startForegroundService(this,myService)
    }

    private fun stopService() {
        val myService = Intent(this, MusicPlayerService ::class.java)
        stopService(myService)
    }


    private fun setPlayPause(play: Boolean) {
        if(mBound) {
            if(mMusicPlayerService.isPlaying()) {
                mMusicPlayerService.pause()
                media_button.setImageResource(R.drawable.ic_play_arrow_black_24dp)
            } else {
                startService()
                playerNotificationManager = mMusicPlayerService.getNotificationInstance()!!
                /* if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                     startForegroundService(intent)
                 } else {
                     startService(intent)
                 }*/
                mMusicPlayerService.play()
                setProgress()
                media_button.setImageResource(R.drawable.ic_pause_black_24dp)
            }
        }

        /*isPlaying = play
        exoPlayer.setPlayWhenReady(play)
        if (!isPlaying) {
            media_button.setImageResource(R.drawable.ic_play_arrow_black_24dp)
        } else {
            setProgress()
            media_button.setImageResource(R.drawable.ic_pause_black_24dp)
        }*/
    }

    private fun stringForTime(timeMs: Int): String {
        val mFormatBuilder: StringBuilder
        val mFormatter: Formatter
        mFormatBuilder = StringBuilder()
        mFormatter = Formatter(mFormatBuilder, Locale.getDefault())
        val totalSeconds = timeMs / 1000

        val seconds = totalSeconds % 60
        val minutes = totalSeconds / 60 % 60
        val hours = totalSeconds / 3600

        mFormatBuilder.setLength(0)
        return if (hours > 0) {
            mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
        } else {
            mFormatter.format("%02d:%02d", minutes, seconds).toString()
        }
    }

    private fun setProgress() {
        seekPlayerProgress.progress = 0
        seekPlayerProgress.max = mPlayer.getDuration().toInt() / 1000
        position.setText(stringForTime(mPlayer.getCurrentPosition().toInt()))
        duration.setText(stringForTime(mPlayer.getDuration().toInt()))

        if (handler == null) handler = Handler()
        //Make sure you update Seekbar on UI thread
        handler!!.post(object : Runnable {
            override fun run() {
                if (mPlayer != null && ::mPlayer.isInitialized && isPlaying) {
                    seekPlayerProgress.max = mPlayer.getDuration().toInt() / 1000
                    val mCurrentPosition = mPlayer.getCurrentPosition().toInt() / 1000
                    seekPlayerProgress.progress = mCurrentPosition
                    position.setText(stringForTime(mPlayer.getCurrentPosition().toInt()))
                    duration.setText(stringForTime(mPlayer.getDuration().toInt()))

                    handler!!.postDelayed(this, 1000)
                }
            }
        })
    }

    private fun initSeekBar() {
        seekPlayerProgress.requestFocus()

        seekPlayerProgress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                if (!fromUser) {
                    // We're not interested in programmatically generated changes to
                    // the progress bar's position.
                    return
                }

                mPlayer.seekTo((progress * 1000).toLong())
            }

            override fun onStartTrackingTouch(seekBar: SeekBar) {

            }

            override fun onStopTrackingTouch(seekBar: SeekBar) {

            }
        })

        seekPlayerProgress.setMax(0)
        seekPlayerProgress.setMax(mPlayer.getDuration().toInt() / 1000)

    }

    private var doubleBackToExitPressedOnce = false

    override fun onBackPressed() {
        val fragment = getSupportFragmentManager().findFragmentByTag(Constants.SUB_CATEGORY_TAG)
        if (fragment != null) {
            getSupportFragmentManager().beginTransaction().remove(fragment).commit()
            return
        }
        val fragment2 = getSupportFragmentManager().findFragmentByTag(Constants.DOWNLOAD_TAG)
        if (fragment2 != null) {
            getSupportFragmentManager().beginTransaction().remove(fragment2).commit()
            return
        }
        if (doubleBackToExitPressedOnce) {
            super.onBackPressed()
            return
        }

        this.doubleBackToExitPressedOnce = true
        this.showSnackBarToast("Please click BACK again to exit")

        Handler().postDelayed(Runnable { doubleBackToExitPressedOnce = false }, 2000)
    }

    override fun onDestroy() {
        if(::playerNotificationManager.isInitialized) {
            playerNotificationManager.setPlayer(null)
        }
        killPlayer()
//        stopService()
        MyLog.e(TAG," #### onDestroy #### ")
        super.onDestroy()
    }

    override fun onStop() {
        super.onStop()
        if(mBound) {
            unbindService(mServiceConnection)
            mBound = false
        }
        LocalBroadcastManager.getInstance(this)
            .unregisterReceiver(broadCastReceiver)
        MyLog.e(TAG," #### onStop #### ")
    }

     private fun killPlayer() {
        if (mPlayer != null) {
            mPlayer.release()
            mediaSource = null
        }
         MyLog.e(TAG,"#### killPlayer ####")
    }


    private fun getHtmlText(str:String):String {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return (Html.fromHtml(str, Html.FROM_HTML_MODE_COMPACT)).toString()
        } else {
            return (Html.fromHtml(str)).toString()
        }
    }

    private fun setMediaSession() {
        mediaSession = MediaSessionCompat(this@MainActivity,"MEDIA_SESSION_TAG")
        mediaSession.isActive = true
        playerNotificationManager.setMediaSessionToken(mediaSession.sessionToken)   //enhance media stye notification and provide artwork in lock screen
        mediaSessionConnector = MediaSessionConnector(mediaSession)
        //timeline is the internal representation of the pllaylist after the player has been prepared
        mediaSessionConnector.setQueueNavigator(object : TimelineQueueNavigator(mediaSession){
            override fun getMediaDescription(player: Player?, windowIndex: Int): MediaDescriptionCompat {
                return getMediaDescriptionData(this@MainActivity, mSongList[windowIndex])
            }

        })
        mediaSessionConnector.setPlayer(exoPlayer/*, null*/)   //sync player wth media session

    }

    fun getMediaDescriptionData(context: Context, sample: RecentSong): MediaDescriptionCompat {
        val extras = Bundle()
        val options = BitmapFactory.Options()
        options.inSampleSize = 8

//        val bitmap = BitmapFactory.decodeFile(getBitmap(context, sample.bitmapResource), options)
        val bitmap = context.getBitmap(R.drawable.bg)

        extras.putParcelable(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap)
        extras.putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, bitmap)
        return MediaDescriptionCompat.Builder()
            .setMediaId(sample.song)
            .setIconBitmap(bitmap)
            .setTitle(sample.name)
            .setDescription(sample.descripation)
            .setExtras(extras)
            .build()
    }

    override fun onStart() {
        super.onStart()
        bindService(Intent(this,MusicPlayerService::class.java),mServiceConnection,Context.BIND_AUTO_CREATE)
        LocalBroadcastManager.getInstance(this)
            .registerReceiver(broadCastReceiver, IntentFilter(MusicPlayerService().MUSIC_COMPLETED))
    }

    val broadCastReceiver = object : BroadcastReceiver() {
        override fun onReceive(contxt: Context?, intent: Intent?) {
            MyLog.e(TAG,"onReceive: ${intent?.getBooleanExtra(MESSAGE_KEY,false)}")
            if(intent!!.getBooleanExtra(MESSAGE_KEY,false)) {
                setPlayPause(intent.getBooleanExtra(MESSAGE_KEY,false))
                if (intent.getBooleanExtra(MESSAGE_KEY,false)) {
                    Log.e(TAG, "PlaybackStatus.PLAYING")
                } else {
                    Log.e(TAG, "PlaybackStatus.PAUSED")
                }
                titleTxt.setHtmlText(mSongList[mPlayer.currentWindowIndex].name)
                MyLog.e(TAG,"====== "+mSongList[mPlayer.currentWindowIndex].name)
                MyLog.e(TAG,"======111 "+mSongList[mPlayer.currentWindowIndex].descripation)
            }

        }
    }
}

MusicPlayerService

import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Binder
import android.os.IBinder
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.brahmakumaris.MainActivity
import com.brahmakumaris.R
import com.brahmakumaris.model.getDashboard.RecentSong
import com.brahmakumaris.util.MyLog
import com.brahmakumaris.util.getBitmap
import com.brahmakumaris.util.getPlaintextfromHtmlHtmlText
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
import com.google.android.exoplayer2.source.ConcatenatingMediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util

class MusicPlayerService : Service() {
    private val TAG = javaClass.simpleName
    private val mContext: Context = this
    private val mBinder = MyServiceBinder()
    val MUSIC_COMPLETED = "music completed"
    val mPlayer: SimpleExoPlayer by lazy { SimpleExoPlayer.Builder(this).build() }
    private lateinit var playerNotificationManager: PlayerNotificationManager
    var mSongList: ArrayList<RecentSong> = ArrayList()

    override fun onCreate() {
        super.onCreate()
        MyLog.d(TAG,"onCreate: ")

    }

    fun playSong(mSongList: ArrayList<RecentSong> = ArrayList(), position: Int = 0)/* mContext: Context = this*/ {
        this.mSongList = mSongList
        val dataSourceFactory = DefaultDataSourceFactory(mContext, Util.getUserAgent(mContext,getString(R.string.app_name)))

        val concateMediaSource = ConcatenatingMediaSource()
        for (i in mSongList) {
            val mediaSource = ProgressiveMediaSource
                .Factory(
                    DefaultDataSourceFactory(mContext, dataSourceFactory),
                    DefaultExtractorsFactory()
                )
                .createMediaSource(/*i.uri*/Uri.parse(i.musicFile))
            concateMediaSource.addMediaSource(mediaSource)
        }

        mPlayer.prepare(concateMediaSource)
        mPlayer.seekToDefaultPosition(position)
        mPlayer.playWhenReady =true

        setNotification()
    }

    private fun setNotification() {
        playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
            this,"channel_id",R.string.channelName,R.string.channelDescription,11,
            object : PlayerNotificationManager.MediaDescriptionAdapter{
                override fun createCurrentContentIntent(player: Player): PendingIntent? {
                    val intent = Intent(mContext, MainActivity::class.java)
                    return PendingIntent.getActivity(mContext,0,intent, PendingIntent.FLAG_UPDATE_CURRENT)
                }

                override fun getCurrentContentText(player: Player): String? {
//                    return mSongList[player.currentWindowIndex].descripation // descrption
                    return mSongList[player.currentWindowIndex].descripation.getPlaintextfromHtmlHtmlText() // descrption
                }

                override fun getCurrentContentTitle(player: Player): String {
//                    return mSongList[player.currentWindowIndex].name // title
                    return mSongList[player.currentWindowIndex].name.getPlaintextfromHtmlHtmlText()
                }

                override fun getCurrentLargeIcon(
                    player: Player,
                    callback: PlayerNotificationManager.BitmapCallback
                ): Bitmap? {
                    return mContext.getBitmap(R.drawable.bg)
                }

            } ,object : PlayerNotificationManager.NotificationListener {
             override fun onNotificationStarted(notificationId: Int, notification: Notification) {
                 startForeground(notificationId,notification)
             }
             override fun onNotificationPosted(notificationId: Int, notification: Notification, ongoing: Boolean) {
                 startForeground(notificationId,notification)
             }

             override fun onNotificationCancelled(notificationId: Int, dismissedByUser: Boolean) {
                 stopSelf()
             }

             override fun onNotificationCancelled(notificationId: Int) {
                 stopSelf()
             }
         }

        )

        //show hide button
        playerNotificationManager.setUseStopAction(false)  //stop song
        playerNotificationManager.setRewindIncrementMs(0)   //hide rewind button
        playerNotificationManager.setFastForwardIncrementMs(0)  //hide fast forward button
        playerNotificationManager.setPlayer(mPlayer)
    }


    inner class MyServiceBinder : Binder() {
        fun getService(): MusicPlayerService = this@MusicPlayerService
    }

    fun getPlayerInstance(): SimpleExoPlayer? {
        return mPlayer
    }

    fun getNotificationInstance(): PlayerNotificationManager? {
        return playerNotificationManager
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        MyLog.d(TAG,"onStartCommand: ")
        return START_NOT_STICKY
    }
    override fun onBind(intent: Intent?): IBinder? {
        MyLog.d(TAG,"onBind: ")
        return mBinder

    }

    override fun onUnbind(intent: Intent?): Boolean {
        MyLog.d(TAG,"onUnbind: ")
        return true
    }

    override fun onRebind(intent: Intent?) {
        MyLog.d(TAG,"onRebind: ")
        super.onRebind(intent)
    }
    override fun onDestroy() {
        MyLog.e(TAG,"onDestroy: ")
        super.onDestroy()
        mPlayer.release()
        if(::playerNotificationManager.isInitialized) {
            playerNotificationManager.setPlayer(null)
        }
    }

    // public client method
    fun isPlaying():Boolean {
        return mPlayer.isPlaying
    }

    fun play() {
        mPlayer.setPlayWhenReady(true)
    }

    fun pause() {
        mPlayer.setPlayWhenReady(false)
    }
}

if I minimize the app then it's printing unbind and then it directly going to onDestroy why it's happening can anyone help me,

Any Help Would Be Highly Appreciated.

Upvotes: 0

Views: 883

Answers (3)

oziomajnr
oziomajnr

Reputation: 1751

I experienced this issue because I set the player on notification manager to null on onStop which causes onNotificationCancelled to be called, you should check, if the notification was canceled by the user then you should stop the service, else leave it running.

override fun onNotificationCancelled(notificationId: Int, dismissedByUser:Boolean)  
  { 
       if (dismissedByUser) {
          stopSelf() 
        }
    }

Upvotes: 0

Chirag Patel
Chirag Patel

Reputation: 467

I just remove onStop unbind and unregister code and set in onDestroy and it's working for me.

Upvotes: 1

Amit Gupta
Amit Gupta

Reputation: 663

You should be using startForeground() with a notification, to Android service that never stops running.

startForeground(1, notification)

Please have a look at this. https://robertohuertas.com/2019/06/29/android_foreground_services/

I hope this will help you.

Upvotes: 0

Related Questions