Я вижу много вопросов, уже заданных на SO, но ни на один вопрос нет правильного ответа.
Большинство из них в SO и блогах предлагают ниже фрагмент кода:
var buttonDown = Intent(Intent.ACTION_MEDIA_BUTTON)
buttonDown.putExtra(Intent.EXTRA_KEY_EVENT,
KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK))
sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED")
var buttonDown1 = Intent(Intent.ACTION_MEDIA_BUTTON)
buttonDown.putExtra(Intent.EXTRA_KEY_EVENT,
KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK))
sendOrderedBroadcast(buttonDown1, "android.permission.CALL_PRIVILEGED")
Однако, это не работает и выдает ошибку, говоря, что "CALL_PRIVILEGED" не разрешен для сторонних приложений.
В некоторых сообщениях и ответах предлагается использовать фрагмент кода ниже.
Runtime.getRuntime().exec("input keyevent " + Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK))
Но, к сожалению, это также не помогает мне.Я понимаю, что у нас есть готовые методы из платформы Android, чтобы принять вызов и завершить вызов для уровня API выше Oreo.Но мне нужно реализовать это и ниже.
Я нашел этот код ниже, чтобы отклонить вызов с помощью отражения, и он отлично работает.
try {
var serviceManagerName = "android.os.ServiceManager"
var serviceManagerNativeName = "android.os.ServiceManagerNative"
var telephonyName = "com.android.internal.telephony.ITelephony"
var telephonyClass: Class<*>
var telephonyStubClass: Class<*>
var serviceManagerClass: Class<*>
var serviceManagerNativeClass: Class<*>
var telephonyEndCall: Method
var telephonyObject: Object
var serviceManagerObject: Object
telephonyClass = Class.forName(telephonyName);
telephonyStubClass = telephonyClass.getClasses()[0];
serviceManagerClass = Class.forName(serviceManagerName);
serviceManagerNativeClass = Class.forName(serviceManagerNativeName);
var getService = // getDefaults[29];
serviceManagerClass.getMethod("getService", String::class.java)
var tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder::class.java)
var tmpBinder = Binder()
tmpBinder.attachInterface(null, "fake");
serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder) as Object;
var retbinder = getService.invoke(serviceManagerObject, "phone") as IBinder
var serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder::class.java)
telephonyObject = serviceMethod.invoke(null, retbinder) as Object;
telephonyEndCall = telephonyClass.getMethod("endCall")
telephonyEndCall.invoke(telephonyObject)
} catch (e: InvocationTargetException) {
e.printStackTrace()
Log.d("unable", "msg cant dissconect call....")
}
Но подобный способ написания для приема вызова не работает.
try {
var telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
// Get the getITelephony() method
val classTelephony = Class.forName(telephonyManager.javaClass.name)
val method = classTelephony.getDeclaredMethod("getITelephony")
// Disable access check
method.isAccessible = true
// Invoke getITelephony() to get the ITelephony interface
val telephonyInterface = method.invoke(telephonyManager)
// Get the endCall method from ITelephony
val telephonyInterfaceClass = Class.forName(telephonyInterface.javaClass.name)
val methodEndCall = telephonyInterfaceClass.getMethod("answerRingingCall")
// Invoke endCall()
methodEndCall.invoke(telephonyInterface)
} catch (e: Exception) {
Log.e(TAG,"Unable to accept call")
e.printStackTrace()
}
Может кто-нибудь сказать мне, если есть правильный способ обработки Принять, Отклонить для входящих и Отключить исходящие вызовы в Android на всех уровнях API?