ITelephony.endCall() 不再适用于 Android 8/Android O/API 26 中的阻塞调用
ITelephony.endCall() doesn't work anymore for blocking calls in Android 8/Android O/API 26
我有一个应用程序使用以下代码来阻止呼叫:
TelephonyManager telephonyManager =
(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
try {
Class<?> telephonyManagerClass =
Class.forName(telephonyManager.getClass().getName());
Method getITelephonyMethod =
telephonyManagerClass.getDeclaredMethod("getITelephony");
getITelephonyMethod.setAccessible(true);
Object iTelephony = getITelephonyMethod.invoke(telephonyManager);
Class<?> iTelephonyClass = Class.forName(iTelephony.getClass().getName());
Method endCallMethod = iTelephonyClass.getDeclaredMethod("endCall");
endCallMethod.setAccessible(true);
endCallMethod.invoke(iTelephony);
} catch (ClassNotFoundException e) {
// ClassNotFoundException
} catch (NoSuchMethodException e) {
// NoSuchMethodException
} catch (IllegalAccessException e) {
// IllegalAccessException
} catch (InvocationTargetException e) {
// InvocationTargetException
} catch (Exception e) {
// Some other exception
}
要工作,这需要 android.permission.MODIFY_PHONE_STATE 在 AndroidManifest.xml 中。在 Android M 和 N 中,我还必须征求用户的许可 Manifest.permission.CALL_PHONE。
但是现在在Android 8/Android O,上面的代码失败并出现InvocationTargetException: MODIFY_PHONE_STATE permission required
我找到了这个相关的 Whosebug post:Android - Why does endCall method work but answerRingingCall doesn't work?
这里建议我可以在 PhoneInterfaceManager 上使用反射(而不是 ITelephony,就像我在上面所做的那样)并使用私有方法 sendRequestAsync(int command) 和结束调用命令,并通过这样做绕过 endCall() 方法中的安全措施。
有没有人试过这样的东西?可能吗?我怎样才能得到 PhoneInterfaceManager object/class 而不是 ITelephony?
在结束通话时,我看不出这与 Android N 的代码有任何区别,所以我可能会误会:
https://android.googlesource.com/platform/packages/services/Telephony/+/nougat-release/src/com/android/phone/PhoneInterfaceManager.java
感谢 Nikola Brežnjak 的博客,我找到了答案:https://dev.to/hitman666/how-to-make-a-native-android-app-that-can-block-phone-calls--4e15
基本上,您需要在项目中包含 ITelephony 接口。使用以下代码创建文件 ITelephony.class(保留命名空间):
package com.android.internal.telephony;
public interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
然后根据您的代码,使用以下代码结束 phone 调用:
// This is only useful on Android O and older
// Needs permission CALL_PHONE
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O
|| checkSelfPermission(Manifest.permission.CALL_PHONE)
== PackageManager.PERMISSION_DENIED) {
return;
}
try {
ITelephony telephonyService;
TelephonyManager telephonyManager = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
Method getITelephony = telephonyManager
.getClass()
.getDeclaredMethod("getITelephony");
getITelephony.setAccessible(true);
telephonyService = (ITelephony) getITelephony.invoke(telephonyManager);
telephonyService.endCall();
} catch (Exception ignored) {
}
我有一个应用程序使用以下代码来阻止呼叫:
TelephonyManager telephonyManager =
(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
try {
Class<?> telephonyManagerClass =
Class.forName(telephonyManager.getClass().getName());
Method getITelephonyMethod =
telephonyManagerClass.getDeclaredMethod("getITelephony");
getITelephonyMethod.setAccessible(true);
Object iTelephony = getITelephonyMethod.invoke(telephonyManager);
Class<?> iTelephonyClass = Class.forName(iTelephony.getClass().getName());
Method endCallMethod = iTelephonyClass.getDeclaredMethod("endCall");
endCallMethod.setAccessible(true);
endCallMethod.invoke(iTelephony);
} catch (ClassNotFoundException e) {
// ClassNotFoundException
} catch (NoSuchMethodException e) {
// NoSuchMethodException
} catch (IllegalAccessException e) {
// IllegalAccessException
} catch (InvocationTargetException e) {
// InvocationTargetException
} catch (Exception e) {
// Some other exception
}
要工作,这需要 android.permission.MODIFY_PHONE_STATE 在 AndroidManifest.xml 中。在 Android M 和 N 中,我还必须征求用户的许可 Manifest.permission.CALL_PHONE。
但是现在在Android 8/Android O,上面的代码失败并出现InvocationTargetException: MODIFY_PHONE_STATE permission required
我找到了这个相关的 Whosebug post:Android - Why does endCall method work but answerRingingCall doesn't work?
这里建议我可以在 PhoneInterfaceManager 上使用反射(而不是 ITelephony,就像我在上面所做的那样)并使用私有方法 sendRequestAsync(int command) 和结束调用命令,并通过这样做绕过 endCall() 方法中的安全措施。
有没有人试过这样的东西?可能吗?我怎样才能得到 PhoneInterfaceManager object/class 而不是 ITelephony?
在结束通话时,我看不出这与 Android N 的代码有任何区别,所以我可能会误会: https://android.googlesource.com/platform/packages/services/Telephony/+/nougat-release/src/com/android/phone/PhoneInterfaceManager.java
感谢 Nikola Brežnjak 的博客,我找到了答案:https://dev.to/hitman666/how-to-make-a-native-android-app-that-can-block-phone-calls--4e15
基本上,您需要在项目中包含 ITelephony 接口。使用以下代码创建文件 ITelephony.class(保留命名空间):
package com.android.internal.telephony;
public interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
然后根据您的代码,使用以下代码结束 phone 调用:
// This is only useful on Android O and older
// Needs permission CALL_PHONE
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O
|| checkSelfPermission(Manifest.permission.CALL_PHONE)
== PackageManager.PERMISSION_DENIED) {
return;
}
try {
ITelephony telephonyService;
TelephonyManager telephonyManager = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
Method getITelephony = telephonyManager
.getClass()
.getDeclaredMethod("getITelephony");
getITelephony.setAccessible(true);
telephonyService = (ITelephony) getITelephony.invoke(telephonyManager);
telephonyService.endCall();
} catch (Exception ignored) {
}