Android 8.0(API 级别 26)引入了几个与电话相关的新权限: ANSWER_PHONE_CALLS 权限允许您的应用以编程方式接听来电。要在您的应用程序中处理来电,您可以使用 acceptRingingCall() 方法。
我的应用程序如何为来电提供语音应答?
但我还没有找到任何关于此的指南或示例。所以
我想要语音自动应答(来自应用程序中的原始文件夹)(我需要指南或示例代码,如应答机)
Android 8.0(API 级别 26)引入了几个与电话相关的新权限: ANSWER_PHONE_CALLS 权限允许您的应用以编程方式接听来电。要在您的应用程序中处理来电,您可以使用 acceptRingingCall() 方法。
我的应用程序如何为来电提供语音应答?
但我还没有找到任何关于此的指南或示例。所以
我想要语音自动应答(来自应用程序中的原始文件夹)(我需要指南或示例代码,如应答机)
https://developer.android.com/reference/android/telecom/TelecomManager.html#acceptRingingCall()
接受应答呼叫已弃用 API LEVEL Q
try {
Toast.makeText(CallAnswerDialog.this, "btn_answer click", Toast.LENGTH_SHORT).show();
TelecomManager tm = (TelecomManager) CallAnswerDialog.this.getSystemService(Context.TELECOM_SERVICE);
if (tm == null) {
// whether you want to handle this is up to you really
throw new NullPointerException("tm == null");
}
tm.acceptRingingCall(); // is deprecated Now API Level Q
btn_answer.setVisibility(View.GONE);
}catch (Exception e){
e.printStackTrace(); }
来自谷歌的更新:
telecomManager.acceptRingingCall();
telecomManager.acceptRingingCall(false);
telecomManager.endCall();
所有这三个命令都已在 Android Q 上弃用
对于接听电话,这仅适用于 Android O。以前,它可能不起作用。这是它的代码:
/**returns true iff we are sure that answering the phone call worked*/
fun answerCall(context: Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(context, Manifest.permission.MODIFY_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
telecomManager.acceptRingingCall()
return true
}
return false
}
// https://stackoverflow.com/a/29651130/878126
// for HTC devices we need to broadcast a connected headset
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
val broadcastConnected = "htc" == Build.MANUFACTURER.toLowerCase(Locale.US) && !audioManager.isWiredHeadsetOn
if (broadcastConnected)
broadcastHeadsetConnected(context, false)
try {
try {
Runtime.getRuntime().exec("input keyevent " + Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK))
} catch (e: IOException) {
// Runtime.exec(String) had an I/O problem, try to fall back
val enforcedPerm = "android.permission.CALL_PRIVILEGED"
val btnDown = Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(Intent.EXTRA_KEY_EVENT, KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK))
val btnUp = Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(Intent.EXTRA_KEY_EVENT, KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK))
context.sendOrderedBroadcast(btnDown, enforcedPerm)
context.sendOrderedBroadcast(btnUp, enforcedPerm)
}
} finally {
if (broadcastConnected)
broadcastHeadsetConnected(context, false)
}
return false
}
对于挂断电话,这是在 Android P 上正式添加的,但解决方法似乎适用于我迄今为止尝试过的大多数情况(例如,不适用于带有 Android 8.1 的 Nexus 5x)。这是此代码:
@SuppressLint("PrivateApi")
fun endCall(context: Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
if (telecomManager != null && ContextCompat.checkSelfPermission(context, Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED) {
telecomManager.endCall()
return true
}
return false
}
//use unofficial API for older Android versions, as written here: https://stackoverflow.com/a/8380418/878126
try {
val telephonyClass = Class.forName("com.android.internal.telephony.ITelephony")
val telephonyStubClass = telephonyClass.classes[0]
val serviceManagerClass = Class.forName("android.os.ServiceManager")
val serviceManagerNativeClass = Class.forName("android.os.ServiceManagerNative")
val getService = serviceManagerClass.getMethod("getService", String::class.java)
val tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder::class.java)
val tmpBinder = Binder()
tmpBinder.attachInterface(null, "fake")
val serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder)
val retbinder = getService.invoke(serviceManagerObject, "phone") as IBinder
val serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder::class.java)
val telephonyObject = serviceMethod.invoke(null, retbinder)
val telephonyEndCall = telephonyClass.getMethod("endCall")
telephonyEndCall.invoke(telephonyObject)
return false
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
因此,对于接听和拒接电话,最安全的方法是让它在 Android P 上运行...... :(