Skip to content
This repository has been archived by the owner on Aug 17, 2020. It is now read-only.

Content resolver Observable produces duplicates sometimes/usually #72

Closed
djensen47 opened this issue Nov 3, 2015 · 7 comments
Closed

Comments

@djensen47
Copy link

Sorry about the cryptic title. The issue is better expressed with some code and an explanation.

I'm creating an Observable for listening to sms messages, specifically I care about sent messages.

Observable<SqlBrite.Query> query = resolver.createQuery(Uri.parse("content://sms/"), null, null, null, null, true);

subscription = query
    // Ignore first immediately emitted value
  .skip(1)
    // read the query, output Message object, which has data from the cursor
  .flatMap(…) 
    // filter everything except sent messages
  .filter(…)
    // Only unique messages
  .distinct(…)
    // We only care about certain keyword in the message
  .filter(…)
    // Show a dialog box
  .compose(…)
    // Filter out if user canceled dialog
  .filter(…)
  .subscribeOn(Schedulers.io())
  .observeOn(scheduler)
  .subscribe(…);

Even after filtering on "sent" I'll get about 5 or 6 Messageobjects per actual sent sms message. When I first push a build to my phone, everything works as expected. Some unknown time later (I usually notice the next day) two identical Message objects pass distinct(). Specifically the first two.

Message has correctly implemented equals() and hashCode().

This may or may not be an issue with SqlBrite but I've been battling this for a while so I'm exploring all of my options. (I have a similar message out on the RxJava mailing list).

@djensen47
Copy link
Author

The problem is in my compose(…) method. Not sure why. 😕

@djensen47
Copy link
Author

I removed the compose step (with the dialog box) and put the dialog box in the subscriber, where it probably belongs. It worked just fine until I rebooted the phone for about 18 hours and now, once again, is not working.

@djensen47 djensen47 reopened this Nov 4, 2015
@djensen47
Copy link
Author

The regression occurs after I reboot the phone and happens on more than one device.

@AlecKazakova
Copy link
Member

Can you expand at all on what you're doing inside of flatMap and distinct? Do you flatmap a query into multiple Messages or just a single Message? Do you have to wait at all before rebooting the phone to see the bug, or are you able to reproduce by just rebooting the phone and then sending an sms regardless of how long your app has been active? Just trying to get a picture of what's creating the bug so I can reproduce myself.

@djensen47
Copy link
Author

Can you expand at all on what you're doing inside of … distinct?

In my latest test, I'm using distinct without a function. My Message class has a properly implemented equals() and hashCode(). My understanding is the hashCode is the important method for distinct.

Do you flatmap a query into multiple Messages or just a single Message?

Single Message, I only want the latest.

Do you have to wait at all before rebooting the phone to see the bug, or are you able to reproduce by just rebooting the phone and then sending an sms regardless of how long your app has been active?

I don't have to wait and it doesn't change if I do wait. After reboot, it always happens. If I adb install a new release (or OTA update), the problem "goes away."

Can you expand at all on what you're doing inside of flatMap …?

.flatMap( (Func1) (query) -> {
  Message message = new Message();

  Cursor cursor = query.run();
  if (cursor.getCount() > 0) {
    cursor.moveToNext();
    String body = cursor.getString(cursor.getColumnIndex("body"));
    int type = cursor.getInt(cursor.getColumnIndex(SMS_COLUMN_TYPE));
    Long datetime = cursor.getLong(cursor.getColumnIndex(SMS_COLUMN_DATE));

    message.setStatusFromType(type);
    message.message = body;
    message.to = cursor.getString(cursor.getColumnIndex(SMS_COLUMN_ADDRESS));
    message.datetime = datetime;
  }

  return Observable.just((Message) message);
});

@djensen47
Copy link
Author

The phones I've tried:

  • OnePlus One with CM12S Android 5.1.1
  • Samsung Alpha with Android 5.0.2
  • Genymotion "HTC One 4.4.4"
  • more to come

@djensen47
Copy link
Author

"Multithreading is hard" might be the answer to my problem. I'm trying to ensure that my background service is started no matter what. Both on boot and when the Application is started. I'm guessing onCreate is called twice and my stream is set up twice on boot.

Ugh, if this is the case and it's likely, sorry about all of this noise. 😔 😞

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants