公司項(xiàng)目有個(gè)需求锨苏,因?yàn)槭莾?nèi)部人員使用的APP公罕,需要對(duì)撥出的電話(huà)做記錄翠胰,然后實(shí)時(shí)跟進(jìn)每一撥電話(huà)是否接通或未接容贝。首先想到的是PhoneStateListener這個(gè)類(lèi),但是實(shí)現(xiàn)后之景,發(fā)現(xiàn)“接通”這個(gè)判斷并不靠譜斤富,然后想到一些APP在注冊(cè)或登錄的時(shí)候,能夠直接讀取短信并填充實(shí)現(xiàn)不用手動(dòng)輸入驗(yàn)證碼即可直接登錄的操作锻狗,最終發(fā)現(xiàn)了ContentObserver的妙用满力,并且非常簡(jiǎn)單焕参。
思路就是讀取手機(jī)通話(huà)記錄,判斷當(dāng)前撥出的號(hào)碼與通話(huà)記錄中的第一條已撥電話(huà)記錄做比較油额,如果一致并且時(shí)長(zhǎng)大于0既為撥出已接通叠纷。
但是實(shí)現(xiàn)之后有個(gè)bug,就是onChange方法會(huì)調(diào)用多次悔耘,調(diào)用多次跟進(jìn)上傳讲岁,最終在stackoverflow找到相關(guān)問(wèn)題,并結(jié)合線程解決了這個(gè)問(wèn)題衬以。
直接上最后的代碼:
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();
}
//標(biāo)記位置防止多次調(diào)用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"));//通話(huà)類(lèi)型缓艳,1 來(lái)電 .INCOMING_TYPE;2 已撥 .OUTGOING_看峻;3 未接 .MISSED_
String number = cur.getString(cur.getColumnIndex("number"));// 電話(huà)號(hào)碼
int duration = cur.getInt(cur.getColumnIndex("duration"));//通話(huà)時(shí)長(zhǎng)阶淘,單位:秒
String msgObj = "\nID:" + _id + "\n類(lèi)型:" + type + "\n號(hào)碼:" + number + "\n時(shí)長(zhǎng):" + 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();
}
}
});
}
}
以上就是修復(fù)后的代碼,目前沒(méi)有發(fā)現(xiàn)什么問(wèn)題互妓。
同理溪窒,獲取來(lái)電,或者短信記錄都可以用類(lèi)似的方案解決