草庐IT

Android ConnectionService 来电

coder 2023-11-26 原文

我正在尝试在 Android 上实现 iOS callkit 行为。我收到来自 firebase 的推送通知,我想向用户显示“来电”屏幕。为此,我使用了 android.telecom 包和其他类中的 ConnectionService

这是我的调用管理器类:

class CallManager(context: Context) {
val telecomManager: TelecomManager
var phoneAccountHandle:PhoneAccountHandle
var context:Context
val number = "3924823202"
init {
    telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
    this.context = context
    val componentName =  ComponentName(this.context, CallConnectionService::class.java)
    phoneAccountHandle = PhoneAccountHandle(componentName, "Admin")
    val phoneAccount = PhoneAccount.builder(phoneAccountHandle, "Admin").setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED).build()


    telecomManager.registerPhoneAccount(phoneAccount)
    val intent = Intent()
    intent.component = ComponentName("com.android.server.telecom", "com.android.server.telecom.settings.EnableAccountPreferenceActivity")
    intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP

}


@TargetApi(Build.VERSION_CODES.M)
fun startOutgoingCall() {
    val extras = Bundle()
    extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true)

    val manager = context.getSystemService(TELECOM_SERVICE) as TelecomManager
    val phoneAccountHandle = PhoneAccountHandle(ComponentName(context.packageName, CallConnectionService::class.java!!.getName()), "estosConnectionServiceId")
    val test = Bundle()
    test.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle)
    test.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, VideoProfile.STATE_BIDIRECTIONAL)
    test.putParcelable(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras)
    try {
        manager.placeCall(Uri.parse("tel:$number"), test)
    } catch (e:SecurityException){
        e.printStackTrace()
    }
}

@TargetApi(Build.VERSION_CODES.M)
fun  startIncomingCall(){
    if (this.context.checkSelfPermission(Manifest.permission.MANAGE_OWN_CALLS) == PackageManager.PERMISSION_GRANTED) {
        val extras = Bundle()
        val uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null)
        extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri)
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle)
        extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true)
        val isCallPermitted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            telecomManager.isIncomingCallPermitted(phoneAccountHandle)
        } else {
           true
        }
        Log.i("CallManager", "is incoming call permited = $isCallPermitted")
        telecomManager.addNewIncomingCall(phoneAccountHandle, extras)
    }
}

还有我的自定义 ConnectionService 实现:

class CallConnectionService : ConnectionService() {
override fun onCreateOutgoingConnection(connectionManagerPhoneAccount: PhoneAccountHandle?, request: ConnectionRequest?): Connection {
    Log.i("CallConnectionService", "onCreateOutgoingConnection")
    val conn = CallConnection(applicationContext)
    conn.setAddress(request!!.address, PRESENTATION_ALLOWED)
    conn.setInitializing()
    conn.videoProvider = MyVideoProvider()
    conn.setActive()
    return conn
}

override fun onCreateOutgoingConnectionFailed(connectionManagerPhoneAccount: PhoneAccountHandle?, request: ConnectionRequest?) {
    super.onCreateOutgoingConnectionFailed(connectionManagerPhoneAccount, request)
    Log.i("CallConnectionService", "create outgoing call failed")
}

override fun onCreateIncomingConnection(connectionManagerPhoneAccount: PhoneAccountHandle?, request: ConnectionRequest?): Connection {
    Log.i("CallConnectionService", "onCreateIncomingConnection")
    val conn = CallConnection(applicationContext)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
        conn.connectionProperties = Connection.PROPERTY_SELF_MANAGED
    }
    conn.setCallerDisplayName("test call", TelecomManager.PRESENTATION_ALLOWED)
    conn.setAddress(request!!.address, PRESENTATION_ALLOWED)
    conn.setInitializing()
    conn.videoProvider = MyVideoProvider()
    conn.setActive()

    return conn
}

override fun onCreateIncomingConnectionFailed(connectionManagerPhoneAccount: PhoneAccountHandle?, request: ConnectionRequest?) {
    super.onCreateIncomingConnectionFailed(connectionManagerPhoneAccount, request)
    Log.i("CallConnectionService", "create outgoing call failed ")
}

我的连接实现是这样的:

    class CallConnection(ctx:Context) : Connection() {

    var ctx:Context = ctx
    val TAG = "CallConnection"

    override fun onShowIncomingCallUi() {
//        super.onShowIncomingCallUi()
        Log.i(TAG, "onShowIncomingCallUi")
        val intent = Intent(Intent.ACTION_MAIN, null)
        intent.flags = Intent.FLAG_ACTIVITY_NO_USER_ACTION or Intent.FLAG_ACTIVITY_NEW_TASK
        intent.setClass(ctx, IncomingCallActivity::class.java!!)
        val pendingIntent = PendingIntent.getActivity(ctx, 1, intent, 0)
        val builder = Notification.Builder(ctx)
        builder.setOngoing(true)
        builder.setPriority(Notification.PRIORITY_HIGH)

        // Set notification content intent to take user to fullscreen UI if user taps on the
        // notification body.
        builder.setContentIntent(pendingIntent)
        // Set full screen intent to trigger display of the fullscreen UI when the notification
        // manager deems it appropriate.
        builder.setFullScreenIntent(pendingIntent, true)

        // Setup notification content.
        builder.setSmallIcon(R.mipmap.ic_launcher)
        builder.setContentTitle("Your notification title")
        builder.setContentText("Your notification content.")

        // Use builder.addAction(..) to add buttons to answer or reject the call.

        val notificationManager = ctx.getSystemService(
                NotificationManager::class.java)

        notificationManager.notify("Call Notification", 37, builder.build())
    }

    override fun onCallAudioStateChanged(state: CallAudioState?) {
        Log.i(TAG, "onCallAudioStateChanged")
    }

    override fun onAnswer() {
        Log.i(TAG, "onAnswer")
    }

    override fun onDisconnect() {
        Log.i(TAG, "onDisconnect")
    }

    override fun onHold() {
        Log.i(TAG, "onHold")
    }

    override fun onUnhold() {
        Log.i(TAG, "onUnhold")
    }

    override fun onReject() {
        Log.i(TAG, "onReject")
    }
}

根据文档显示用户传入的 calcustomon UI - 我应该在 onShowIncomingCallUi() 方法中执行一些操作。但它只是不被系统调用。

我该如何解决?

最佳答案

我能够使用测试应用程序和在 Pixel 2 XL 上运行的 Android Pie 让它工作。

根据我的测试,重要的部分是确保:

  • 在连接上设置了 Connection.PROPERTY_SELF_MANAGED。至少需要 API 26。
  • 您必须注册您的电话帐户。
  • 您必须在注册电话帐户时在您的功能中设置 PhoneAccount.CAPABILITY_SELF_MANAGED。这是我设置的唯一能力。设置其他功能会导致它抛出异常。
  • 最后,您需要确保在 AndroidManifest.xml 中设置了此权限。 android.permission.MANAGE_OWN_CALLS

因此,我会检查您的 list 以确保您拥有权限并确保功能设置正确。看起来您上面的代码中的其他所有内容都已正确设置。

希望对您有所帮助!

关于Android ConnectionService 来电,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53158693/

有关Android ConnectionService 来电的更多相关文章

  1. go - 由于未接来电而导致测试中止 - 2

    我试图在本地函数内部调用的方法上mock.Expect。当我通过考试时。但当我期望它至少执行一次时,它失败了。此调用之前绝对没有其他代码路径,因此不应失败。我在这里使用方法的简化表示,因为这是一个复杂的测试设置/方法。但这绝对是要点。我的问题是,我的测试是否因为我模拟的方法而失败。期望的不是直接在mock.Expect.AddNumbers(a,b).AnyTimes().Return(&result.sum,nil)函数内部?add_test.goimportresultTestAdditionFunction(t*testing.T){//mocksetupstuff...a:=1

  2. windows - 如何查到来电信息? - 2

    这需要一些背景知识。我正在使用Detours拦截系统调用。对于那些不知道Detours是什么的人-它是一种将对系统函数的调用重定向到绕行函数的工具,它允许我们在进行实际系统调用之前和之后做我们想做的任何事情。我想知道的是,是否有可能以某种方式找出有关进行此系统调用的dll/模块的任何信息?是否有任何win32api函数可以帮助我做到这一点?假设traceapi.dll对kernel32.dll中的GetModuleFileNameW()进行系统调用。Detour将拦截此调用并将控制重定向到绕行函数(比如Mine_GetModuleFileNameW())。现在在Mine_GetModu

  3. windows - 获取来电事件 - 2

    我们如何在移动设备上的Windows10UWP中注册以监听来电事件?我试过了WindowsCallSample但它只适用于未知的拨号器。我还尝试使用不同的PhoneTriggerType注册示例,但这似乎不起作用。 最佳答案 ItriedWindowsCallSamplebutitworksonlyforunknowndialers.I'vealsotriedtoregisterthesamplewithdifferentPhoneTriggerTypebutthatdoesn'tseemtowork.如果你想监听任何来电事件。您可

  4. ios - 核心数据 NSPersistentStoreCoordinator 从来电调用中止,SWIFT - 2

    我花了很多时间让我的CoreData模型在开发中的iOS应用程序中高效工作。在大多数情况下,我的一切工作都很顺利,但前几天我偶然遇到了一个独特的错误加载我的数据。我刚开始在我的iPhone上运行我的应用程序进行测试,就在它启动并开始使用CoreData加载数据时,我姐姐给我打电话。时机相当偶然,因为那个中断似乎从AppDelegate中的persistentStoreCoordinator调用了abort()函数。这是我指的代码:lazyvarpersistentStoreCoordinator:NSPersistentStoreCoordinator={//Thepersistent

  5. ios - twilio iOS Sdk 中的 Twilio 来电问题 - 2

    我在我的应用程序中使用twilioiOSsdk并且遇到来电问题。我可以接听来电,但来电者在讲话后断开通话,我的应用程序中没有收到任何回叫。所以我无法确定我的应用程序中的调用已断开连接。注意:现在我在我的应用程序中使用下面的回调方法,当来电被忽略时它被调用了一次,但是当调用者说话并断开调用时它没有调用。-(void)connectionDidDisconnect:(TCConnection*)connection 最佳答案 您可能会在调用者断开连接后尝试通过调用-(void)disconnectAll来更新您的代码。https://w

  6. ios - XCUITest 使用 Springboard 测试 native Callkit UI。如何获取来电标签? - 2

    我正在尝试在我们的应用程序中测试VOIP通话。我模拟一个调用,并尝试断言是否存在正确的调用者ID。但是,我无法使用以下方法访问来电者姓名标签“Bob”:letspringBoard=XCUIApplication(bundleIdentifier:"com.apple.springboard")XCTAssert(springBoard.staticTexts["Bob‬"].waitForExistence(timeout:10))//Assertionfails但是,如果我尝试使用相同的调用访问它正下方的标签“***Audio...”,则断言通过:XCTAssert(springB

  7. ios - 来电时屏幕未正确调整大小 - 2

    当我的iPhone有来电时,我的应用程序无法正确调整大小。我该怎么做才能更好地处理调整大小问题? 最佳答案 参见AdjustingYourUserInterfaceDuringaPhoneCall在iOS应用程序编程指南中。 关于ios-来电时屏幕未正确调整大小,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/10315732/

  8. iphone - 使用 IOS SDK 是否可以在另一个调用正在进行时(在后台)检测来电? - 2

    我知道我们可以使用CoreTelephony框架(使用CTCallCenter)获取调用状态信息。如果调用已经在进行中,是否有可能检测到新的来电,还有一件事是可以在后台应用程序中跟踪来电。DetectingcallstateiniOS4backgroundappiniOSthatdetectsincomingphonecalls根据以上链接,我认为无法在后台中运行该应用程序。是否有任何其他方法可以实现此目的? 最佳答案 目前的sdk好像不行 关于iphone-使用IOSSDK是否可以在另

  9. android - 用于处理未接来电的 PhoneGap 插件 - 2

    我正在寻找PhoneGap插件以允许处理来电状态,例如Android上的RINGING和IDLE状态。我在这里搜索了插件的官方存储库:https://github.com/phonegap/phonegap-plugins并且也在Google上进行了搜索,但没有什么用。我也想知道,在iOS上是否完全可以实现相同的概念?据我所知,它在iOS上不可用。 最佳答案 检查此Android插件:https://github.com/madeinstefano/PhoneStateChangeListener对于iOS,正如Ved所提到的,它不

  10. ios - Skype 如何在 iOS 上实现来电长推送通知? - 2

    我正在尝试实现一个iOS应用程序,用户可以在其中接收推送通知/提醒一分钟,声音类似于Skype的来电提醒。但它不是VoIP应用程序。它用于紧急警报,所以我想推送一些文本,但与普通推送通知不同的是,推送时间更长。谢谢 最佳答案 我会采用不同的方法。发送静音通知,这样通知就不会播放任何声音。构建您的应用程序,使其能够在后台播放音乐,并在收到无声通知后,启动声音循环。播放声音并等待用户与应用交互或在X时间后停止。至少我会从这种方法开始并调整它以使其成为我想要的方式。 关于ios-Skype如何

随机推荐