Beispiel #1
0
  @Override
  protected void doWork(final Intent i) {
    final Prefs prefs = new Prefs(getBaseContext());
    final Config conf;
    try {
      conf = prefs.asConfig();
    } catch (final JSONException e) {
      LOG.w("Can not send to Hosaka: %s", e.toString());
      return;
    }

    // XXX Currently this assumes only one Hosaka account.
    // TODO Make UI stop user adding more than one Hosaka account.

    final Account account = conf.firstAccountOfType(AccountProvider.HOSAKA);
    if (account == null) {
      LOG.i("Not sending to Hosaka: no account found.");
      return;
    }

    if (!waitForDbReady()) return;
    final DbInterface db = getDb();

    SaveScrollNow.requestAndWaitForUiToSaveScroll(db);

    final Map<String, Column> hashToCol = new HashMap<String, Column>();
    final Map<String, HosakaColumn> toPush = new HashMap<String, HosakaColumn>();
    for (final Column col : conf.getColumns()) {
      if (InternalColumnType.fromColumn(col) != null) continue; // Do not sync internal columns.

      final String hash = HosakaColumn.columnHash(col, conf);
      hashToCol.put(hash, col);
      final ScrollState ss = db.getScroll(col.getId());
      if (ss == null) continue; // In case of (new) empty columns.
      // Always add all columns, even if sent before new values.
      // - Old / regressed values will be filtered server side.
      // - Values sent can be used to filter response.
      // - Also useful as do not know state of remote DB.
      toPush.put(
          hash,
          new HosakaColumn(
              null /* ss.getItemId(); TODO ScrollState to also store sid? */,
              ss.getItemTime(),
              ss.getUnreadTime(),
              ss.getScrollDirection()));
    }

    final HosakaProvider prov = new HosakaProvider();
    try {
      // Make POST even if not really sending anything new, as may be fetching new state.
      final long startTime = now();
      final Map<String, HosakaColumn> returnedColumns = prov.sendColumns(account, toPush);
      final long durationMillis = TimeUnit.NANOSECONDS.toMillis(now() - startTime);
      LOG.i("Sent %s in %d millis: %s", account.getAccessToken(), durationMillis, toPush);

      final boolean syncScroll =
          prefs.getSharedPreferences().getBoolean(FetchingPrefFragment.KEY_SYNC_SCROLL, false);

      final Map<Column, ScrollState> colToNewScroll = new HashMap<Column, ScrollState>();
      for (final Entry<String, HosakaColumn> e : returnedColumns.entrySet()) {
        final String hash = e.getKey();
        final Column col = hashToCol.get(hash);
        final HosakaColumn before = toPush.get(hash);
        final HosakaColumn after = e.getValue();
        if (col != null
            && before != null
            && (after.getUnreadTime() > before.getUnreadTime()
                || (syncScroll
                    && before.getScrollDirection() == ScrollDirection.UP
                    && after.getItemTime() > before.getItemTime()))) {
          colToNewScroll.put(col, after.toScrollState());
        }
      }
      db.mergeAndStoreScrolls(
          colToNewScroll,
          syncScroll ? ScrollChangeType.UNREAD_AND_SCROLL : ScrollChangeType.UNREAD);
      LOG.i("Merged %s columns: %s.", colToNewScroll.size(), colToNewScroll);

      storeResult(db, toPush.size(), colToNewScroll.size(), null);
    } catch (final IOException e) {
      storeResult(db, toPush.size(), 0, e);
    } catch (final JSONException e) {
      storeResult(db, toPush.size(), 0, e);
    } finally {
      prov.shutdown();
    }
  }
Beispiel #2
0
 public static InternalColumnType fromColumn(final Column col) {
   for (final InternalColumnType t : InternalColumnType.values()) {
     if (t.matchesColumn(col)) return t;
   }
   return null;
 }