通话记录分析 --- 通话详情 之二

5.2 通话详情界面

在通话详情界面,主要是完成2个功能,展示通话详情,删除该条通话记录。

CallDetailActivity界面如下,


1,通话记录详情

CallDetailActivity的onCreate方法主要是加载界面布局。

主要在onResume方法中调用异步线程查询通话信息,调用流程图如下,


CallDetailActivity的onResume方法逻辑如下,

super.onResume();
getCallDetails();

getCallDetails方法如下,

CallLogAsyncTaskUtil.getCallDetails(this, getCallLogEntryUris(), mCallLogAsyncTaskListener);

getCallDetails方法 首先调用getCallLogEntryUris方法获取Uri对象,该方法如下,

final Uri uri = getIntent().getData(); // 单条通话信息
if (uri != null) {
    // If there is a data on the intent, it takes precedence over the extra.
    return new Uri[]{ uri };
}
// 多条通话信息
final long[] ids = getIntent().getLongArrayExtra(EXTRA_CALL_LOG_IDS);
final int numIds = ids == null ? 0 : ids.length;
final Uri[] uris = new Uri[numIds];
for (int index = 0; index < numIds; ++index) {
    uris[index] = ContentUris.withAppendedId(
         TelecomUtil.getCallLogUri(CallDetailActivity.this), ids[index]);
}
return uris;

TelecomUtil的getCallLogUri方法如下,

return hasReadWriteVoicemailPermissions(context) ? Calls.CONTENT_URI_WITH_VOICEMAIL : Calls.CONTENT_URI;

CONTENT_URI  Uri定义如下,

public static final Uri CONTENT_URI =  Uri.parse("content://call_log/calls");

就是calllog对应的Uri对象。

mCallLogAsyncTaskListener是CallLogAsyncTaskUtil内部接口CallLogAsyncTaskListener的匿名实现对象. CallLogAsyncTaskListener定义如下,

public interface CallLogAsyncTaskListener {
    public void onDeleteCall();
    public void onDeleteVoicemail();
    public void onGetCallDetails(PhoneCallDetails[] details);
}

很明显,是三个回调接口,分别是异步查询完成通话记录/删除通话记录/删除Voicemail 之后的回调。

CallLogAsyncTaskUtil的getCallDetails方法逻辑如下,

1,构造线程池,

if (sAsyncTaskExecutor == null) {
    initTaskExecutor();
}

initTaskExecutor方法如下,

sAsyncTaskExecutor = AsyncTaskExecutors.createThreadPoolExecutor();

2,调用AsyncTaskExecutor的submit方法开始查询。

主要看匿名内部类AsyncTask对象的doInBackground和onPostExecute方法。

doInBackground方法如下,

1,根据通话记录条数构造PhoneCallDetails组,

final int numCalls = callUris.length;
PhoneCallDetails[] details = new PhoneCallDetails[numCalls];

2,然后逐个调用getPhoneCallDetailsForUri方法 将查询信息 封装在 PhoneCallDetails中,

for (int index = 0; index < numCalls; ++index) {
   details[index] =  getPhoneCallDetailsForUri(context, callUris[index]);
}

3,最后返回的是PhoneCallDetails组,

return details;

当然, doInBackground方法是在后台线程中执行, onPostExecute方法在UI线程中执行,

onPostExecute方法如下,

if (callLogAsyncTaskListener != null) {
   callLogAsyncTaskListener.onGetCallDetails(phoneCallDetails);
}

回调mCallLogAsyncTaskListener的onGetCallDetails方法,结果是PhoneCallDetails组。

CallLogAsyncTaskUtil的getPhoneCallDetailsForUri方法主要逻辑如下,

1,在Contacts2.db数据库里面查询call表单,获取cursor对象,

Cursor cursor = context.getContentResolver().query(
                callUri, CallDetailQuery.CALL_LOG_PROJECTION, null, null, null);

2,查询通话记录信息,并且利用将这些信息封装在PhoneCallDetails中,

PhoneCallDetails details = new PhoneCallDetails(
     context, number, numberPresentation, info.formattedNumber, isVoicemail);

PhoneCallDetails这个类比较简单,主要是一些变量,保存通话记录的信息,只有一个构造方法。

CallDetailActivity的mCallLogAsyncTaskListener的onGetCallDetails方法如下,

public void onGetCallDetails(PhoneCallDetails[] details) {

所有搜索结果都保存在PhoneCallDetails中。主要逻辑如下,

1,因为号码相同,因此首先显示第一条通话记录信息,

// We know that all calls are from the same number and the same contact, so pick the
// first.
PhoneCallDetails firstDetails = details[0];
mNumber = TextUtils.isEmpty(firstDetails.number) ? null : firstDetails.number.toString();

2,然后将其他PhoneCallDetails放入ListView中显示,

ListView historyList = (ListView) findViewById(R.id.history);
historyList.setAdapter(
   new CallDetailHistoryAdapter(mContext, mInflater, mCallTypeHelper, details));

CallDetailHistoryAdapter还是比较简单的Adapter,简单的继承BaseAdapter,

public class CallDetailHistoryAdapter extends BaseAdapter {

其getView方法主要逻辑如下,

1,加载布局资源,获取PhoneCallDetails对象,因为第一条已经显示过了,因此需要减1,并且第一条结果直接返回了,

final View result  = convertView == null
   ? mLayoutInflater.inflate(R.layout.call_detail_history_item, parent, false) : convertView;
PhoneCallDetails details = mPhoneCallDetails[position - 1];

2,为view赋值,例如,通话类型,通话时间,通话持续时间,

callTypeTextView.setText(mCallTypeHelper.getCallTypeText(callType, isVideoCall));
•••
dateView.setText(dateValue);

小结:

查询通话记录主要是异步查询加回调完成的,并且将信息封装在PhoneCallDetails对象中;

显示时利用CallDetailHistoryAdapter进行显示。

架构图如下,


2,删除通话记录

有上个小节做铺垫,删除通话记录虽然也是异步的,但是容易很多了。

在CallDetailActivity的onMenuItemClick方法中,点击时,

1,如果是删除通话记录,

case R.id.menu_remove_from_call_log:
    final StringBuilder callIds = new StringBuilder();
    for (Uri callUri : getCallLogEntryUris()) {
         •••
    CallLogAsyncTaskUtil.deleteCalls(
         this, callIds.toString(), mCallLogAsyncTaskListener);
break;

调用CallLogAsyncTaskUtil的deleteCalls方法进行删除。

2,删除Voicemail,

case R.id.menu_trash:
     CallLogAsyncTaskUtil.deleteVoicemail(
        this, mVoicemailUri, mCallLogAsyncTaskListener);
    break;

这2个都是异步在数据库中删除数据,流程完全一样。

CallLogAsyncTaskUtil的deleteCalls方法流程图如下,


deleteCalls方法中的AsyncTask对象的doInBackground方法如下,

context.getContentResolver().delete(TelecomUtil.getCallLogUri(context),
   CallLog.Calls._ID + " IN (" + callIds + ")", null);
return null;

直接对Contacts2.db数据库的calls进行删除操作。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值