Ich verbinde den CallScreeningServcie mithilfe von Messenger mit der MainActivity. Die Kommunikation zwischen Main und Service funktioniert von beiden Seite her ausgelöst problemlos. Wenn jedoch das erste Call-Ereignis, z.B. "ringing" geschieht, erscheint im Log eine RuntimeException, aus der ich nicht schlau werden und nicht sehen kann, was am Interface inkorrekt ist. Ich wäre dankbar, wenn mir jemand weiterhelfen kann.
Logcat:
2023-08-24 11:56:23.379 6731-6749 Parcel com.example.anrufdemo3 W **** enforceInterface() expected 'android.os.IMessenger' but read 'com.android.internal.telecom.ICallScreeningService'
2023-08-24 11:56:23.380 6731-6749 Binder com.example.anrufdemo3 W Caught a RuntimeException from the binder stub implementation.
java.lang.SecurityException: Binder invocation to an incorrect interface
at android.os.Parcel.nativeEnforceInterface(Native Method)
at android.os.Parcel.enforceInterface(Parcel.java:623)
at android.os.IMessenger$Stub.onTransact(IMessenger.java:79)
at android.os.Binder.execTransactInternal(Binder.java:1021)
at android.os.Binder.execTransact(Binder.java:994)
MyCallScreening.kt
package com.example.anrufdemo3
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.os.Message
import android.os.Messenger
import android.os.SystemClock
import android.telecom.Call
import android.telecom.CallScreeningService
import android.util.Log
const val TEL_PREFIX = "tel:"
const val MSG_CSS_RC = 0
const val MSG_CSS_IN = 1
const val MSG_CSS_OUT = 2
const val MSG_CSS_END = 3
const val MSG_CSS_DAT = 4
const val MSG_CSS_ASY = 5
class MyCallScreening: CallScreeningService() {
private lateinit var mCallDetails: Call.Details //temporary fix for future later use
private val mClients: ArrayList<Messenger> = ArrayList()
private lateinit var messenger: Messenger
override fun onBind(intent: Intent): IBinder? {
messenger = Messenger(IncomingHandler(mClients))
return messenger.binder
}
override fun onScreenCall(callDetails: Call.Details) {
mCallDetails = callDetails
Log.i("onScreenCall Service", callDetails.toString())
if (mClients.size > 0) {
try {
val msg: Message = Message.obtain(null, MSG_CSS_DAT)
msg.arg1 = callDetails.callDirection
val b = Bundle()
b.putString("telNr", callDetails.handle.toString())
msg.data = b
mClients[0].send(msg)
} catch (ex: Exception) {
Log.e("onScreenCall Service", "$ex")
}
}
val response = CallResponse.Builder()
if (callDetails.callDirection == Call.Details.DIRECTION_INCOMING) {
response.apply {
setRejectCall(true)
setDisallowCall(true)
setSkipCallLog(false)
}
}
respondToCall(callDetails, response.build())
}
private class IncomingHandler(val clients: ArrayList<Messenger>):
Handler(Looper.getMainLooper()) {
private val timer = Handler(Looper.getMainLooper())
override fun handleMessage(msg: Message) {
when (msg.what) {
MSG_CSS_RC -> { // register client
clients.add(msg.replyTo)
Log.d("CSS incoming","init ${clients.size} $clients")
}
MSG_CSS_IN -> { // in out test
Log.d("CSS incoming","alive ${clients.size} $clients, ${msg.arg1}, ${msg.arg2}")
if (clients.size > 0) {
try {
msg.replyTo.send(Message.obtain(null, MSG_CSS_OUT, 6, 7))
} catch (ex: Exception) {
Log.e("onScreenCall Service", "$ex")
} // asynch out test
timer.postAtTime(asyMsg, SystemClock.uptimeMillis() + 500L)
}
}
MSG_CSS_END -> {
Log.d("CSS incoming","end ${clients.size} $clients")
}
else -> super.handleMessage(msg)
}
}
private val asyMsg = Runnable {
if (clients.size > 0) {
try {
clients[0].send(Message.obtain(null, MSG_CSS_ASY, 8,9 ))
} catch (ex: Exception) {
Log.e("onScreenCall asynch", "$ex")
}
}
}
}// val abc: (Int) -> Unit = {}
}
Alles anzeigen
Ausschitte aus Main:
class MainActivity : AppCompatActivity() {
private var msgService: Messenger? = null
private val messenger = Messenger(IncomingHandler())
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
msgService = Messenger(service)
msgService?.let {
try { // register the Messenger(IncomingHandler()) for CallScreeningService events
val msg = Message.obtain(null, MSG_CSS_RC,0,0)
msg.replyTo = messenger
it.send(msg)
} catch (ex: Exception) {
Log.d("Main Init CSS","$ex")
}
}
B.buCall.isEnabled = true
}
override fun onServiceDisconnected(name: ComponentName) {
msgService = null
}
}
.......
private fun startService() {
intent = Intent(this, MyCallScreening::class.java)
if (roleManager.isRoleHeld(RoleManager.ROLE_CALL_SCREENING))
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
override fun onDestroy() {
super.onDestroy()
msgService?.let { unbindService(connection) }
msgService = null
}
Alles anzeigen