为什么ContentObserver会被多次调用?
我有以下用于接收和写入短信的 ContentObserver
实现,但它被多次调用。
代码:
public class SMSObserverActivity extends Activity {
protected MyContentObserver observer = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String url = "content://mms-sms/";
Uri uri = Uri.parse(url);
observer = new MyContentObserver(new Handler());
getContentResolver().registerContentObserver(uri, true, observer);
}
@Override
protected void onDestroy(){
super.onDestroy();
getContentResolver().unregisterContentObserver(observer);
}
class MyContentObserver extends ContentObserver {
ContentValues values = new ContentValues();
Handler handler;
public MyContentObserver(Handler handler){
super(handler);
this.handler = handler;
}
@Override
public boolean deliverSelfNotifications(){
return false;
}
@Override
public void onChange(boolean arg0){
super.onChange(arg0);
Log.v("SMS", "Notification on SMS observer");
values.put("status", 5);
Message msg = new Message();
msg.obj = "xxxxxxxxxx";
int threadId = 0;
handler.sendMessage(msg);
Uri uriSMSURI = Uri.parse("content://sms/");
Cursor cur =
getContentResolver().query(uriSMSURI, null, null, null,
null);
cur.moveToNext();
Log.e("sms", cur.getString(4)+" "+cur.getString(11));
}
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SMS"></uses-permission>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".SMSObserverActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
为什么会被多次调用?
编辑:
有人认为问题是由缺少 unregisterContentObserver
引起的,但这没有什么区别。
I have following ContentObserver
implementation for receiving and writing SMS, but it is called multiple times.
Code:
public class SMSObserverActivity extends Activity {
protected MyContentObserver observer = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String url = "content://mms-sms/";
Uri uri = Uri.parse(url);
observer = new MyContentObserver(new Handler());
getContentResolver().registerContentObserver(uri, true, observer);
}
@Override
protected void onDestroy(){
super.onDestroy();
getContentResolver().unregisterContentObserver(observer);
}
class MyContentObserver extends ContentObserver {
ContentValues values = new ContentValues();
Handler handler;
public MyContentObserver(Handler handler){
super(handler);
this.handler = handler;
}
@Override
public boolean deliverSelfNotifications(){
return false;
}
@Override
public void onChange(boolean arg0){
super.onChange(arg0);
Log.v("SMS", "Notification on SMS observer");
values.put("status", 5);
Message msg = new Message();
msg.obj = "xxxxxxxxxx";
int threadId = 0;
handler.sendMessage(msg);
Uri uriSMSURI = Uri.parse("content://sms/");
Cursor cur =
getContentResolver().query(uriSMSURI, null, null, null,
null);
cur.moveToNext();
Log.e("sms", cur.getString(4)+" "+cur.getString(11));
}
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SMS"></uses-permission>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".SMSObserverActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Why is it called multiple times?
EDIT:
There was the idea that the problem is caused by the missing unregisterContentObserver
, but it makes no difference.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
发生这种情况是因为您正在为整个 SMS 数据库注册内容观察器。因此,每次数据库中的表条目更新时,您的内容观察者都会收到通知。
在这种情况下,当发送消息时,例如大约 7 个表条目会更新,因此您的内容观察者会收到 7 次通知。
由于我只对是否发送消息感兴趣,因此我已更改为仅观察排队的消息,这意味着我的观察者总是会收到三次通知,因此我已经实现了代码来防止这种情况。
可能还有一些其他问题,例如多收件人或多部分消息,但到目前为止,基础知识是有效的。
This is occurring because you are registering your content observer for the entire SMS database. So your content observer gets notified each time a table entry in the database gets updated.
In this case when a message is sent for example around 7 tables entries get updated so your content observer gets notified 7 times.
Since I'm only interested if a message is sent I've changed to only observe the queued messages and this means my observer always gets notified exactly three times so I have implemented code to protect against that.
There are likely to be some other issues such as multi recipient or multi part messages but the basics work so far.
为了避免内容观察者发送多条短信,请尝试以下操作
To avoid sending multiple sms by content observer try this
如果您希望仅在 Activity 处于活动状态时启用观察者,我建议您将
registerContentObserver()
和unregisterContentObserver()
移至方法onResume( )
和onPause()
分别。如果应用程序退出,onDestroy()
可能不会被调用,但onPause()
肯定会被调用。If you want to have your observer enabled only when the activity is in active state, I advise you to move
registerContentObserver()
andunregisterContentObserver()
to methodsonResume()
andonPause()
respectively.onDestroy()
may not be called if your application exits, butonPause()
is guaranteed to be.廉价黑客
您当前正在使用布尔参数覆盖
onChange
方法。我通过简单地覆盖接受
Uri
的问题来避免同样的问题,以便您可以比较它们。插图(科特林):
Cheap hack
You are currently overriding the
onChange
method with the boolean parameter.I circumvented the same problem by simple overriding the one that takes in the
Uri
so that you could compare them.Illustration (Kotlin):