公司项目有个需求,因为是内部人员使用的APP,需要对拨出的电话做记录,然后实时跟进每一拨电话是否接通或未接。首先想到的是PhoneStateListener这个类,但是实现后,发现“接通”这个判断并不靠谱,然后想到一些APP在注册或登录的时候,能够直接读取短信并填充实现不用手动输入验证码即可直接登录的操作,最终发现了ContentObserver的妙用,并且非常简单。
思路就是读取手机通话记录,判断当前拨出的号码与通话记录中的第一条已拨电话记录做比较,如果一致并且时长大于0既为拨出已接通。
但是实现之后有个bug,就是onChange方法会调用多次,调用多次跟进上传,最终在stackoverflow找到相关问题,并结合线程解决了这个问题。
直接上最后的代码:
public class CallContentObserver extends ContentObserver {
public Logger gLogger = Logger.getLogger(this.getClass());
private static volatile int initialPos;
private static final Uri outSMSUri = CallLog.Calls.CONTENT_URI;
private Context context;
private String address;
private Handler mHandler; //更新UI线程
ExecutorService singleThreadExecuto
public CallContentObserver(Handler handler, Context context, String number) {
super(handler);
this.context = context;
this.address = number;
this.mHandler = handler;
singleThreadExecuto= Executors.newSingleThreadExecutor();
}
public void onChange(boolean selfChange) {
super.onChange(selfChange);
gLogger.debug("on change called");
queryLastCall();
}
//标记位置防止多次调用onchange
public int getLastCallId() {
try {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
return -1;
}
Cursor cur = context.getContentResolver().query(outSMSUri, null, null, null, CallLog.Calls.DATE + " desc");
cur.moveToFirst();
int lastMsgId = cur.getInt(cur.getColumnIndex("_id"));
return lastMsgId;
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
protected void queryLastCall() {
singleThreadExecuto.execute(new Runnable() {
@Override
public void run() {
try {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
return;
}
Cursor cur =
context.getContentResolver().query(outSMSUri, null, null, null, CallLog.Calls.DATE + " desc");
if (cur.moveToNext()) {
if (initialPos != getLastCallId()) {
if(!TextUtils.isEmpty(address)){
if (cur.getString(cur.getColumnIndex("number")).contains(address)) {
int _id = cur.getInt(cur.getColumnIndex("_id"));
int type = cur.getInt(cur.getColumnIndex("type"));//通话类型,1 来电 .INCOMING_TYPE;2 已拨 .OUTGOING_;3 未接 .MISSED_
String number = cur.getString(cur.getColumnIndex("number"));// 电话号码
int duration = cur.getInt(cur.getColumnIndex("duration"));//通话时长,单位:秒
String msgObj = "\nID:" + _id + "\n类型:" + type + "\n号码:" + number + "\n时长:" + duration;
gLogger.debug(msgObj);
if(type==2){
if(duration>0){
mHandler.obtainMessage(answered, isSuccessSend).sendToTarget();
}else {
mHandler.obtainMessage(noAnswer, isSuccessSend).sendToTarget();
}
}
}
}
initialPos = getLastCallId();
}
}
cur.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
以上就是修复后的代码,目前没有发现什么问题。
同理,获取来电,或者短信记录都可以用类似的方案解决
网友评论