I am displaying one overlay view using Window Manager on incoming or outgoing call. When I receive one call my overlay window appears on screen but when I receive another call overlay window appears again on the previous displayng window and so on.

I am expecting to remove previously displaying overlay view when I receive call again and only display one overlay view at a time. Here is my WindowManager class.

class WindowManagerForNumber(private val context: Context) {
    private var mView: View? = null
    private var mParams: WindowManager.LayoutParams? = null
    private var mWindowManager: WindowManager? = null
    private var layoutInflater: LayoutInflater? = null
    private var bool: Boolean = false
    private var isWindowOpen = false
    private var callerNumber: String? = null
    private var callerName: String? = null
    private var dialogCallerSearchBinding: DialogCallerSearchBinding? = null
    private val scope = CoroutineScope(Job())

    init {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mParams = WindowManager.LayoutParams(
                WRAP_CONTENT,
                WRAP_CONTENT,
                TYPE_APPLICATION_OVERLAY,
                 FLAG_NOT_FOCUSABLE or FLAG_SHOW_WHEN_LOCKED,
                PixelFormat.TRANSLUCENT
            )
        }

        layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        layoutInflater?.let {
            dialogCallerSearchBinding =
                DialogCallerSearchBinding.inflate(it, null, false)

            mView = dialogCallerSearchBinding?.root
          //  mView?.isFocusableInTouchMode = true
           // mView?.requestFocus()
            /*mView?.setOnKeyListener { v,keyCode,event ->
                if(keyCode == KeyEvent.KEYCODE_BACK){
                    close()
                    return@setOnKeyListener true
                }
             return@setOnKeyListener   false
            }*/

            dialogCallerSearchBinding?.apply {
                tvCallingName.text = callerName
                tvCallingNumber.text = callerNumber
                ivClose.onClickListener {
                    close()
                }
            }

            mParams?.gravity = Gravity.CENTER
            mWindowManager = context.getSystemService(WINDOW_SERVICE) as WindowManager
        }
    }

    fun setData(
        name: String,
        number: String?,
        appRepository: ApplicationRepository,
        isDataSet: (Boolean) -> Unit
    ) {
        scope.launch(Dispatchers.Main) {
            dialogCallerSearchBinding?.apply {
                number?.let {
                    when (val data = appRepository.fetchContactData(it)) {
                        is ResultOfResponse.ResponseEmpty -> {
                            progressBar.isVisible = false
                            contactDetail.isVisible = true
                            tvCallingName.text =
                                context.resources.getString(R.string.no_name_found)
                            tvCountryName.isVisible = false
                            tvCallingNumber.text = number
                            isDataSet(true)
                        }
                        is ResultOfResponse.ResponseError -> {
                            progressBar.isVisible = false
                            contactDetail.isVisible = true
                            tvCallingName.text =
                                context.resources.getString(R.string.no_name_found)
                            tvCountryName.isVisible = false
                            tvCallingNumber.text = number
                            isDataSet(true)
                        }
                        ResultOfResponse.ResponseLoading -> {

                        }
                        is ResultOfResponse.ResponseSuccess -> {
                            progressBar.isVisible = false
                            contactDetail.isVisible = true
                            tvCountryName.isVisible = true
                            tvCallingName.text = data.data.ContactName
                            tvCallingNumber.text = data.data.ContactUuid
                            tvCountryName.text = data.data.ContactCountry
                                dialogCallerSearchBinding?.ivContactImage?.let { it1 ->
                                    appRepository.fetchContactImage(
                                        it,
                                        it1, name
                                    )
                                }

                            isDataSet(true)
                        }
                    }
                }
                /*if (name.contentEquals(PRIVATE_NUMBER)) {
                    progressBar.isVisible = false
                    contactDetail.isVisible = true
                    tvCallingName.text = PRIVATE_NUMBER
                    tvCountryName.visibility = View.INVISIBLE
                    tvCallingNumber.text = number
                    isDataSet(true)
                } else {


                }*/
            }
        }
       // hideView()
    }

    fun open() {
        try {
            
            if (mView?.windowToken == null) {
                if (mView?.parent == null) {
                    mWindowManager?.addView(mView, mParams)
                    bool = true
                    setDialogWindowStatus(true)

                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

     fun close() {
        if (bool) {
            mWindowManager?.removeView(mView)
            mView?.invalidate()
            bool = false
            setDialogWindowStatus(false)
            Log.i("check", "isWindowOpenInClose =$isWindowOpen")

            dialogCallerSearchBinding?.apply {
                tvCallingName.text = null
                tvCountryName.text = null
                tvCallingNumber.text = null
            }
        }
    }

Now if I receive 5 calls I have to click my imageView 5 times to close all overlay windows. Appreciate your efforts in advance.

1

There are 1 answers

1
Rahim Virani On

You are creating new view everytime you get the events i would suggest you to use the same and just change the data whenever you get new events.

For your answer you view is intialised as null so when inflating new view you can check if your view is already intialised then you can remvove it from windowManageer and then reinitialise it .

 dialogCallerSearchBinding =
            DialogCallerSearchBinding.inflate(it, null, false)

        mView = dialogCallerSearchBinding?.root

instead do this

windowManager?.let{
view?.let{
 windowManager?.removeView(it)
 view =null;
 view = mView = dialogCallerSearchBinding?.root
}
}

that way you can remove your previously added view and have new one !