我正在尝试在 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 让它工作。
根据我的测试,重要的部分是确保:
因此,我会检查您的 list 以确保您拥有权限并确保功能设置正确。看起来您上面的代码中的其他所有内容都已正确设置。
希望对您有所帮助!
关于Android ConnectionService 来电,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53158693/
我试图在本地函数内部调用的方法上mock.Expect。当我通过考试时。但当我期望它至少执行一次时,它失败了。此调用之前绝对没有其他代码路径,因此不应失败。我在这里使用方法的简化表示,因为这是一个复杂的测试设置/方法。但这绝对是要点。我的问题是,我的测试是否因为我模拟的方法而失败。期望的不是直接在mock.Expect.AddNumbers(a,b).AnyTimes().Return(&result.sum,nil)函数内部?add_test.goimportresultTestAdditionFunction(t*testing.T){//mocksetupstuff...a:=1
这需要一些背景知识。我正在使用Detours拦截系统调用。对于那些不知道Detours是什么的人-它是一种将对系统函数的调用重定向到绕行函数的工具,它允许我们在进行实际系统调用之前和之后做我们想做的任何事情。我想知道的是,是否有可能以某种方式找出有关进行此系统调用的dll/模块的任何信息?是否有任何win32api函数可以帮助我做到这一点?假设traceapi.dll对kernel32.dll中的GetModuleFileNameW()进行系统调用。Detour将拦截此调用并将控制重定向到绕行函数(比如Mine_GetModuleFileNameW())。现在在Mine_GetModu
我们如何在移动设备上的Windows10UWP中注册以监听来电事件?我试过了WindowsCallSample但它只适用于未知的拨号器。我还尝试使用不同的PhoneTriggerType注册示例,但这似乎不起作用。 最佳答案 ItriedWindowsCallSamplebutitworksonlyforunknowndialers.I'vealsotriedtoregisterthesamplewithdifferentPhoneTriggerTypebutthatdoesn'tseemtowork.如果你想监听任何来电事件。您可
我花了很多时间让我的CoreData模型在开发中的iOS应用程序中高效工作。在大多数情况下,我的一切工作都很顺利,但前几天我偶然遇到了一个独特的错误加载我的数据。我刚开始在我的iPhone上运行我的应用程序进行测试,就在它启动并开始使用CoreData加载数据时,我姐姐给我打电话。时机相当偶然,因为那个中断似乎从AppDelegate中的persistentStoreCoordinator调用了abort()函数。这是我指的代码:lazyvarpersistentStoreCoordinator:NSPersistentStoreCoordinator={//Thepersistent
我在我的应用程序中使用twilioiOSsdk并且遇到来电问题。我可以接听来电,但来电者在讲话后断开通话,我的应用程序中没有收到任何回叫。所以我无法确定我的应用程序中的调用已断开连接。注意:现在我在我的应用程序中使用下面的回调方法,当来电被忽略时它被调用了一次,但是当调用者说话并断开调用时它没有调用。-(void)connectionDidDisconnect:(TCConnection*)connection 最佳答案 您可能会在调用者断开连接后尝试通过调用-(void)disconnectAll来更新您的代码。https://w
我正在尝试在我们的应用程序中测试VOIP通话。我模拟一个调用,并尝试断言是否存在正确的调用者ID。但是,我无法使用以下方法访问来电者姓名标签“Bob”:letspringBoard=XCUIApplication(bundleIdentifier:"com.apple.springboard")XCTAssert(springBoard.staticTexts["Bob"].waitForExistence(timeout:10))//Assertionfails但是,如果我尝试使用相同的调用访问它正下方的标签“***Audio...”,则断言通过:XCTAssert(springB
当我的iPhone有来电时,我的应用程序无法正确调整大小。我该怎么做才能更好地处理调整大小问题? 最佳答案 参见AdjustingYourUserInterfaceDuringaPhoneCall在iOS应用程序编程指南中。 关于ios-来电时屏幕未正确调整大小,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/10315732/
我知道我们可以使用CoreTelephony框架(使用CTCallCenter)获取调用状态信息。如果调用已经在进行中,是否有可能检测到新的来电,还有一件事是可以在后台应用程序中跟踪来电。DetectingcallstateiniOS4backgroundappiniOSthatdetectsincomingphonecalls根据以上链接,我认为无法在后台中运行该应用程序。是否有任何其他方法可以实现此目的? 最佳答案 目前的sdk好像不行 关于iphone-使用IOSSDK是否可以在另
我正在寻找PhoneGap插件以允许处理来电状态,例如Android上的RINGING和IDLE状态。我在这里搜索了插件的官方存储库:https://github.com/phonegap/phonegap-plugins并且也在Google上进行了搜索,但没有什么用。我也想知道,在iOS上是否完全可以实现相同的概念?据我所知,它在iOS上不可用。 最佳答案 检查此Android插件:https://github.com/madeinstefano/PhoneStateChangeListener对于iOS,正如Ved所提到的,它不
我正在尝试实现一个iOS应用程序,用户可以在其中接收推送通知/提醒一分钟,声音类似于Skype的来电提醒。但它不是VoIP应用程序。它用于紧急警报,所以我想推送一些文本,但与普通推送通知不同的是,推送时间更长。谢谢 最佳答案 我会采用不同的方法。发送静音通知,这样通知就不会播放任何声音。构建您的应用程序,使其能够在后台播放音乐,并在收到无声通知后,启动声音循环。播放声音并等待用户与应用交互或在X时间后停止。至少我会从这种方法开始并调整它以使其成为我想要的方式。 关于ios-Skype如何