/**
* ORcycle, Copyright 2014, 2015, PSU Transportation, Technology, and People Lab.
*
* ORcycle 2.2.0 has introduced new app features: safety focus with new buttons
* to report safety issues and crashes (new questionnaires), expanded trip
* questionnaire (adding questions besides trip purpose), app utilization
* reminders, app tutorial, and updated font and color schemes.
*
* @author Bryan.Blanc <bryanpblanc@gmail.com> (code)
* @author Miguel Figliozzi <figliozzi@pdx.edu> and ORcycle team (general app
* design and features, report questionnaires and new ORcycle features)
*
* For more information on the project, go to
* http://www.pdx.edu/transportation-lab/orcycle and http://www.pdx.edu/transportation-lab/app-development
*
* Updated/modified for Oregon pilot study and app deployment.
*
* ORcycle is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or any later version.
* ORcycle is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with
* ORcycle. If not, see <http://www.gnu.org/licenses/>.
*
*************************************************************************************
*
* Cycle Altanta, Copyright 2012 Georgia Institute of Technology
* Atlanta, GA. USA
*
* @author Christopher Le Dantec <ledantec@gatech.edu>
* @author Anhong Guo <guoanhong15@gmail.com>
*
* Updated/Modified for Atlanta's app deployment. Based on the
* CycleTracks codebase for SFCTA.
*
* CycleTracks, Copyright 2009,2010 San Francisco County Transportation Authority
* San Francisco, CA, USA
*
* @author Billy Charlton <billy.charlton@sfcta.org>
*
* This file is part of CycleTracks.
*
* CycleTracks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CycleTracks is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CycleTracks. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.pdx.cecs.orcycle;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import java.util.zip.GZIPOutputStream;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import android.widget.ListView;
import android.widget.Toast;
public class TripUploader extends AsyncTask<Long, Integer, Boolean> {
private static final String MODULE_TAG = "TripUploader";
public static final int kSaveProtocolVersion = 3;
private static final String POST_URL = "http://orcycle2.cecs.pdx.edu/post/";
// Saving protocol version 3
public static final String TRIP_COORDS_TIME = "r";
public static final String TRIP_COORDS_LAT = "l";
public static final String TRIP_COORDS_LON = "n";
public static final String TRIP_COORDS_ALT = "a";
public static final String TRIP_COORDS_SPEED = "s";
public static final String TRIP_COORDS_HACCURACY = "h";
public static final String TRIP_COORDS_VACCURACY = "v";
public static final String TRIP_COORDS_SENSOR_READINGS = "sr";
public static final String PAUSE_START = "ps";
public static final String PAUSE_END = "pe";
public static final String TRIP_COORD_SENSOR_ID = "s_id";
public static final String TRIP_COORD_SENSOR_TYPE = "s_t";
public static final String TRIP_COORD_SENSOR_SAMPLES = "s_ns";
public static final String TRIP_COORD_SENSOR_NUM_VALS = "s_nv";
public static final String TRIP_COORD_SENSOR_AVG_0 = "s_a0";
public static final String TRIP_COORD_SENSOR_AVG_1 = "s_a1";
public static final String TRIP_COORD_SENSOR_AVG_2 = "s_a2";
public static final String TRIP_COORD_SENSOR_SSD_0 = "s_s0";
public static final String TRIP_COORD_SENSOR_SSD_1 = "s_s1";
public static final String TRIP_COORD_SENSOR_SSD_2 = "s_s2";
public static final String USER_AGE = "age";
public static final String USER_EMAIL = "email";
public static final String USER_GENDER = "gender";
public static final String USER_ZIP_HOME = "homeZIP";
public static final String USER_ZIP_WORK = "workZIP";
public static final String USER_ZIP_SCHOOL = "schoolZIP";
public static final String USER_CYCLING_FREQUENCY = "cyclingFreq";
public static final String APP_VERSION = "app_version";
public static final String USER_ETHNICITY = "ethnicity";
public static final String USER_INCOME = "income";
public static final String USER_HHSIZE = "hhSize";
public static final String USER_HHVEHICLES = "hhVehicles";
public static final String USER_RIDERTYPE = "rider_type";
public static final String USER_RIDERHISTORY = "rider_history";
private static final String FID_QUESTION_ID = "question_id";
private static final String FID_ANSWER_ID = "answer_id";
private static final String FID_ANSWER_OTHER_TEXT = "other_text";
private final Context mCtx;
private final String userId;
private final DbAdapter mDb;
private Map<String, Integer> sensorColumn = null;
public TripUploader(Context ctx, String userId) {
super();
this.mCtx = ctx;
this.userId = userId;
this.mDb = new DbAdapter(this.mCtx);
}
@SuppressLint("SimpleDateFormat")
private JSONObject getCoordsJSON(long tripId) throws JSONException {
JSONObject jsonTripCoords = null;
JSONArray jsonSensorReadings = null;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mDb.openReadOnly();
try {
Cursor cursorTripCoords = mDb.fetchAllCoordsForTrip(tripId);
// Build the map between JSON field name and phone db field name:
Map<String, Integer> fieldMap = new HashMap<String, Integer>();
fieldMap.put(TRIP_COORDS_TIME, cursorTripCoords.getColumnIndex(DbAdapter.K_POINT_TIME));
fieldMap.put(TRIP_COORDS_LAT, cursorTripCoords.getColumnIndex(DbAdapter.K_POINT_LAT));
fieldMap.put(TRIP_COORDS_LON, cursorTripCoords.getColumnIndex(DbAdapter.K_POINT_LGT));
fieldMap.put(TRIP_COORDS_ALT, cursorTripCoords.getColumnIndex(DbAdapter.K_POINT_ALT));
fieldMap.put(TRIP_COORDS_SPEED, cursorTripCoords.getColumnIndex(DbAdapter.K_POINT_SPEED));
fieldMap.put(TRIP_COORDS_HACCURACY, cursorTripCoords.getColumnIndex(DbAdapter.K_POINT_ACC));
fieldMap.put(TRIP_COORDS_VACCURACY, cursorTripCoords.getColumnIndex(DbAdapter.K_POINT_ACC));
// Build JSON objects for each coordinate:
jsonTripCoords = new JSONObject();
double coordTime;
while (!cursorTripCoords.isAfterLast()) {
// *****************
// * Get coordinates
// *****************
coordTime = cursorTripCoords.getDouble(fieldMap.get(TRIP_COORDS_TIME));
JSONObject jsonCoord = new JSONObject();
jsonCoord.put(TRIP_COORDS_TIME, df.format(coordTime));
jsonCoord.put(TRIP_COORDS_LAT, cursorTripCoords.getDouble(fieldMap.get(TRIP_COORDS_LAT)) / 1E6);
jsonCoord.put(TRIP_COORDS_LON, cursorTripCoords.getDouble(fieldMap.get(TRIP_COORDS_LON)) / 1E6);
jsonCoord.put(TRIP_COORDS_ALT, dr1(cursorTripCoords.getDouble(fieldMap.get(TRIP_COORDS_ALT))));
jsonCoord.put(TRIP_COORDS_SPEED, dr1(cursorTripCoords.getDouble(fieldMap.get(TRIP_COORDS_SPEED))));
jsonCoord.put(TRIP_COORDS_HACCURACY, cursorTripCoords.getDouble(fieldMap.get(TRIP_COORDS_HACCURACY)));
jsonCoord.put(TRIP_COORDS_VACCURACY, cursorTripCoords.getDouble(fieldMap.get(TRIP_COORDS_VACCURACY)));
// **********************************************************
// * Get all sensor readings corresponding to this time index
// **********************************************************
jsonSensorReadings = getJsonSensorReadings(coordTime);
if ((null != jsonSensorReadings) && (jsonSensorReadings.length() > 0)) {
jsonCoord.put(TRIP_COORDS_SENSOR_READINGS, jsonSensorReadings);
}
// ****************************************************
// * Insert sensor readings into jSON coordinate object
// ****************************************************
jsonTripCoords.put(jsonCoord.getString("r"), jsonCoord);
// move to next coordinate
cursorTripCoords.moveToNext();
}
cursorTripCoords.close();
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
finally {
mDb.close();
}
return jsonTripCoords;
}
/**
* Get all sensor readings corresponding to this time index
* @return
*/
private JSONArray getJsonSensorReadings(double coordTime) {
JSONArray jsonSensorReadings = null;
JSONObject jsonSensorReading;
int numVals;
Cursor cursorSV = null;
try {
if (null != (cursorSV = mDb.fetchSensorValues(coordTime))) {
// Collect sensor readings into a json object
jsonSensorReadings = new JSONArray();
// Construct a map between cursor column index
if (null == sensorColumn) {
sensorColumn = new HashMap<String, Integer>();
sensorColumn.put(TRIP_COORD_SENSOR_ID, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_ID));
sensorColumn.put(TRIP_COORD_SENSOR_TYPE, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_TYPE));
sensorColumn.put(TRIP_COORD_SENSOR_SAMPLES, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_SAMPLES));
sensorColumn.put(TRIP_COORD_SENSOR_NUM_VALS, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_NUM_VALS));
sensorColumn.put(TRIP_COORD_SENSOR_AVG_0, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_AVG_0));
sensorColumn.put(TRIP_COORD_SENSOR_AVG_1, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_AVG_1));
sensorColumn.put(TRIP_COORD_SENSOR_AVG_2, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_AVG_2));
sensorColumn.put(TRIP_COORD_SENSOR_SSD_0, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_SSD_0));
sensorColumn.put(TRIP_COORD_SENSOR_SSD_1, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_SSD_1));
sensorColumn.put(TRIP_COORD_SENSOR_SSD_2, cursorSV.getColumnIndex(DbAdapter.K_SENSOR_SSD_2));
}
int numSamples;
while (!cursorSV.isAfterLast()) {
jsonSensorReading = new JSONObject();
jsonSensorReading.put(TRIP_COORD_SENSOR_ID, cursorSV.getString(sensorColumn.get(TRIP_COORD_SENSOR_ID)));
jsonSensorReading.put(TRIP_COORD_SENSOR_TYPE, cursorSV.getInt (sensorColumn.get(TRIP_COORD_SENSOR_TYPE)));
jsonSensorReading.put(TRIP_COORD_SENSOR_SAMPLES, (numSamples = cursorSV.getInt (sensorColumn.get(TRIP_COORD_SENSOR_SAMPLES))));
numVals = cursorSV.getInt(sensorColumn.get(TRIP_COORD_SENSOR_NUM_VALS));
switch(numVals) {
case 1:
jsonSensorReading.put(TRIP_COORD_SENSOR_AVG_0, dr2(cursorSV.getDouble(sensorColumn.get(TRIP_COORD_SENSOR_AVG_0))));
if (numSamples > 0) {
jsonSensorReading.put(TRIP_COORD_SENSOR_SSD_0, dr2(Math.sqrt(cursorSV.getDouble(sensorColumn.get(TRIP_COORD_SENSOR_SSD_0))/numSamples)));
}
else {
jsonSensorReading.put(TRIP_COORD_SENSOR_SSD_0, 0.0);
}
break;
case 3:
jsonSensorReading.put(TRIP_COORD_SENSOR_AVG_0, dr2(cursorSV.getDouble(sensorColumn.get(TRIP_COORD_SENSOR_AVG_0))));
jsonSensorReading.put(TRIP_COORD_SENSOR_AVG_1, dr2(cursorSV.getDouble(sensorColumn.get(TRIP_COORD_SENSOR_AVG_1))));
jsonSensorReading.put(TRIP_COORD_SENSOR_AVG_2, dr2(cursorSV.getDouble(sensorColumn.get(TRIP_COORD_SENSOR_AVG_2))));
if (numSamples > 0) {
jsonSensorReading.put(TRIP_COORD_SENSOR_SSD_0, dr2(Math.sqrt(cursorSV.getDouble(sensorColumn.get(TRIP_COORD_SENSOR_SSD_0))/numSamples)));
jsonSensorReading.put(TRIP_COORD_SENSOR_SSD_1, dr2(Math.sqrt(cursorSV.getDouble(sensorColumn.get(TRIP_COORD_SENSOR_SSD_1))/numSamples)));
jsonSensorReading.put(TRIP_COORD_SENSOR_SSD_2, dr2(Math.sqrt(cursorSV.getDouble(sensorColumn.get(TRIP_COORD_SENSOR_SSD_2))/numSamples)));
}
else {
jsonSensorReading.put(TRIP_COORD_SENSOR_SSD_0, 0.0);
jsonSensorReading.put(TRIP_COORD_SENSOR_SSD_1, 0.0);
jsonSensorReading.put(TRIP_COORD_SENSOR_SSD_2, 0.0);
}
break;
}
jsonSensorReadings.put(jsonSensorReading);
cursorSV.moveToNext();
}
}
}
catch (Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
finally {
if (null != cursorSV) {
cursorSV.close();
}
}
return jsonSensorReadings;
}
/**
* Rounds double value to two decimal places.
* @param value to round.
* @return value rounded to two decimal places.
*/
private double dr1(double value) {
return Math.round(value * 10.0) / 10.0;
}
/**
* Rounds double value to two decimal places.
* @param value to round.
* @return value rounded to two decimal places.
*/
private double dr2(double value) {
return Math.round(value * 100.0) / 100.0;
}
@SuppressLint("SimpleDateFormat")
private JSONArray getPausesJSON(long tripId) throws JSONException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mDb.openReadOnly();
Cursor pausesCursor = mDb.fetchPauses(tripId);
// Build the map between JSON fieldname and phone db fieldname:
Map<String, Integer> fieldMap = new HashMap<String, Integer>();
fieldMap.put(PAUSE_START, pausesCursor.getColumnIndex(DbAdapter.K_PAUSE_START_TIME));
fieldMap.put(PAUSE_END, pausesCursor.getColumnIndex(DbAdapter.K_PAUSE_END_TIME));
// Build JSON objects for each coordinate:
JSONArray jsonPauses = new JSONArray();
while (!pausesCursor.isAfterLast()) {
JSONObject json = new JSONObject();
try {
json.put(PAUSE_START, df.format(pausesCursor.getDouble(fieldMap.get(PAUSE_START))));
json.put(PAUSE_END, df.format(pausesCursor.getDouble(fieldMap.get(PAUSE_END))));
jsonPauses.put(json);
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
pausesCursor.moveToNext();
}
pausesCursor.close();
mDb.close();
return jsonPauses;
}
private JSONArray getTripResponsesJSON(long tripId) throws JSONException {
// Create a JSON array to hold all of the answers
JSONArray jsonAnswers = new JSONArray();
mDb.openReadOnly();
try {
Cursor answers = mDb.fetchTripAnswers(tripId);
int questionColumn = answers.getColumnIndex(DbAdapter.K_ANSWER_QUESTION_ID);
int answerColumn = answers.getColumnIndex(DbAdapter.K_ANSWER_ANSWER_ID);
int otherText = answers.getColumnIndex(DbAdapter.K_ANSWER_OTHER_TEXT);
String text;
// Cycle thru the database entries
while (!answers.isAfterLast()) {
// For each row, construct a JSON object
JSONObject json = new JSONObject();
try {
// Place values into the JSON object
json.put(FID_QUESTION_ID, answers.getInt(questionColumn));
json.put(FID_ANSWER_ID, answers.getInt(answerColumn));
if (null != (text = answers.getString(otherText))) {
text = text.trim();
if (!text.equals("")) {
json.put(FID_ANSWER_OTHER_TEXT, text);
}
}
// Place JSON objects into the JSON array
jsonAnswers.put(json);
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
// Move to next row
answers.moveToNext();
}
answers.close();
}
catch(Exception ex) {
Log.e(MODULE_TAG, ex.getMessage());
}
finally {
mDb.close();
}
return jsonAnswers;
}
@SuppressLint("SimpleDateFormat")
private Vector<String> getTripData(long tripId) {
Vector<String> tripData = new Vector<String>();
mDb.openReadOnly();
Cursor tripCursor = mDb.fetchTrip(tripId);
String note = tripCursor.getString(tripCursor.getColumnIndex(DbAdapter.K_TRIP_NOTE));
String purpose = tripCursor.getString(tripCursor.getColumnIndex(DbAdapter.K_TRIP_PURP));
Double startTime = tripCursor.getDouble(tripCursor.getColumnIndex(DbAdapter.K_TRIP_START));
Double endTime = tripCursor.getDouble(tripCursor.getColumnIndex(DbAdapter.K_TRIP_END));
tripCursor.close();
mDb.close();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
tripData.add(note);
tripData.add(purpose);
tripData.add(df.format(startTime));
tripData.add(df.format(endTime));
return tripData;
}
public String getAppVersion() {
String versionName = "";
int versionCode = 0;
try {
PackageInfo pInfo = mCtx.getPackageManager().getPackageInfo(
mCtx.getPackageName(), 0);
versionName = pInfo.versionName;
versionCode = pInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
String systemVersion = Build.VERSION.RELEASE;
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
if (model.startsWith(manufacturer)) {
return versionName + " (" + versionCode + ") on Android "
+ systemVersion + " " + capitalize(model);
} else {
return versionName + " (" + versionCode + ") on Android "
+ systemVersion + " " + capitalize(manufacturer) + " "
+ model;
}
}
private String capitalize(String s) {
if (s == null || s.length() == 0) {
return "";
}
char first = s.charAt(0);
if (Character.isUpperCase(first)) {
return s;
} else {
return Character.toUpperCase(first) + s.substring(1);
}
}
private String getPostData(long tripId) throws JSONException {
JSONObject coords = getCoordsJSON(tripId);
JSONArray pauses = getPausesJSON(tripId);
//JSONObject user = getUserJSON();
JSONArray tripResponses = getTripResponsesJSON(tripId);
String deviceId = userId;
Vector<String> tripData = getTripData(tripId);
String notes = tripData.get(0);
String purpose = tripData.get(1);
String startTime = tripData.get(2);
String codedPostData =
"purpose=" + purpose +
"&tripid=" + String.valueOf(tripId) +
// "&user=" + user.toString() +
"¬es=" + notes +
"&coords=" + coords.toString() +
"&pauses=" + pauses.toString() +
"&version=" + String.valueOf(kSaveProtocolVersion) +
"&start=" + startTime +
"&device=" + deviceId +
"&tripResponses=" + tripResponses.toString();
return codedPostData;
}
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the
* BufferedReader.readLine() method. We iterate until the BufferedReader
* return null which means there's no more data to read. Each line will
* appended to a StringBuilder and returned as String.
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
public static byte[] compress(String string) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
GZIPOutputStream gos = new GZIPOutputStream(os);
gos.write(string.getBytes());
gos.close();
byte[] compressed = os.toByteArray();
os.close();
return compressed;
}
boolean uploadOneTrip(long currentTripId) {
boolean result = false;
byte[] postBodyDataZipped;
String postBodyData;
try {
postBodyData = getPostData(currentTripId);
} catch (JSONException ex) {
ex.printStackTrace();
return result;
}
HttpClient client = new DefaultHttpClient();
HttpPost postRequest = new HttpPost(POST_URL);
try {
// Zip Upload!!!
postBodyDataZipped = compress(postBodyData);
postRequest.setHeader("Cycleatl-Protocol-Version", "3");
postRequest.setHeader("Content-Encoding", "gzip");
postRequest.setHeader("Content-Type", "application/vnd.cycleatl.trip-v3+form");
postRequest.setEntity(new ByteArrayEntity(postBodyDataZipped));
HttpResponse response = client.execute(postRequest);
String responseString = convertStreamToString(response.getEntity().getContent());
JSONObject responseData = new JSONObject(responseString);
String responseStatus = responseData.getString("status");
if (responseStatus.equals("success")) {
mDb.open();
mDb.updateTripStatus(currentTripId, TripData.STATUS_SENT);
mDb.close();
result = true;
}
else {
Log.e(MODULE_TAG, "Server response status: " + responseStatus);
}
} catch (IllegalStateException ex) {
ex.printStackTrace();
return false;
} catch (IOException ex) {
ex.printStackTrace();
return false;
} catch (JSONException ex) {
ex.printStackTrace();
return false;
}
return result;
}
@Override
protected Boolean doInBackground(Long... tripid) {
// First, send the trip user asked for:
Boolean result = true;
if (tripid.length != 0) {
result = uploadOneTrip(tripid[0]);
}
// Then, automatically try and send previously-completed trips
// that were not sent successfully.
Vector<Long> unsentTrips = new Vector<Long>();
mDb.openReadOnly();
Cursor cur = mDb.fetchUnsentTrips();
if (cur != null && cur.getCount() > 0) {
// pd.setMessage("Sent. You have previously unsent trips; submitting those now.");
while (!cur.isAfterLast()) {
unsentTrips.add(Long.valueOf(cur.getLong(0)));
cur.moveToNext();
}
cur.close();
}
mDb.close();
for (Long trip : unsentTrips) {
result &= uploadOneTrip(trip);
}
return result;
}
@Override
protected void onPreExecute() {
Toast.makeText(mCtx.getApplicationContext(),
"Submitting. Thanks for using ORcycle!",
Toast.LENGTH_LONG).show();
}
private SavedTripsAdapter mSavedTripsAdapter;
public SavedTripsAdapter setSavedTripsAdapter(
SavedTripsAdapter mSavedTripsAdapter) {
this.mSavedTripsAdapter = mSavedTripsAdapter;
return mSavedTripsAdapter;
}
private FragmentSavedTripsSection fragmentSavedTripsSection;
public FragmentSavedTripsSection setFragmentSavedTripsSection(
FragmentSavedTripsSection fragmentSavedTripsSection) {
this.fragmentSavedTripsSection = fragmentSavedTripsSection;
return fragmentSavedTripsSection;
}
private ListView listSavedTrips;
public ListView setListView(ListView listSavedTrips) {
this.listSavedTrips = listSavedTrips;
return listSavedTrips;
}
@Override
protected void onPostExecute(Boolean result) {
try {
if (mSavedTripsAdapter != null) {
mSavedTripsAdapter.notifyDataSetChanged();
}
if (fragmentSavedTripsSection != null) {
listSavedTrips.invalidate();
fragmentSavedTripsSection.populateTripList(listSavedTrips);
}
if (result) {
Toast.makeText(mCtx.getApplicationContext(),
"Trip uploaded successfully.", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(
mCtx.getApplicationContext(),
"ORcycle couldn't upload the trip, and will retry when your next trip is completed.",
Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
// Just don't toast if the view has gone out of context
}
}
}