在上一个版本中, 详细介绍了如何利用 广播与接收、Worker、Service 等实现电话的触发与状态变化的监听. 在这个基础之上, 实际使用中发现很不少可以优化的部分. 下面把比较重要的展示一下:
1. 首先是获取号码:
在高版本中, 获取号码需要传入卡槽id, 如果使用DEFAULT_SUBSCRIPTION_ID 默认ID的话, 会有一定的问题, 即当卡拔掉后, 获取的号码还是之前插卡对应的号码. 不能获取实时数据. 这在用户换卡时候容易造成歧义. 因此需要真实的当前卡槽1的ID, 这样每次请求号码就都是真实的. 完整代码:
@SuppressLint("MissingPermission")
public static String getLine1Num(Context context, String TAG){
String line1Num;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
line1Num = telephonyManager.getLine1Number();
}else{
SubscriptionManager subscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int[] ids = subscriptionManager.getSubscriptionIds(0);
int slot0_subId = (ids == null || ids.length == 0) ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : ids[0];
Log.d(TAG, "slot0 id: "+ slot0_subId);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
line1Num = subscriptionManager.getPhoneNumber(slot0_subId);
}else{
SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(0);
line1Num = info == null ? "" : info.getNumber();
}
}
Log.i(TAG, "line1Number:"+line1Num);
return line1Num == null ? "" : line1Num;
}
2. 如何获取通话记录及录音:
之前的逻辑是在电话监听到挂断的时候, 延时调用getContentResolver查询最新一通录音. 这个逻辑能用,但不是最好的, 后来发现ContentResolver是可以注册回调的(Observer), 这就方便多了, 在服务启动的时候就可以注册上, 然后一旦录音生成了, 就会自动触发回调(Observer). 然后在后续的研究中,发现除了通话记录, 录音也可以通过这样的方式来获取到(但很多手机这里录音后可能没有写ContentResolver数据,导致无法如此查询, 目前发现可以完美适配的有OPPO的Color OS 12+). 详细代码展示:
private void monitorCallLogChange(Context context) {
// 获取ContentResolver实例
ContentResolver contentResolver = context.getContentResolver();
// 注册一个观察者来监听通话记录的变化
contentResolver.registerContentObserver(CallLog.Calls.CONTENT_URI, false, new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChan