如何在Android Oreo中以编程方式挂断电话?
嘿,在Android Oreo(API 26)及更高版本里,你原来依赖的反射getITelephony()的方法已经行不通啦——谷歌从Oreo开始收紧了对电话相关API的权限限制,私有方法的反射调用会被系统拦截。下面给你两种靠谱的实现方案,适配不同版本:
方法1:使用官方
TelecomManager API(推荐) 这是谷歌推荐的正规方式,兼容性最好,步骤如下:
1. 声明权限
首先在AndroidManifest.xml里添加必要的权限:
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" /> <uses-permission android:name="android.permission.CALL_PHONE" />
注意:ANSWER_PHONE_CALLS在API 26+需要动态申请,用户手动授权后才能使用。
2. 实现挂断逻辑
编写代码判断系统版本,针对Oreo及以上使用TelecomManager,低版本 fallback 到原来的反射方法:
import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.widget.Toast; import java.lang.reflect.Method; public class CallUtils { public static boolean killCall(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Android Oreo及以上使用TelecomManager TelecomManager telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); // 检查权限是否已授权 if (context.checkSelfPermission(Manifest.permission.ANSWER_PHONE_CALLS) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(context, "需要授予挂断电话权限", Toast.LENGTH_SHORT).show(); // 这里可以触发动态权限申请流程 return false; } try { telecomManager.endCall(); return true; } catch (SecurityException e) { e.printStackTrace(); Toast.makeText(context, "挂断电话失败:权限不足", Toast.LENGTH_SHORT).show(); return false; } } else { // 低版本使用反射方法(兼容API 25及以下) try { TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); Class<?> telephonyClass = Class.forName(telephonyManager.getClass().getName()); Method getITelephonyMethod = telephonyClass.getDeclaredMethod("getITelephony"); getITelephonyMethod.setAccessible(true); Object iTelephony = getITelephonyMethod.invoke(telephonyManager); Method endCallMethod = iTelephony.getClass().getDeclaredMethod("endCall"); endCallMethod.invoke(iTelephony); return true; } catch (Exception e) { e.printStackTrace(); Toast.makeText(context, "挂断电话失败:反射调用出错", Toast.LENGTH_SHORT).show(); return false; } } } }
关键注意点
- 动态申请权限:在调用
killCall()之前,要先检查ANSWER_PHONE_CALLS权限是否已获取,如果没有,需要调用Activity.requestPermissions()发起申请。 - Android 10+兼容:如果你的App需要支持API 29及以上,
TelecomManager.endCall()会被废弃,需要改用TelecomManager.endCall(String callId),这时候需要获取当前通话的ID,并且需要MANAGE_OWN_CALLS权限或者将App设置为默认电话应用。
方法2:使用广播接收器(不推荐,兼容性差)
有些旧设备可能支持通过发送特定Intent来挂断电话,但这种方式在Oreo及以上基本被厂商限制,仅作参考:
// 仅部分旧设备有效 Intent intent = new Intent("android.intent.action.CALL"); intent.setData(Uri.parse("tel:")); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent);
这种方式依赖厂商实现,稳定性无法保证,不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者Ali Akram
相关产品推荐
相关产品推荐

