Android 电话功能开发指南
在 Android 应用开发中,电话功能涉及拨打电话、监听通话状态、拦截呼出电话以及处理来电挂断等核心场景。由于涉及用户隐私和通信费用,相关 API 需要严格的权限声明和运行时授权。
1. 如何使用代码拨打电话
Android 提供了两种主要的拨打电话方式:
- 打开拨号界面:使用
Intent.ACTION_DIAL。用户确认后会显示号码并等待点击呼叫。此方式不需要CALL_PHONE权限。 - 直接拨打电话:使用
Intent.ACTION_CALL。程序直接发起呼叫,无需用户二次确认。此方式必须声明android.permission.CALL_PHONE权限。
代码示例
// 打开拨号界面(无需 CALL_PHONE 权限)
Intent intentDial = new Intent();
intentDial.setAction(Intent.ACTION_DIAL);
intentDial.setData(Uri.parse("tel:10086"));
startActivity(intentDial);
// 直接拨打电话(需 CALL_PHONE 权限)
Intent intentCall = new Intent();
intentCall.setAction(Intent.ACTION_CALL);
intentCall.setData(Uri.parse("tel:10086"));
startActivity(intentCall);
权限配置
在 AndroidManifest.xml 中添加权限:
<uses-permission android:name="android.permission.CALL_PHONE" />
注意:从 Android 6.0 (API 23) 开始,CALL_PHONE 属于危险权限,必须在运行时动态申请并获得用户授权后才能调用,否则会导致 SecurityException。
2. 如何监听电话状态
Android 提供了 TelephonyManager 类来管理电话服务,配合 PhoneStateListener 可以监听三种主要状态:
- 空闲状态 (IDLE):无通话活动。
- 振铃状态 (RINGING):有来电或正在拨出。
- 摘机状态 (OFFHOOK):通话正在进行中。
实现步骤
- 创建继承自
PhoneStateListener的类。 - 重写
onCallStateChanged方法处理状态变化。 - 获取
TelephonyManager实例并注册监听器。 - 在适当时机取消监听以避免内存泄漏。
代码示例
public class MainActivity extends AppCompatActivity {
private TelephonyManager telephonyManager;
private MyPhoneStateListener listener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取电话管理器
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// 创建监听器
listener = new MyPhoneStateListener();
// 开启监听(需 READ_PHONE_STATE 权限)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
// 电话状态监听器
class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.i("Telephony", "CALL_STATE_IDLE: 空闲");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i("Telephony", "CALL_STATE_OFFHOOK: 通话中");
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.i("Telephony", "CALL_STATE_RINGING: 振铃,号码:" + incomingNumber);
break;
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 取消监听
if (telephonyManager != null && listener != null) {
telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE);
}
}
}
权限配置
需要在清单文件中声明以下权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
同样,READ_PHONE_STATE 也需要在运行时动态申请。
3. 如何拦截呼出电话
通过广播接收器监听系统发出的呼出电话广播,可以在特定条件下阻止呼叫。
实现逻辑
- 注册
BroadcastReceiver监听Intent.ACTION_NEW_OUTGOING_CALL。 - 在
onReceive中获取目标号码。 - 根据业务逻辑决定是否中断呼叫(设置结果为 null)。
代码示例
public class MainActivity extends AppCompatActivity {
private MyPhoneReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册广播接收器
receiver = new MyPhoneReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
registerReceiver(receiver, filter);
}
// 拦截呼出电话的 Receiver
class MyPhoneReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String number = getResultData();
Log.i("MyPhoneReceiver", "Outgoing call to: " + number);
// 示例:拦截拨打 10086
if (number != null && number.equals("10086")) {
setResultData(null); // 阻止拨出
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 取消注册广播接收器
if (receiver != null) {
unregisterReceiver(receiver);
}
}
}
权限配置
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
注意:从 Android 9 (API 28) 开始,PROCESS_OUTGOING_CALLS 已被废弃,且普通应用无法再拦截所有呼出电话。此功能通常仅适用于默认电话应用或系统级应用。现代开发建议使用 Telecom API 进行更合规的管理。
4. 如何自动挂断来电
对于特定的来电,可以使用 TelecomManager 提供的接口在响铃阶段自动挂断。
代码示例
if (incomingNumber.equals("10086")) {
TelecomManager tm = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
if (tm != null) {
tm.endCall();
}
}
权限与版本要求
- 需要添加权限:
android.permission.ANSWER_PHONE_CALLS - 该 API 仅在 Android 8.0 (API 28) 及以上版本可用。
5. 最佳实践与注意事项
- 生命周期管理:务必在
onDestroy或onPause中取消电话监听器和广播接收器,防止内存泄漏。 - 权限检查:始终在调用敏感 API 前检查运行时权限,避免崩溃。
- 兼容性:部分电话相关 API 随 Android 版本迭代发生变化,开发时需查阅对应版本的官方文档。
- 用户体验:拦截或自动挂断电话应谨慎使用,避免影响正常通信体验。
通过以上方法,开发者可以在 Android 应用中安全、有效地实现电话相关的核心功能。


