@Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.deviations_row);

    Log.d(TAG, "details!?");

    /*Bundle extras = getIntent().getExtras();
    Deviation deviation = extras.getParcelable(EXTRA_DEVIATION);
    if (extras.containsKey(EXTRA_DEVIATION_NOTIFICATION_ID)) {
        int notificationId = extras.getInt(EXTRA_DEVIATION_NOTIFICATION_ID);
        NotificationManager mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        mNotificationManager.cancel(notificationId);
    }*/

    final Uri uri = getIntent().getData();
    String header = uri.getQueryParameter("header");
    String details = uri.getQueryParameter("details");
    String scope = uri.getQueryParameter("scope");
    String reference = uri.getQueryParameter("reference");
    Time created = new Time();
    created.parse3339(uri.getQueryParameter("created"));
    int notificationId = Integer.parseInt(uri.getQueryParameter("notificationId"));

    TextView headerView = (TextView) findViewById(R.id.deviation_header);
    headerView.setText(header);
    TextView detailsView = (TextView) findViewById(R.id.deviation_details);
    detailsView.setText(details);
    TextView createdView = (TextView) findViewById(R.id.deviation_created);
    createdView.setText(created.format("%F %R"));

    NotificationManager mNotificationManager =
        (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    mNotificationManager.cancel(notificationId);
  }
  private long parse3339(String time) {
    if (time == null || time.length() == 0) {
      return 0;
    }

    if (timestamper != null) {
      try {
        timestamper.parse3339(time);
      } catch (TimeFormatException e) {
        parse_trace("got TimeFormatException parsing timestamp: \"" + time + '"');
        e.printStackTrace();
        return 0;
      }

      return timestamper.normalize(false);
    } else {
      Date timestamp = new Date();

      SimpleDateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
      rfc3339.setLenient(true);

      try {
        timestamp = rfc3339.parse(time);
      } catch (ParseException e) {
        parse_trace("got ParseException parsing timestamp: \"" + time + '"');
        e.printStackTrace();
        return 0;
      }

      return timestamp.getTime();
    }
  }
  /**
   * Parse a NWS date string into a Unix timestamp. Assumes incoming values are in the format
   * "2009-03-23T18:00:00-07:00", which we adjust slightly to correctly follow RFC 3339 before
   * parsing.
   */
  private static long parseDate(String raw) throws TimeFormatException {
    // Inject milliseconds so that NWS dates follow RFC
    sEditable.clear();
    sEditable.append(raw);
    sEditable.insert(19, ".000");

    String rfcFormat = sEditable.toString();
    sTime.parse3339(rfcFormat);
    return sTime.toMillis(false);
  }
Example #4
0
 public static Time timeFrom3339(String s3339) {
   final android.text.format.Time time = new Time();
   if (TextUtils.isEmpty(s3339)) {
     return time;
   }
   try {
     time.parse3339(s3339);
   } catch (TimeFormatException e) {
     return time;
   }
   time.switchTimezone(android.text.format.Time.getCurrentTimezone());
   return time;
 }
  /**
   * Clear out the map and stuff an Entry into it in a format that can be inserted into a content
   * provider.
   *
   * <p>If a date is before 1970 or past 2038, ENTRY_INVALID is returned, and DTSTART is set to -1.
   * This is due to the current 32-bit time restriction and will be fixed in a future release.
   *
   * @return ENTRY_OK, ENTRY_DELETED, or ENTRY_INVALID
   */
  private int entryToContentValues(
      EventEntry event, Long syncLocalId, ContentValues map, Object info) {
    SyncInfo syncInfo = (SyncInfo) info;

    // There are 3 cases for parsing a date-time string:
    //
    // 1. The date-time string specifies a date and time with a time offset.
    //    (The "normal" format.)
    // 2. The date-time string is just a date, used for all-day events,
    //    with no time or time offset fields. (The "all-day" format.)
    // 3. The date-time string specifies a date and time, but no time
    //    offset.  (The "floating" format, not supported yet.)
    //
    // Case 1: Time.parse3339() converts the date-time string to UTC and
    // sets the Time.timezone to UTC.  It does not matter what the initial
    // Time.timezone field was set to.  The initial timezone is ignored.
    //
    // Case 2: The date-time string doesn't specify the time.
    // Time.parse3339() just sets the date but not the time (hour, minute,
    // second) fields.  (The time fields should be zero, meaning midnight.)
    // This code then sets the timezone to UTC (because this is an all-day
    // event).  It does not matter in this case either what the initial
    // Time.timezone field was set to.
    //
    // Case 3: This is a "floating time" (which we do not support yet).
    // In this case, it will matter what the initial Time.timezone is set
    // to.  It should use UTC.  If I specify a floating time of 1pm then I
    // want that event displayed at 1pm in every timezone.  The easiest way
    // to support this would be store it as 1pm in UTC and mark the event
    // as "isFloating" (with a new database column).  Then when displaying
    // the event, the code checks "isFloating" and just leaves the time at
    // 1pm without doing any conversion to the local timezone.
    //
    // So in all cases, it is correct to set the Time.timezone to UTC.
    Time time = new Time(Time.TIMEZONE_UTC);

    map.clear();

    // Base sync info
    map.put(Events._SYNC_ID, event.getId());
    String version = event.getEditUri();
    if (!StringUtils.isEmpty(version)) {
      // Always rewrite the edit URL to https for dasher account to avoid
      // redirection.
      map.put(Events._SYNC_VERSION, rewriteUrlforAccount(getAccount(), version));
    }

    // see if this is an exception to an existing event/recurrence.
    String originalId = event.getOriginalEventId();
    String originalStartTime = event.getOriginalEventStartTime();
    boolean isRecurrenceException = false;
    if (!StringUtils.isEmpty(originalId) && !StringUtils.isEmpty(originalStartTime)) {
      isRecurrenceException = true;
      time.parse3339(originalStartTime);
      map.put(Events.ORIGINAL_EVENT, originalId);
      map.put(Events.ORIGINAL_INSTANCE_TIME, time.toMillis(false /* use isDst */));
      map.put(Events.ORIGINAL_ALL_DAY, time.allDay ? 1 : 0);
    }

    // Event status
    byte status = event.getStatus();
    switch (status) {
      case EventEntry.STATUS_CANCELED:
        if (!isRecurrenceException) {
          return ENTRY_DELETED;
        }
        map.put(Events.STATUS, sCanceledStatus);
        break;
      case EventEntry.STATUS_TENTATIVE:
        map.put(Events.STATUS, sTentativeStatus);
        break;
      case EventEntry.STATUS_CONFIRMED:
        map.put(Events.STATUS, sConfirmedStatus);
        break;
      default:
        // should not happen
        return ENTRY_INVALID;
    }

    map.put(Events._SYNC_LOCAL_ID, syncLocalId);

    // Updated time, only needed for non-deleted items
    String updated = event.getUpdateDate();
    map.put(Events._SYNC_TIME, updated);
    map.put(Events._SYNC_DIRTY, 0);

    // visibility
    switch (event.getVisibility()) {
      case EventEntry.VISIBILITY_DEFAULT:
        map.put(Events.VISIBILITY, Events.VISIBILITY_DEFAULT);
        break;
      case EventEntry.VISIBILITY_CONFIDENTIAL:
        map.put(Events.VISIBILITY, Events.VISIBILITY_CONFIDENTIAL);
        break;
      case EventEntry.VISIBILITY_PRIVATE:
        map.put(Events.VISIBILITY, Events.VISIBILITY_PRIVATE);
        break;
      case EventEntry.VISIBILITY_PUBLIC:
        map.put(Events.VISIBILITY, Events.VISIBILITY_PUBLIC);
        break;
      default:
        // should not happen
        Log.e(TAG, "Unexpected visibility " + event.getVisibility());
        return ENTRY_INVALID;
    }

    // transparency
    switch (event.getTransparency()) {
      case EventEntry.TRANSPARENCY_OPAQUE:
        map.put(Events.TRANSPARENCY, Events.TRANSPARENCY_OPAQUE);
        break;
      case EventEntry.TRANSPARENCY_TRANSPARENT:
        map.put(Events.TRANSPARENCY, Events.TRANSPARENCY_TRANSPARENT);
        break;
      default:
        // should not happen
        Log.e(TAG, "Unexpected transparency " + event.getTransparency());
        return ENTRY_INVALID;
    }

    // html uri
    String htmlUri = event.getHtmlUri();
    if (!StringUtils.isEmpty(htmlUri)) {
      // TODO: convert this desktop url into a mobile one?
      // htmlUri = htmlUri.replace("/event?", "/mevent?"); // but a little more robust
      map.put(Events.HTML_URI, htmlUri);
    }

    // title
    String title = event.getTitle();
    if (!StringUtils.isEmpty(title)) {
      map.put(Events.TITLE, title);
    }

    // content
    String content = event.getContent();
    if (!StringUtils.isEmpty(content)) {
      map.put(Events.DESCRIPTION, content);
    }

    // where
    String where = event.getWhere();
    if (!StringUtils.isEmpty(where)) {
      map.put(Events.EVENT_LOCATION, where);
    }

    // Calendar ID
    map.put(Events.CALENDAR_ID, syncInfo.calendarId);

    // comments uri
    String commentsUri = event.getCommentsUri();
    if (commentsUri != null) {
      map.put(Events.COMMENTS_URI, commentsUri);
    }

    boolean timesSet = false;

    // see if there are any reminders for this event
    if (event.getReminders() != null) {
      // just store that we have reminders.  the caller will have
      // to update the reminders table separately.
      map.put(Events.HAS_ALARM, 1);
    }

    // see if there are any extended properties for this event
    if (event.getExtendedProperties() != null) {
      // just store that we have extended properties.  the caller will have
      // to update the extendedproperties table separately.
      map.put(Events.HAS_EXTENDED_PROPERTIES, 1);
    }

    // dtstart & dtend
    When when = event.getFirstWhen();
    if (when != null) {
      String startTime = when.getStartTime();
      if (!StringUtils.isEmpty(startTime)) {
        time.parse3339(startTime);

        // we also stash away the event's timezone.
        // this timezone might get overwritten below, if this event is
        // a recurrence (recurrences are defined in terms of the
        // timezone of the creator of the event).
        // note that we treat all day events as occurring in the UTC timezone, so
        // an event on 05/08/2007 occurs on 05/08/2007, no matter what timezone the device
        // is in.
        // TODO: handle the "floating" timezone.
        if (time.allDay) {
          map.put(Events.ALL_DAY, 1);
          map.put(Events.EVENT_TIMEZONE, Time.TIMEZONE_UTC);
        } else {
          map.put(Events.EVENT_TIMEZONE, syncInfo.calendarTimezone);
        }

        long dtstart = time.toMillis(false /* use isDst */);
        if (dtstart < 0) {
          if (Config.LOGD) {
            Log.d(TAG, "dtstart out of range: " + startTime);
          }
          map.put(Events.DTSTART, -1); // Flag to caller that date is out of range
          return ENTRY_INVALID;
        }
        map.put(Events.DTSTART, dtstart);

        timesSet = true;
      }

      String endTime = when.getEndTime();
      if (!StringUtils.isEmpty(endTime)) {
        time.parse3339(endTime);
        long dtend = time.toMillis(false /* use isDst */);
        if (dtend < 0) {
          if (Config.LOGD) {
            Log.d(TAG, "dtend out of range: " + endTime);
          }
          map.put(Events.DTSTART, -1); // Flag to caller that date is out of range
          return ENTRY_INVALID;
        }
        map.put(Events.DTEND, dtend);
      }
    }

    // rrule
    String recurrence = event.getRecurrence();
    if (!TextUtils.isEmpty(recurrence)) {
      ICalendar.Component recurrenceComponent = new ICalendar.Component("DUMMY", null /* parent */);
      ICalendar ical = null;
      try {
        ICalendar.parseComponent(recurrenceComponent, recurrence);
      } catch (ICalendar.FormatException fe) {
        if (Config.LOGD) {
          Log.d(TAG, "Unable to parse recurrence: " + recurrence);
        }
        return ENTRY_INVALID;
      }

      if (!RecurrenceSet.populateContentValues(recurrenceComponent, map)) {
        return ENTRY_INVALID;
      }

      timesSet = true;
    }

    if (!timesSet) {
      return ENTRY_INVALID;
    }

    map.put(SyncConstValue._SYNC_ACCOUNT, getAccount());
    return ENTRY_OK;
  }
Example #6
0
 /**
  * Parse the given string as a RFC 3339 timestamp, returning the value as milliseconds since the
  * epoch.
  */
 public static long parseTime(String time) {
   sTime.parse3339(time);
   return sTime.toMillis(false);
 }
Example #7
0
    protected void showDonationView(int status) {
      HashMap<String, Time> donations = new HashMap<String, Time>();
      if (mCursor.moveToFirst()) {
        do {
          String productId = mCursor.getString(mCursor.getColumnIndex(Donations.PRODUCT_ID));
          Time time = new Time();
          String purchaseTime = mCursor.getString(mCursor.getColumnIndex(Donations.PURCHASE_TIME));
          time.parse3339(purchaseTime);
          donations.put(productId, time);
        } while (mCursor.moveToNext());
      }

      TextView tv = (TextView) findViewById(R.id.donate_text);

      if (status == BILLING_CANNOT_CONNECT) {
        tv.setText(
            "ERROR:\nCannot connect to Google Play application. Your version of app"
                + " may be out of date. You can continue to use this app but certain"
                + " features may not be available.");
      } else if (status == BILLING_NOT_SUPPORTED) {
        tv.setText(
            "ERROR:\nGoogle Play in-app billing is not available this time. You can"
                + " continue to use this app but certain features may not be available.");
      } else if (status == BILLING_ERROR_RESTORE) {
        tv.setText(
            "ERROR:\nThere was an error trying to restore your past donations. This"
                + " could be a temporary failure. Please try again later.");
      } else {
        tv.setText(
            "Please consider donating to help me recover my costs to develop"
                + " the app and provide you with data updates. You may also choose not to"
                + " donate at all and that is fine too."
                + "\n\n"
                + "You will be redirected to Google Play checkout to allow you to securely"
                + " complete your payment transaction."
                + "\n\n"
                + "Please donate generously to show your appreciation.");

        tv = (TextView) findViewById(R.id.donate_level_label);
        LinearLayout layout = (LinearLayout) findViewById(R.id.donate_level_layout);
        layout.removeAllViews();

        int count = mDonationLevels.length - donations.size();
        for (int i = 0; i < mDonationLevels.length; ++i) {
          DonationLevel level = mDonationLevels[i];
          if (!donations.containsKey(level.productId)) {
            View row = addRow(layout, level.description, FormatUtils.formatCurrency(level.amount));
            row.setTag(level.productId);
            row.setOnClickListener(this);
            row.setBackgroundResource(UiUtils.getRowSelector(i, count));
          }
        }

        if (layout.getChildCount() > 0) {
          tv.setVisibility(View.VISIBLE);
          layout.setVisibility(View.VISIBLE);
        } else {
          tv.setVisibility(View.GONE);
          layout.setVisibility(View.GONE);
        }
      }

      tv = (TextView) findViewById(R.id.donate_text2);
      LinearLayout layout = (LinearLayout) findViewById(R.id.past_donations_layout);
      layout.removeAllViews();
      if (donations.isEmpty()) {
        Application.sDonationDone = false;
        addRow(layout, "No donations made yet");
        tv.setVisibility(View.GONE);
      } else {
        Application.sDonationDone = true;
        for (String productId : donations.keySet()) {
          Time time = donations.get(productId);
          DonationLevel level = getDonationLevel(productId);
          if (level != null) {
            addRow(
                layout,
                TimeUtils.formatDateTimeLocal(getActivity(), time.toMillis(true)),
                FormatUtils.formatCurrency(level.amount));
          }
        }

        tv.setText(
            "You can restore the above donations on your other devices by"
                + " simply visiting this screen on those devices.");
        tv.setVisibility(View.VISIBLE);
      }

      setContentShown(true);
    }