Функция Onchange класса content observer вызывается более одного раза

#android

#Android

Вопрос:

Я использую a contentObserver для мониторинга содержимого sms content provider , я поместил Log.d() тег для отладки, и тег в logcat просматривается более одного раза, что означает, что onchange() идентификатор вызывается более одного раза, как мне предотвратить это? Я внедрил observer в службу, работающую в фоновом режиме. Вот код

 package com.messageHider;

 import android.app.Service;
 import android.content.ContentResolver;
 import android.content.Intent;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
 import android.util.Log;
 import android.widget.Toast;

 public class smsSentService extends Service {
ContentResolver contentResolver;
Uri uri=Uri.parse("content://sms/");
Handler handler;
@Override
public IBinder onBind(Intent arg0) {
    return null;
}
@Override
public void onCreate() {
    contentResolver=getContentResolver();
    contentResolver.registerContentObserver(uri, true, new contentObserver(handler));
    Log.d("SENTSERVICE", "Service created");
    super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
    Log.d("SENTSERVICE", "Service started");
    super.onStart(intent, startId);
}
@Override
public void onDestroy() {
    super.onDestroy();
}
public class contentObserver extends ContentObserver
{
    public contentObserver(Handler handler) {
        super(handler);

    }
    @Override
    public void onChange(boolean selfChange) {
        Cursor cursor=contentResolver.query(uri, null, null, null, null);
        cursor.moveToFirst();
        String type=cursor.getString(cursor.getColumnIndex("type"));
        Log.d("THEMESSAGE", type);
        super.onChange(selfChange);
    }
}
  

}


Ответ №1:

Просто рекомендация: зарегистрируйте content observer в методе onResume и отмените его регистрацию в onPause.

Ответ №2:

Я использовал content observer для просмотра исходящих SMS-сообщений и заметил, что если вы попытаетесь отправить исходящее SMS из эмулятора, вы на самом деле увидите, что 3 его экземпляра прошли, потому что он пытался повторно отправить текст, но потерпел неудачу. Вы также видите это для входящих текстовых сообщений?

Если это только для исходящих SMS-сообщений, тогда посмотрите на поле статуса SMS. Значение -1 указывает на сбой.

Ответ №3:

Вам нужно переопределить функцию deliverSelfNotifications(), чтобы вернуть значение true.

 class contentObserver extends ContentObserver { private Context mContext;

    public contentObserver(Handler handler) {
        super(handler);

    }

    @Override
    public void onChange(boolean selfChange) {
        Cursor cursor=contentResolver.query(uri, null, null, null, null);
        cursor.moveToFirst();
        String type=cursor.getString(cursor.getColumnIndex("type"));
        Log.d("THEMESSAGE", type);
        super.onChange(selfChange);
    }

    @Override
    public boolean deliverSelfNotifications() {
        return true;
    }
}
  

Комментарии:

1. Я переопределяю функцию deliverSelfNotifications (), тогда и onChange () вызывается дважды.

Ответ №4:

Чтобы просматривать содержимое того, что вы хотите, вы должны зарегистрировать observer так, как у вас есть. Однако обратный вызов onChange вызывается с разными флагами, например ContentResolver.NOTIFY_INSERT или ContentResolver.NOTIFY_UPDATE и другими, что означает, что некоторый контент только что был вставлен или обновлен. Итак, внутри вашего ContentObserver, возможно, вам нужно проверить событие, которое вызвало обратный вызов

 private val contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
        override fun onChange(selfChange: Boolean, uri: Uri?, flags: Int) {
            super.onChange(selfChange, uri, flags)

            uri?.let {
                if (flags == ContentResolver.NOTIFY_INSERT)
                    // do something
            }
        }
    }



....
contentResolver.registerContentObserver(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, contentObserver
        )
  

В приведенном выше примере просматривается содержимое нового изображения, вставленного из приложения. Я не знаю, как это могло бы помочь в вашем примере, но у меня возникла та же проблема, что и у вас, пока я не проверил флаг

Надеюсь, это помогло ..!