Android中获取到历史通话时长而非刚挂断通话时长的问题
解决通话挂断后获取最新通话时长的问题
嘿,我明白你遇到的麻烦了——刚挂断通话就去查时长,结果拿到的是上一次的,这确实挺闹心的。问题出在系统的通话记录(CallLog)并不是在通话挂断瞬间就立刻写入数据库的,你现在的代码是挂断后马上调用LastCall()去查询,这时候新的通话记录还没被系统保存下来,自然拿到的是之前的那条。
接下来给你几个可行的解决方案,按可靠性排序:
方案1:使用ContentObserver监听CallLog变化(推荐)
这是最靠谱的方式,我们可以注册一个内容观察者,当系统更新CallLog的时候,再去查询最新的通话时长,这样能保证拿到的是刚挂断的那条记录。
修改步骤:
- 定义一个ContentObserver子类:
private class CallLogObserver extends ContentObserver { public CallLogObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); // 当CallLog更新时,查询最新通话时长 String dura = LastCall(); // 这里处理你的业务逻辑,比如更新白名单限制 WhitelistDAO whiteListDao1 = new WhitelistDAO(context); if (dura.equals("0")) { int dbTime = Integer.parseInt(whiteListDao1.getLimit(finalNumber)); whiteListDao1.updateLimit(String.valueOf(dbTime), finalNumber); } else { whiteListDao1.updateLimit("0", finalNumber); } } }
- 在你的Activity或Service里注册和注销观察者:
private CallLogObserver callLogObserver; private Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 注册观察者 callLogObserver = new CallLogObserver(handler); getContentResolver().registerContentObserver( CallLog.Calls.CONTENT_URI, true, callLogObserver ); } @Override protected void onDestroy() { super.onDestroy(); // 注销观察者,避免内存泄漏 if (callLogObserver != null) { getContentResolver().unregisterContentObserver(callLogObserver); } }
- 修改你的
disconnect()方法,去掉里面直接查询时长的逻辑,只保留挂断通话的部分:
public void disconnect(){ disconnectPhoneItelephony(context); calldisconnected(); // 这里不再直接查询时长,等待CallLogObserver触发后处理 }
方案2:延迟查询(简单但不够可靠)
如果暂时不想用观察者,也可以给查询加个短延迟,让系统有时间写入CallLog。比如用Handler.postDelayed():
public void disconnect(){ disconnectPhoneItelephony(context); calldisconnected(); new Handler().postDelayed(new Runnable() { @Override public void run() { WhitelistDAO whiteListDao1 = new WhitelistDAO(context); String dura = LastCall(); if (dura.equals("0")) { int dbTime = Integer.parseInt(whiteListDao1.getLimit(finalNumber)); whiteListDao1.updateLimit(String.valueOf(dbTime), finalNumber); } else { whiteListDao1.updateLimit("0", finalNumber); } } }, 500); // 延迟500毫秒,可根据设备调整 }
⚠️ 注意:这个方法的缺点是不同设备的系统写入速度不一样,延迟时间设短了可能还是拿不到最新记录,设长了用户会有明显等待感,所以优先推荐方案1。
额外检查点
- 确保你已经动态申请了
READ_CALL_LOG权限,并且用户已经授权,虽然你的代码里有检查,但要确认权限申请流程是正确的(比如在Activity里请求权限,处理onRequestPermissionsResult)。 - 你的
LastCall()方法里,查询时排序用的是android.provider.CallLog.Calls.DATE+ " DESC limit 1;",这个是对的,能拿到最新的通话记录,只要时机对就没问题。
内容的提问来源于stack exchange,提问作者Dillz
相关产品推荐
相关产品推荐

