Android6.0之后官方SDK提供了Telecom framework框架,这个框架允许第三方开发者可以用自己的程序替换系统的默认电话应用,实现过程也尤为简单;
API 提供了InCallService服务,里面定义了来电话与拨打电话的相关方法,我们只要实现这个Service并控制自己的UI页面就可以了。
InCallService 的实现如下:
public class PhoneCallService extends InCallService {
public static final int CALL_IN = 1;
public static final int CALL_OUT = 2;
private Call.Callback callback = new Call.Callback() {
@Override
public void onStateChanged(Call call, int state) {
super.onStateChanged(call, state);
switch (state) {
case Call.STATE_ACTIVE: {
// 通话中
break;
}
case Call.STATE_DISCONNECTED: {
// 通话结束
PhoneCallActivity.killA();
break;
}
default:
break;
}
}
};
@Override
public void onCallAdded(Call call) {
super.onCallAdded(call);
call.registerCallback(callback);
PhoneCallManager.call = call;
int callType = 0;
if (call.getState() == Call.STATE_RINGING) {
callType = CALL_IN;
} else if (call.getState() == Call.STATE_CONNECTING) {
callType = CALL_OUT;
}
// 去除拨出电话中的空格
Call.Details details = call.getDetails();
String phoneNumber = details.getHandle().toString().substring(4).replaceAll("%20", "");
PhoneCallActivity.startPhoneCallActivity(this, phoneNumber, callType);
}
@Override
public void onCallRemoved(Call call) {
super.onCallRemoved(call);
call.unregisterCallback(callback);
PhoneCallManager.call = null;
}
来电UI的实现如下:
public class PhoneCallActivity extends AppCompatActivity {
private static PhoneCallActivity instance;
public static void startPhoneCallActivity(Context context, String number, int type) {
Intent intent = new Intent(context, PhoneCallActivity.class);
intent.putExtra("number", number);
intent.putExtra("type", type);
if (type == PhoneCallService.CALL_IN) {
context.startActivity(intent);
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone_call);
instance = this;
TextView number = findViewById(R.id.number);
number.setText(getIntent().getStringExtra("number"));
findViewById(R.id.hangup).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PhoneCallManager.disconnect();
}
});
findViewById(R.id.answer).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PhoneCallManager.answer();
}
});
}
public static void killA() {
if (instance != null) {
instance.finish();
}
}
}
相关工具类实现:
public class PhoneCallManager {
public static Call call;
/**
* 接听电话
*/
public static void answer() {
if (call != null) {
call.answer(VideoProfile.STATE_AUDIO_ONLY);
}
}
/**
* 断开电话,包括来电时的拒接以及接听后的挂断
*/
public static void disconnect() {
if (call != null) {
call.disconnect();
}
}
}
最后需要在AndroidManifest里注册Activity与Service;
Activity的第一个 <intent-filter> 是提供打电话UI的 ,第二个是提供拨号功能的。
service的 <meta-data> 用于表明我们的应用提供了接听电话的 UI;
注意的是设置默认电话应用不需要申请额外的权限,只需在InCallService注册时添加android.permission.BIND_INCALL_SERVICE权限声明就可以了。
<activity android:name=".activity.PhoneCallActivity">
<!-- provides ongoing call UI -->
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent-filter> <!-- provides dial UI -->
<intent-filter>
<action android:name="android.intent.action.DIAL" />
</intent-filter>
</activity>
<service
android:name=".service.PhoneCallService"
android:permission="android.permission.BIND_INCALL_SERVICE">
<meta-data
android:name="android.telecom.IN_CALL_SERVICE_UI"
android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService" />
</intent-filter>
</service>
最后不要忘了在你的应用中申请成为默认电话应用;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, getPackageName());
startActivity(intent);
}
网友评论