I am using CallScreenService Api to detect call and show window on incoming and outgoing calls, but I want to close my overlay dialog window when calls ends or decline.
Here is my code for CallScreenService.class
class AppService : CallScreeningService() {
@Inject
lateinit var applicationRepository: ApplicationRepository
@Inject
lateinit var telephonyManager: TelephonyManager
private val windowManagerForNumber by lazy {
WindowManagerForNumber(this)
}
private var finalPhoneNumb: String? = ""
private val callerName: String?
get() = finalPhoneNumb?.let {
applicationRepository.fetchNameFromPhoneNumber(
it
)
}
private val notificationManagerImpl = NotificationManagerImpl()
private val notification by lazy {
com.example.truecaller.calling_app.utils.notification.Notification(this)
}
companion object {
fun startService(context: Context) {
Intent(context, TrueCallerAppService::class.java).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(context, this)
} else {
context.startService(this)
}
}
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
startNotification()
return START_STICKY
}
override fun onScreenCall(p0: Call.Details) {
val number = getPhoneNumber(p0)
var callResponse = CallResponse.Builder()
callResponse = handlePhoneCall(callResponse, number)
respondToCall(p0, callResponse.build())
}
private fun handlePhoneCall(
response: CallResponse.Builder,
phoneNumber: String
): CallResponse.Builder {
if (phoneNumber == FORBIDDEN_PHONE_CALL_NUMBER) {
response.apply {
setRejectCall(true)
setDisallowCall(true)
setSkipCallLog(false)
}
} else {
if (Settings.canDrawOverlays(this)) {
finalPhoneNumb = phoneNumber
if (PhoneNumberValidCheck.checkValidPhoneNumber(phoneNumber)) {
displayToast(phoneNumber)
Log.e("phone", "handlePhoneCall: $phoneNumber")
}
}
}
return response
}
private fun startNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(notification.notificationId, notification.createNotification())
} else {
startForeground(
notification.notificationId,
android.app.Notification()
)
}
isForeGroundService = true
}
private fun displayToast(message: String) {
try {
val countryCodeOfNumber = telephonyManager.simCountryIso.toString()
val phoneNumberUtil = PhoneNumberUtil.getInstance()
val phoneNumber: Phonenumber.PhoneNumber =
phoneNumberUtil.parse(message, countryCodeOfNumber.uppercase(Locale.ENGLISH))
val incomingNumber = phoneNumberUtil.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164)
notificationManagerImpl.appRepo(applicationRepository, windowManagerForNumber, incomingNumber)
} catch (e: Exception) {
e.printStackTrace()
}
}
Here is my WindowManagerClass
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 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(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.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 {
}*/
}
}
}
fun open() {
try {
if (mView?.windowToken == null) {
if (mView?.parent == null) {
mWindowManager?.addView(mView, mParams)
bool = true
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
fun close() {
if (bool) {
mWindowManager?.removeView(mView)
mView?.invalidate()
bool = false
dialogCallerSearchBinding?.apply {
tvCallingName.text = null
tvCountryName.text = null
tvCallingNumber.text = null
}
}
}
}
I am using WindowManager for showing overlay dialog window and closing window when user click "x" (cross imageView) but I want to close window when call ends or decline.