2

The following code is from the project.

The Notification icon will be displayed when I launch bindService(), it's Ok.

But the Notification icon will not be cleaned when I launch unbindService(), why? I can't find any code to clean Notification icon in following code.

MainActivity.kt

class MainActivity : AppCompatActivity(), View.OnClickListener {
    val mTAG = MainActivity::class.java.simpleName
    // Variable for storing instance of our service class
    var mService: MyBoundService? = null

    // Boolean to check if our activity is bound to service or not
    var mIsBound: Boolean? = null

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

        startServiceButton?.setOnClickListener(this)
        stopServiceButton?.setOnClickListener(this)
        startActivityButton?.setOnClickListener(this)
    }


    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, iBinder: IBinder) {
            Log.d(mTAG, "ServiceConnection: connected to service.")
            // We've bound to MyService, cast the IBinder and get MyBinder instance
            val binder = iBinder as MyBinder
            mService = binder.service
            mIsBound = true
            getRandomNumberFromService() // return a random number from the service
        }

        override fun onServiceDisconnected(arg0: ComponentName) {
            Log.d(mTAG, "ServiceConnection: disconnected from service.")
            mIsBound = false
        }
    }

    /**
     * Method for listening to random numbers generated by our service class
     */
    private fun getRandomNumberFromService() {
        mService?.randomNumberLiveData?.observe(this
                , Observer {
            resultTextView?.text = "Random number from service: $it"
        })
    }

    override fun onDestroy() {
        super.onDestroy()
        // Unbinding to the service class
        unbindService()
    }


    private fun bindService() {
        Intent(this, MyBoundService::class.java).also { intent ->
            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }


    private fun unbindService() {
        Intent(this, MyBoundService::class.java).also { intent ->
            unbindService(serviceConnection)
        }
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.startServiceButton -> {
                bindService()
            }
            R.id.stopServiceButton -> {
                if (mIsBound == true) {
                    unbindService()
                    mIsBound = false
                }
            }
            R.id.startActivityButton -> {
                val intent = Intent(this, ResultActivity::class.java)
                startActivity(intent)
            }
        }
    }
}

MyBoundService.kt

class MyBoundService : Service() {
    ...

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

    override fun onCreate() {
        super.onCreate()
        Log.d("MyBoundService", "onCreate called")
        startNotification()

        Handler().postDelayed({
            val randomNumber = mGenerator.nextInt(100)
            randomNumberLiveData.postValue(randomNumber)
        }, 1000)
    }

  
    private fun startNotification() {
        val channel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel(
                    CHANNEL_ID,
                    "My Channel",
                    NotificationManager.IMPORTANCE_DEFAULT
            )
        } else {
            TODO("VERSION.SDK_INT < O")
        }
        (getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(channel)
        val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("A service is running in the background")
                .setContentText("Generating random number").build()
        startForeground(1, notification)
    }
}
ahasbini
  • 6,761
  • 2
  • 29
  • 45
HelloCW
  • 843
  • 22
  • 125
  • 310

2 Answers2

1

That is true, the code for MyBoundService calls startForeground() which allows MyBoundService to continue running even when MainActivity is destroyed or not in the foreground until the Android OS decides to stop MyBoundService for a reason like freeing up memory.

To stop MyBoundService and remove the notification, it needs to call stopForeground(true) and then stopSelf(). You could make this happen with the sample code you have by adding the below:

MainActivity.kt

    private fun unbindService() {
        Intent(this, MyBoundService::class.java).also { intent ->
            unbindService(serviceConnection)
            mService.stopForeground(true)
            mService.stopSelf()
        }
    }
ahasbini
  • 6,761
  • 2
  • 29
  • 45
1

You are starting a foreground service

Please check this link What is the proper way to stop a service running as foreground

Also, you may want to check Stopping a service

Sourabh Saldi
  • 3,567
  • 6
  • 34
  • 57