关于监听联系人变化的问题与解决方法探讨
需要注意的问题:文中的ContentObserve的使用是一个非常好的主意;不过在两个数据库的监听和Handler消息发送上容易出问题。
建议改为对联系人data表的监听:
部分主要代码如下:
1.
//注册监听联系人数据库 Uri uri=Uri.parse("content://com.android.contacts/data"); getContentResolver().registerContentObserver(uri, true, mContactObserver);
2.
/** * 系统联系人数据库监控器 */ public ContentObserver mContactObserver=new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { super.onChange(selfChange); //当系统联系人数据库发生更改时触发此操作 LogUtil.d(TAG, "SYS CONTACT CHANGE"); // //去掉多余的或者重复的同步 // mHandler.removeMessages(CONTACT_CHANGE); //延时ELAPSE_TIME(10秒)发送同步信号CONTACT_CHANGE mHandler.sendEmptyMessageDelayed(CONTACT_CHANGE, ELAPSE_TIME); } };
原文转自:
http://www.eoeandroid.com/forum.php?mod=viewthread&tid=234378
由于最近做的项目Any.ONE中需要缓冲联系人数据库,遇到很狗血的是,Android只能监听整个数据库的改变,更狗血的是,当你监听联系人数据库时,通话记录改变,也就是打一下电话什么的,也会触发前面的监听器!具体原因,查看了一下资料,主要是联系人数据库中有“联系次数"、”最后通话时间“等字段,所以每次打电话都会更新联系人数据库。
始终查不到比较完美的解决方法,这里展示出我的比较折中的解决办法,主要思路是同时监听联系人数据库和通话记录数据库,如果两个监听器都触发了,则认为这仅仅是打了一次电话,如果只有联系人数据库的监听器被触发了,则认为是真正的联系人被更改了,从而做出相应的处理。当然,这是一种折中的处理,会有一些“意外”,不过一般都不会出现而且可被接受。
如果哪位大神对“监听联系人变化”这个问题有比较好的方法,希望提供出来研讨一下,谢谢~
下面是解决代码片段,带详细注释,是一个Service来的,稍作修改即可直接使用:
[mw_shl_code=java,true]package tk.linshuaibin.any.one;
import android.app.Service;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.util.Log;
public class ContacterSyncService extends Service {
private final static String TAG = "Any.ONE.ContacterSyncService";
//延时处理同步联系人,若在延时期间,通话记录数据库未改变,即判断为联系人被改变了
private final static int ELAPSE_TIME = 10000;
private Handler mHandler = null;
public ContentObserver mObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
// 当系统联系人数据库发生更改时触发此操作
Log.i(TAG, "Catact");
//去掉多余的或者重复的同步
mHandler.removeMessages(0);
//延时ELAPSE_TIME(10秒)发送同步信号“0”
mHandler.sendEmptyMessageDelayed(0, ELAPSE_TIME);
}
};
// 当通话记录数据库发生更改时触发此操作
private ContentObserver mCallLogObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
// 当通话记录数据库发生更改时触发此操作
Log.i(TAG, "CallLog");
//如果延时期间发现通话记录数据库也改变了,即判断为联系人未被改变,取消前面的同步
mHandler.removeMessages(0);
}
};
//在此处处理联系人被修改后应该执行的操作
public void updataContact() {
//DO SOMETHING HERE...
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "OnCreate");
//注册监听通话记录数据库
getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, true, mCallLogObserver);
//注册监听联系人数据库
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, mObserver);
//为了避免同步联系人时阻塞主线程,此处获取一个子线程的handler
new Thread(new Runnable() {
public void run() {
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
updataContact();
break;
default:
break;
}
}
};
Looper.loop();
}
}).start();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return flags;
}
}
[/mw_shl_code]