@Override public String toString() { // Static class, so the time in this toString will not reflect the // home tz settings. This should only affect debugging. Time time = new Time(); StringBuilder sb = new StringBuilder(); time.setJulianDay(start); time.normalize(false); sb.append("Start:").append(time.toString()); time.setJulianDay(end); time.normalize(false); sb.append(" End:").append(time.toString()); sb.append(" Offset:").append(offset); sb.append(" Size:").append(size); return sb.toString(); }
// To make it easy to query for the exact date, we normalize all dates that go into // the database to the start of the the Julian day at UTC. public static long normalizeDate(long startDate) { // normalize the start date to the beginning of the (UTC) day Time time = new Time(); time.set(startDate); int julianDay = Time.getJulianDay(startDate, time.gmtoff); return time.setJulianDay(julianDay); }
public static long normalizeDate(long startDate) { Time time = new Time(); time.set(startDate); int julianDay = Time.getJulianDay(startDate, time.gmtoff); return time.setJulianDay(julianDay); }
// Do a "snap to start of month" fling private void doFling(float velocityY) { // Stop the list-view movement and take over MotionEvent cancelEvent = MotionEvent.obtain( mDownActionTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0); onTouchEvent(cancelEvent); // Below the threshold, fling one month. Above the threshold , fling // according to the speed of the fling. int monthsToJump; if (Math.abs(velocityY) < MULTIPLE_MONTH_VELOCITY_THRESHOLD) { if (velocityY < 0) { monthsToJump = 1; } else { // value here is zero and not -1 since by the time the fling is // detected the list moved back one month. monthsToJump = 0; } } else { if (velocityY < 0) { monthsToJump = 1 - (int) ((velocityY + MULTIPLE_MONTH_VELOCITY_THRESHOLD) / FLING_VELOCITY_DIVIDER); } else { monthsToJump = -(int) ((velocityY - MULTIPLE_MONTH_VELOCITY_THRESHOLD) / FLING_VELOCITY_DIVIDER); } } // Get the day at the top right corner int day = getUpperRightJulianDay(); // Get the day of the first day of the next/previous month // (according to scroll direction) mTempTime.setJulianDay(day); mTempTime.monthDay = 1; mTempTime.month += monthsToJump; long timeInMillis = mTempTime.normalize(false); // Since each view is 7 days, round the target day up to make sure the // scroll will be at least one view. int scrollToDay = Time.getJulianDay(timeInMillis, mTempTime.gmtoff) + ((monthsToJump > 0) ? 6 : 0); // Since all views have the same height, scroll by pixels instead of // "to position". // Compensate for the top view offset from the top. View firstView = getChildAt(0); int firstViewHeight = firstView.getHeight(); // Get visible part length firstView.getLocalVisibleRect(mFirstViewRect); int topViewVisiblePart = mFirstViewRect.bottom - mFirstViewRect.top; int viewsToFling = (scrollToDay - day) / 7 - ((monthsToJump <= 0) ? 1 : 0); int offset = (viewsToFling > 0) ? -(firstViewHeight - topViewVisiblePart + SimpleDayPickerFragment.LIST_TOP_OFFSET) : (topViewVisiblePart - SimpleDayPickerFragment.LIST_TOP_OFFSET); // Fling smoothScrollBy(viewsToFling * firstViewHeight + offset, FLING_TIME); }
private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays) throws JSONException { final String OWM_LIST = "list"; final String OWM_WEATHER = "weather"; final String OWM_TEMPERATURE = "temp"; final String OWM_MAX = "max"; final String OWM_MIN = "min"; final String OWM_DESCRIPTION = "main"; if (forecastJsonStr == null) { return null; } JSONObject forecastJson = new JSONObject(forecastJsonStr); if (forecastJson == null) { return null; } JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST); if (weatherArray == null || weatherArray.length() == 0) { return null; } Time dayTime = new Time(); dayTime.setToNow(); int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff); dayTime = new Time(); String[] resultStr = new String[numDays]; for (int i = 0; i < weatherArray.length(); i++) { String day; String desciption; String highAndLow; JSONObject dayForecast = weatherArray.getJSONObject(i); long dateTime; dateTime = dayTime.setJulianDay(julianStartDay + i); day = getReadableDateString(dateTime); JSONObject weatherObject = (JSONObject) dayForecast.getJSONArray(OWM_WEATHER).get(0); desciption = weatherObject.getString(OWM_DESCRIPTION); JSONObject temperature = dayForecast.getJSONObject(OWM_TEMPERATURE); double high = temperature.getLong(OWM_MAX); double low = temperature.getLong(OWM_MIN); highAndLow = formatHighLow(high, low); resultStr[i] = day + " - " + desciption + " - " + highAndLow; } for (String s : resultStr) { Log.v(TAG, "Forecast entry: " + s); } return resultStr; }
private String formatDateString(int julianDay) { Time time = new Time(mTimeZone); time.setJulianDay(julianDay); long millis = time.toMillis(false); mStringBuilder.setLength(0); return DateUtils.formatDateRange( mContext, mFormatter, millis, millis, DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH, mTimeZone) .toString(); }
private AgendaItem buildAgendaItemFromCursor( final Cursor cursor, int cursorPosition, boolean isDayHeader) { if (cursorPosition == -1) { cursor.moveToFirst(); } else { cursor.moveToPosition(cursorPosition); } AgendaItem agendaItem = new AgendaItem(); agendaItem.begin = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN); agendaItem.end = cursor.getLong(AgendaWindowAdapter.INDEX_END); agendaItem.startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY); agendaItem.allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0; if (agendaItem.allDay) { // UTC to Local time conversion Time time = new Time(mTimeZone); time.setJulianDay(Time.getJulianDay(agendaItem.begin, 0)); agendaItem.begin = time.toMillis(false /* use isDst */); } else if (isDayHeader) { // Trim to midnight. Time time = new Time(mTimeZone); time.set(agendaItem.begin); time.hour = 0; time.minute = 0; time.second = 0; agendaItem.begin = time.toMillis(false /* use isDst */); } // If this is not a day header, then it's an event. if (!isDayHeader) { agendaItem.id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID); if (agendaItem.allDay) { Time time = new Time(mTimeZone); time.setJulianDay(Time.getJulianDay(agendaItem.end, 0)); agendaItem.end = time.toMillis(false /* use isDst */); } } return agendaItem; }
@Override public Time getDayFromLocation(float x) { int dayPosition = getDayIndexFromLocation(x); if (dayPosition == -1) { return null; } int day = mFirstJulianDay + dayPosition; Time time = new Time(mTimeZone); if (mWeek == 0) { // This week is weird... if (day < Time.EPOCH_JULIAN_DAY) { day++; } else if (day == Time.EPOCH_JULIAN_DAY) { time.set(1, 0, 1970); time.normalize(true); return time; } } time.setJulianDay(day); return time; }
/** * Take the String representing the complete forecast in JSON Format and pull out the data we * need to construct the Strings needed for the wireframes. * * <p>Fortunately parsing is easy: constructor takes the JSON string and converts it into an * Object hierarchy for us. */ private ForeCastObj[] getWeatherDataFromJson(String forecastJsonStr, int numDays) throws JSONException { // These are the names of the JSON objects that need to be extracted. final String OWM_LIST = "list"; final String OWM_WEATHER = "weather"; final String OWM_TEMPERATURE = "temp"; final String OWM_MAX = "max"; final String OWM_MIN = "min"; final String OWM_DESCRIPTION = "main"; JSONObject forecastJson = new JSONObject(forecastJsonStr); JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST); // OWM returns daily forecasts based upon the local time of the city that is being // asked for, which means that we need to know the GMT offset to translate this data // properly. // Since this data is also sent in-order and the first day is always the // current day, we're going to take advantage of that to get a nice // normalized UTC date for all of our weather. Time dayTime = new Time(); dayTime.setToNow(); // we start at the day returned by local time. Otherwise this is a mess. int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff); // now we work exclusively in UTC dayTime = new Time(); ForeCastObj[] resultStrs = new ForeCastObj[numDays]; for (int i = 0; i < weatherArray.length(); i++) { // For now, using the format "Day, description, hi/low" String day; String description; String highAndLow; // Get the JSON object representing the day JSONObject dayForecast = weatherArray.getJSONObject(i); // The date/time is returned as a long. We need to convert that // into something human-readable, since most people won't read "1400356800" as // "this saturday". long dateTime; // Cheating to convert this to UTC time, which is what we want anyhow dateTime = dayTime.setJulianDay(julianStartDay + i); // day = getReadableDateString(dateTime); day = Utility.getDayName(getApplicationContext(), dateTime); // description is in a child array called "weather", which is 1 element long. JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0); description = weatherObject.getString(OWM_DESCRIPTION); // Temperatures are in a child object called "temp". Try not to name variables // "temp" when working with temperature. It confuses everybody. JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE); double high = temperatureObject.getDouble(OWM_MAX); double low = temperatureObject.getDouble(OWM_MIN); ForeCastObj tmpObj = new ForeCastObj(); tmpObj.day = day; tmpObj.description = description; Log.d(LOG_TAG, Unit); tmpObj.hight = Utility.formatTemperature( getApplicationContext(), high, (Unit == "metric" ? false : true)); tmpObj.low = Utility.formatTemperature( getApplicationContext(), low, (Unit == "metric" ? false : true)); resultStrs[i] = tmpObj; } return resultStrs; }
public void calculateDays(DayAdapterInfo dayAdapterInfo) { Cursor cursor = dayAdapterInfo.cursor; ArrayList<RowInfo> rowInfo = new ArrayList<RowInfo>(); int prevStartDay = -1; Time tempTime = new Time(mTimeZone); long now = System.currentTimeMillis(); tempTime.set(now); mTodayJulianDay = Time.getJulianDay(now, tempTime.gmtoff); LinkedList<MultipleDayInfo> multipleDayList = new LinkedList<MultipleDayInfo>(); for (int position = 0; cursor.moveToNext(); position++) { int startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY); long id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID); long startTime = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN); long endTime = cursor.getLong(AgendaWindowAdapter.INDEX_END); long instanceId = cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID); boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0; if (allDay) { startTime = Utils.convertAlldayUtcToLocal(tempTime, startTime, mTimeZone); endTime = Utils.convertAlldayUtcToLocal(tempTime, endTime, mTimeZone); } // Skip over the days outside of the adapter's range startDay = Math.max(startDay, dayAdapterInfo.start); // Make sure event's start time is not before the start of the day // (setJulianDay sets the time to 12:00am) long adapterStartTime = tempTime.setJulianDay(startDay); startTime = Math.max(startTime, adapterStartTime); if (startDay != prevStartDay) { // Check if we skipped over any empty days if (prevStartDay == -1) { rowInfo.add(new RowInfo(TYPE_DAY, startDay)); } else { // If there are any multiple-day events that span the empty // range of days, then create day headers and events for // those multiple-day events. boolean dayHeaderAdded = false; for (int currentDay = prevStartDay + 1; currentDay <= startDay; currentDay++) { dayHeaderAdded = false; Iterator<MultipleDayInfo> iter = multipleDayList.iterator(); while (iter.hasNext()) { MultipleDayInfo info = iter.next(); // If this event has ended then remove it from the // list. if (info.mEndDay < currentDay) { iter.remove(); continue; } // If this is the first event for the day, then // insert a day header. if (!dayHeaderAdded) { rowInfo.add(new RowInfo(TYPE_DAY, currentDay)); dayHeaderAdded = true; } long nextMidnight = Utils.getNextMidnight(tempTime, info.mEventStartTimeMilli, mTimeZone); long infoEndTime = (info.mEndDay == currentDay) ? info.mEventEndTimeMilli : nextMidnight; rowInfo.add( new RowInfo( TYPE_MEETING, currentDay, info.mPosition, info.mEventId, info.mEventStartTimeMilli, infoEndTime, info.mInstanceId, info.mAllDay)); info.mEventStartTimeMilli = nextMidnight; } } // If the day header was not added for the start day, then // add it now. if (!dayHeaderAdded) { rowInfo.add(new RowInfo(TYPE_DAY, startDay)); } } prevStartDay = startDay; } // If this event spans multiple days, then add it to the multipleDay // list. int endDay = cursor.getInt(AgendaWindowAdapter.INDEX_END_DAY); // Skip over the days outside of the adapter's range endDay = Math.min(endDay, dayAdapterInfo.end); if (endDay > startDay) { long nextMidnight = Utils.getNextMidnight(tempTime, startTime, mTimeZone); multipleDayList.add( new MultipleDayInfo(position, endDay, id, nextMidnight, endTime, instanceId, allDay)); // Add in the event for this cursor position - since it is the start of a multi-day // event, the end time is midnight rowInfo.add( new RowInfo( TYPE_MEETING, startDay, position, id, startTime, nextMidnight, instanceId, allDay)); } else { // Add in the event for this cursor position rowInfo.add( new RowInfo( TYPE_MEETING, startDay, position, id, startTime, endTime, instanceId, allDay)); } } // There are no more cursor events but we might still have multiple-day // events left. So create day headers and events for those. if (prevStartDay > 0) { for (int currentDay = prevStartDay + 1; currentDay <= dayAdapterInfo.end; currentDay++) { boolean dayHeaderAdded = false; Iterator<MultipleDayInfo> iter = multipleDayList.iterator(); while (iter.hasNext()) { MultipleDayInfo info = iter.next(); // If this event has ended then remove it from the // list. if (info.mEndDay < currentDay) { iter.remove(); continue; } // If this is the first event for the day, then // insert a day header. if (!dayHeaderAdded) { rowInfo.add(new RowInfo(TYPE_DAY, currentDay)); dayHeaderAdded = true; } long nextMidnight = Utils.getNextMidnight(tempTime, info.mEventStartTimeMilli, mTimeZone); long infoEndTime = (info.mEndDay == currentDay) ? info.mEventEndTimeMilli : nextMidnight; rowInfo.add( new RowInfo( TYPE_MEETING, currentDay, info.mPosition, info.mEventId, info.mEventStartTimeMilli, infoEndTime, info.mInstanceId, info.mAllDay)); info.mEventStartTimeMilli = nextMidnight; } } } mRowInfo = rowInfo; }
@Override public View getView(int position, View convertView, ViewGroup parent) { if ((mRowInfo == null) || (position > mRowInfo.size())) { // If we have no row info, mAgendaAdapter returns the view. return mAgendaAdapter.getView(position, convertView, parent); } RowInfo row = mRowInfo.get(position); if (row.mType == TYPE_DAY) { ViewHolder holder = null; View agendaDayView = null; if ((convertView != null) && (convertView.getTag() != null)) { // Listview may get confused and pass in a different type of // view since we keep shifting data around. Not a big problem. Object tag = convertView.getTag(); if (tag instanceof ViewHolder) { agendaDayView = convertView; holder = (ViewHolder) tag; holder.julianDay = row.mDay; } } if (holder == null) { // Create a new AgendaView with a ViewHolder for fast access to // views w/o calling findViewById() holder = new ViewHolder(); agendaDayView = mInflater.inflate(R.layout.agenda_day, parent, false); holder.dayView = (TextView) agendaDayView.findViewById(R.id.day); holder.dateView = (TextView) agendaDayView.findViewById(R.id.date); holder.julianDay = row.mDay; holder.grayed = false; agendaDayView.setTag(holder); } // Re-use the member variable "mTime" which is set to the local // time zone. // It's difficult to find and update all these adapters when the // home tz changes so check it here and update if needed. String tz = Utils.getTimeZone(mContext, mTZUpdater); if (!TextUtils.equals(tz, mTmpTime.timezone)) { mTimeZone = tz; mTmpTime = new Time(tz); } // Build the text for the day of the week. // Should be yesterday/today/tomorrow (if applicable) + day of the week Time date = mTmpTime; long millis = date.setJulianDay(row.mDay); int flags = DateUtils.FORMAT_SHOW_WEEKDAY; mStringBuilder.setLength(0); String dayViewText = Utils.getDayOfWeekString(row.mDay, mTodayJulianDay, millis, mContext); // Build text for the date // Format should be month day mStringBuilder.setLength(0); flags = DateUtils.FORMAT_SHOW_DATE; String dateViewText = DateUtils.formatDateRange(mContext, mFormatter, millis, millis, flags, mTimeZone) .toString(); if (AgendaWindowAdapter.BASICLOG) { dayViewText += " P:" + position; dateViewText += " P:" + position; } holder.dayView.setText(dayViewText); holder.dateView.setText(dateViewText); // Set the background of the view, it is grayed for day that are in the past and today if (row.mDay > mTodayJulianDay) { agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_primary); holder.grayed = false; } else { agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_secondary); holder.grayed = true; } return agendaDayView; } else if (row.mType == TYPE_MEETING) { View itemView = mAgendaAdapter.getView(row.mPosition, convertView, parent); AgendaAdapter.ViewHolder holder = ((AgendaAdapter.ViewHolder) itemView.getTag()); TextView title = holder.title; // The holder in the view stores information from the cursor, but the cursor has no // notion of multi-day event and the start time of each instance of a multi-day event // is the same. RowInfo has the correct info , so take it from there. holder.startTimeMilli = row.mEventStartTimeMilli; boolean allDay = holder.allDay; if (AgendaWindowAdapter.BASICLOG) { title.setText(title.getText() + " P:" + position); } else { title.setText(title.getText()); } // if event in the past or started already, un-bold the title and set the background if ((!allDay && row.mEventStartTimeMilli <= System.currentTimeMillis()) || (allDay && row.mDay <= mTodayJulianDay)) { itemView.setBackgroundResource(R.drawable.agenda_item_bg_secondary); title.setTypeface(Typeface.DEFAULT); holder.grayed = true; } else { itemView.setBackgroundResource(R.drawable.agenda_item_bg_primary); title.setTypeface(Typeface.DEFAULT_BOLD); holder.grayed = false; } holder.julianDay = row.mDay; return itemView; } else { // Error throw new IllegalStateException("Unknown event type:" + row.mType); } }
/** * Take the String representing the complete forecast in JSON Format and pull out the data we need * to construct the Strings needed for the wireframes. * * <p>Fortunately parsing is easy: constructor takes the JSON string and converts it into an * Object hierarchy for us. */ private void getWeatherDataFromJson(String forecastJsonStr, String locationSetting) throws JSONException { // Location information final String OWM_CITY = "city"; final String OWM_CITY_NAME = "name"; final String OWM_COORD = "coord"; // Location coordinate final String OWM_LATITUDE = "lat"; final String OWM_LONGITUDE = "lon"; // These are the names of the JSON objects that need to be extracted. final String OWM_PRESSURE = "pressure"; final String OWM_HUMIDITY = "humidity"; final String OWM_WINDSPEED = "speed"; final String OWM_WIND_DIRECTION = "deg"; // All temperatures are children of the "temp" object. final String OWM_LIST = "list"; final String OWM_TEMPERATURE = "temp"; final String OWM_MAX = "max"; final String OWM_MIN = "min"; final String OWM_WEATHER = "weather"; final String OWM_DESCRIPTION = "main"; final String OWM_WEATHER_ID = "id"; JSONObject forecastJson = new JSONObject(forecastJsonStr); JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST); // OWM returns daily forecasts based upon the local time of the city that is being // asked for, which means that we need to know the GMT offset to translate this data // properly. JSONObject cityJson = forecastJson.getJSONObject(OWM_CITY); String cityName = cityJson.getString(OWM_CITY_NAME); JSONObject cityCoordJson = cityJson.getJSONObject(OWM_COORD); double cityLongitude = cityCoordJson.getDouble(OWM_LONGITUDE); double cityLatitude = cityCoordJson.getDouble(OWM_LATITUDE); long locationId = addLocation(locationSetting, cityName, cityLongitude, cityLatitude); // Insert the new weather information into the database Vector<ContentValues> cVVector = new Vector<ContentValues>(weatherArray.length()); // Since this data is also sent in-order and the first day is always the // current day, we're going to take advantage of that to get a nice // normalized UTC date for all of our weather. Time dayTime = new Time(); dayTime.setToNow(); // we start at the day returned by local time. Otherwise this is a mess. int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff); // now we work exclusively in UTC dayTime = new Time(); for (int i = 0; i < weatherArray.length(); i++) { // These are the values that will be collected. long dateTime; double pressure; int humidity; double windSpeed; double windDirection; double high; double low; String description; int weatherId; // Get the JSON object representing the day JSONObject dayForecast = weatherArray.getJSONObject(i); pressure = dayForecast.getDouble(OWM_PRESSURE); humidity = dayForecast.getInt(OWM_HUMIDITY); windSpeed = dayForecast.getDouble(OWM_WINDSPEED); windDirection = dayForecast.getDouble(OWM_WIND_DIRECTION); // Description is in a child array called "weather", which is 1 element long. // That element also contains a weather code. JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0); description = weatherObject.getString(OWM_DESCRIPTION); weatherId = weatherObject.getInt(OWM_WEATHER_ID); // Cheating to convert this to UTC time, which is what we want anyhow dateTime = dayTime.setJulianDay(julianStartDay + i); // Temperatures are in a child object called "temp". Try not to name variables // "temp" when working with temperature. It confuses everybody. JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE); high = temperatureObject.getDouble(OWM_MAX); low = temperatureObject.getDouble(OWM_MIN); ContentValues weatherValues = new ContentValues(); weatherValues.put(WeatherEntry.COLUMN_LOC_KEY, locationId); weatherValues.put(WeatherEntry.COLUMN_DATE, dateTime); weatherValues.put(WeatherEntry.COLUMN_HUMIDITY, humidity); weatherValues.put(WeatherEntry.COLUMN_PRESSURE, pressure); weatherValues.put(WeatherEntry.COLUMN_WIND_SPEED, windSpeed); weatherValues.put(WeatherEntry.COLUMN_DEGREES, windDirection); weatherValues.put(WeatherEntry.COLUMN_MAX_TEMP, high); weatherValues.put(WeatherEntry.COLUMN_MIN_TEMP, low); weatherValues.put(WeatherEntry.COLUMN_SHORT_DESC, description); weatherValues.put(WeatherEntry.COLUMN_WEATHER_ID, weatherId); cVVector.add(weatherValues); } // add to database if (cVVector.size() > 0) { // Student: call bulkInsert to add the weatherEntries to the database here ContentValues[] contents = new ContentValues[cVVector.size()]; ContentResolver weatherProvider = mContext.getContentResolver(); weatherProvider.bulkInsert(WeatherEntry.CONTENT_URI, cVVector.toArray(contents)); } String sortOrder = WeatherEntry.COLUMN_DATE + " ASC"; Uri weatherForLocationUri = WeatherEntry.buildWeatherLocationWithStartDate(locationSetting, System.currentTimeMillis()); // Students: Uncomment the next lines to display what what you stored in the bulkInsert Cursor cur = mContext.getContentResolver().query(weatherForLocationUri, null, null, null, sortOrder); cVVector = new Vector<ContentValues>(cur.getCount()); if (cur.moveToFirst()) { do { ContentValues cv = new ContentValues(); DatabaseUtils.cursorRowToContentValues(cur, cv); cVVector.add(cv); } while (cur.moveToNext()); } Log.d(LOG_TAG, "FetchWeatherTask Complete. " + cVVector.size() + " Inserted"); }
private void doQuery(QuerySpec queryData) { if (!mAdapterInfos.isEmpty()) { int start = mAdapterInfos.getFirst().start; int end = mAdapterInfos.getLast().end; int queryDuration = calculateQueryDuration(start, end); switch (queryData.queryType) { case QUERY_TYPE_OLDER: queryData.end = start - 1; queryData.start = queryData.end - queryDuration; break; case QUERY_TYPE_NEWER: queryData.start = end + 1; queryData.end = queryData.start + queryDuration; break; } // By "compacting" cursors, this fixes the disco/ping-pong problem // b/5311977 if (mRowCount < 20 && queryData.queryType != QUERY_TYPE_CLEAN) { if (DEBUGLOG) { Log.e( TAG, "Compacting cursor: mRowCount=" + mRowCount + " totalStart:" + start + " totalEnd:" + end + " query.start:" + queryData.start + " query.end:" + queryData.end); } queryData.queryType = QUERY_TYPE_CLEAN; if (queryData.start > start) { queryData.start = start; } if (queryData.end < end) { queryData.end = end; } } } if (BASICLOG) { Time time = new Time(mTimeZone); time.setJulianDay(queryData.start); Time time2 = new Time(mTimeZone); time2.setJulianDay(queryData.end); Log.v( TAG, "startQuery: " + time.toString() + " to " + time2.toString() + " then go to " + queryData.goToTime); } mQueryHandler.cancelOperation(0); if (BASICLOG) queryData.queryStartMillis = System.nanoTime(); Uri queryUri = buildQueryUri(queryData.start, queryData.end, queryData.searchQuery); mQueryHandler.startQuery( 0, queryData, queryUri, PROJECTION, buildQuerySelection(), null, AGENDA_SORT_ORDER); }
/** * Take the String representing the complete forecast in JSON Format and pull out the data we * need to construct the Strings needed for the wireframes. * * <p>Fortunately parsing is easy: constructor takes the JSON string and converts it into an * Object hierarchy for us. */ private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays) throws JSONException { // These are the names of the JSON objects that need to be extracted. final String OWM_LIST = "list"; final String OWM_MAIN = "main"; final String OWM_WEATHER = "weather"; final String OWM_MAX = "temp_max"; final String OWM_MIN = "temp_min"; final String OWM_DESCRIPTION = "main"; JSONObject forecastJson = new JSONObject(forecastJsonStr); JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST); // OWM returns daily forecasts based upon the local time of the city that is being // asked for, which means that we need to know the GMT offset to translate this data // properly. // Since this data is also sent in-order and the first day is always the // current day, we're going to take advantage of that to get a nice // normalized UTC date for all of our weather. Time dayTime = new Time(); dayTime.setToNow(); // we start at the day returned by local time. Otherwise this is a mess. int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff); // now we work exclusively in UTC dayTime = new Time(); String[] resultStrs = new String[numDays]; // Temperature Unit Preference SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity()); // Default is Metric String unitType = sharedPref.getString( getString(R.string.pref_units_key), getString(R.string.pref_units_metric)); for (int i = 0; i < weatherArray.length(); i++) { // For now, using the format "Day, description, hi/low" String day; String description; String highAndLow; // Get the JSON object representing the day JSONObject dayForecast = weatherArray.getJSONObject(i); // The date/time is returned as a long. We need to convert that // into something human-readable, since most people won't read "1400356800" as // "this saturday". long dateTime; // Cheating to convert this to UTC time, which is what we want anyhow dateTime = dayTime.setJulianDay(julianStartDay + i); day = getReadableDateString(dateTime); // description is in a child array called "weather", which is 1 element long. JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0); description = weatherObject.getString(OWM_DESCRIPTION); // 3 Temperatures values are in a child object called "main". Try not to name variables // "temp" when working with temperature. It confuses everybody. JSONObject descriptionObject = dayForecast.getJSONObject(OWM_MAIN); double high = descriptionObject.getDouble(OWM_MAX); double low = descriptionObject.getDouble(OWM_MIN); highAndLow = formatHighLows(high, low, unitType); resultStrs[i] = day + " - " + description + " - " + highAndLow; } return resultStrs; }
/** * Take the String representing the complete forecast in JSON Format and pull out the data we need * to construct the Strings needed for the wireframes. * * <p>Fortunately parsing is easy: constructor takes the JSON string and converts it into an * Object hierarchy for us. */ private void getWeatherDataFromJson(String forecastJsonStr, String locationSetting) throws JSONException { // Now we have a String representing the complete forecast in JSON Format. // Fortunately parsing is easy: constructor takes the JSON string and converts it // into an Object hierarchy for us. // These are the names of the JSON objects that need to be extracted. // Location information final String OWM_CITY = "city"; final String OWM_CITY_NAME = "name"; final String OWM_COORD = "coord"; // Location coordinate final String OWM_LATITUDE = "lat"; final String OWM_LONGITUDE = "lon"; // Weather information. Each day's forecast info is an element of the "list" array. final String OWM_LIST = "list"; final String OWM_PRESSURE = "pressure"; final String OWM_HUMIDITY = "humidity"; final String OWM_WINDSPEED = "speed"; final String OWM_WIND_DIRECTION = "deg"; // All temperatures are children of the "temp" object. final String OWM_TEMPERATURE = "temp"; final String OWM_MAX = "max"; final String OWM_MIN = "min"; final String OWM_WEATHER = "weather"; final String OWM_DESCRIPTION = "main"; final String OWM_WEATHER_ID = "id"; try { JSONObject forecastJson = new JSONObject(forecastJsonStr); JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST); JSONObject cityJson = forecastJson.getJSONObject(OWM_CITY); String cityName = cityJson.getString(OWM_CITY_NAME); JSONObject cityCoord = cityJson.getJSONObject(OWM_COORD); double cityLatitude = cityCoord.getDouble(OWM_LATITUDE); double cityLongitude = cityCoord.getDouble(OWM_LONGITUDE); long locationId = addLocation(locationSetting, cityName, cityLatitude, cityLongitude); // Insert the new weather information into the database Vector<ContentValues> cVVector = new Vector<ContentValues>(weatherArray.length()); // OWM returns daily forecasts based upon the local time of the city that is being // asked for, which means that we need to know the GMT offset to translate this data // properly. // Since this data is also sent in-order and the first day is always the // current day, we're going to take advantage of that to get a nice // normalized UTC date for all of our weather. Time dayTime = new Time(); dayTime.setToNow(); // we start at the day returned by local time. Otherwise this is a mess. int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff); // now we work exclusively in UTC dayTime = new Time(); for (int i = 0; i < weatherArray.length(); i++) { // These are the values that will be collected. long dateTime; double pressure; int humidity; double windSpeed; double windDirection; double high; double low; String description; int weatherId; // Get the JSON object representing the day JSONObject dayForecast = weatherArray.getJSONObject(i); // Cheating to convert this to UTC time, which is what we want anyhow dateTime = dayTime.setJulianDay(julianStartDay + i); pressure = dayForecast.getDouble(OWM_PRESSURE); humidity = dayForecast.getInt(OWM_HUMIDITY); windSpeed = dayForecast.getDouble(OWM_WINDSPEED); windDirection = dayForecast.getDouble(OWM_WIND_DIRECTION); // Description is in a child array called "weather", which is 1 element long. // That element also contains a weather code. JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0); description = weatherObject.getString(OWM_DESCRIPTION); weatherId = weatherObject.getInt(OWM_WEATHER_ID); // Temperatures are in a child object called "temp". Try not to name variables // "temp" when working with temperature. It confuses everybody. JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE); high = temperatureObject.getDouble(OWM_MAX); low = temperatureObject.getDouble(OWM_MIN); ContentValues weatherValues = new ContentValues(); weatherValues.put(WeatherEntry.COLUMN_LOC_KEY, locationId); weatherValues.put(WeatherEntry.COLUMN_DATE, dateTime); weatherValues.put(WeatherEntry.COLUMN_HUMIDITY, humidity); weatherValues.put(WeatherEntry.COLUMN_PRESSURE, pressure); weatherValues.put(WeatherEntry.COLUMN_WIND_SPEED, windSpeed); weatherValues.put(WeatherEntry.COLUMN_DEGREES, windDirection); weatherValues.put(WeatherEntry.COLUMN_MAX_TEMP, high); weatherValues.put(WeatherEntry.COLUMN_MIN_TEMP, low); weatherValues.put(WeatherEntry.COLUMN_SHORT_DESC, description); weatherValues.put(WeatherEntry.COLUMN_WEATHER_ID, weatherId); cVVector.add(weatherValues); } int inserted = 0; // add to database if (cVVector.size() > 0) { ContentValues[] cvArray = new ContentValues[cVVector.size()]; cVVector.toArray(cvArray); inserted = mContext.getContentResolver().bulkInsert(WeatherEntry.CONTENT_URI, cvArray); } Log.d(LOG_TAG, "FetchWeatherTask Complete. " + inserted + " Inserted"); } catch (JSONException e) { Log.e(LOG_TAG, e.getMessage(), e); e.printStackTrace(); } }