Java tutorial
/** * ORcycle, Copyright 2014, 2015, PSU Transportation, Technology, and People Lab. * * @author Robin Murray <robin5@pdx.edu> (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/>. * */ package edu.pdx.cecs.orcycle; import java.io.DataOutputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.util.Vector; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.database.Cursor; import android.os.AsyncTask; import android.util.Log; import android.widget.Toast; public class Uploader extends AsyncTask<Long, Integer, Boolean> { private static final String MODULE_TAG = "Uploader"; private static final int kSaveNoteProtocolVersion = 4; private static final String boundary = "cycle*******notedata*******atlanta"; private final Context mCtx; private final String userId; private final DbAdapter mDb; public Uploader(Context ctx, String userId) { super(); this.mCtx = ctx; this.userId = userId; this.mDb = new DbAdapter(this.mCtx); } private static final String contentFieldPrefix = "--cycle*******notedata*******atlanta\r\n"; private String makeContentField(String name, String value) { return contentFieldPrefix + "Content-Disposition: form-data; name=\"" + name + "\"\r\n\r\n" + value + "\r\n"; } private boolean uploadOneSegment(long currentNoteId) { boolean result = false; final String postUrl = mCtx.getResources().getString(R.string.post_url); try { URL url = new URL(postUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoInput(true); // Allow Inputs conn.setDoOutput(true); // Allow Outputs conn.setUseCaches(false); // Don't use a Cached Copy conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("ENCTYPE", "multipart/form-data"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); conn.setRequestProperty("Cycleatl-Protocol-Version", "4"); SegmentData segmentData = SegmentData.fetchSegment(mCtx, currentNoteId); JSONObject json = segmentData.getJSON(); String deviceId = userId; DataOutputStream stream = new DataOutputStream(conn.getOutputStream()); stream.writeBytes(makeContentField("ratesegment", json.toString())); stream.writeBytes(makeContentField("version", String.valueOf(kSaveNoteProtocolVersion))); stream.writeBytes(makeContentField("device", deviceId)); stream.writeBytes(contentFieldPrefix); stream.flush(); stream.close(); int serverResponseCode = conn.getResponseCode(); String serverResponseMessage = conn.getResponseMessage(); Log.v(MODULE_TAG, "HTTP Response is : " + serverResponseMessage + ": " + serverResponseCode); if (serverResponseCode == 201 || serverResponseCode == 202) { segmentData.updateSegmentStatus(SegmentData.STATUS_SENT); result = true; } } catch (IllegalStateException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } catch (JSONException e) { e.printStackTrace(); return false; } return result; } @Override protected Boolean doInBackground(Long... noteid) { // First, send the note user asked for: Boolean result = true; if (noteid.length != 0) { result = uploadOneSegment(noteid[0]); } // Then, automatically try and send previously-completed notes // that were not sent successfully. return result && SendAllSegments(); } private boolean SendAllSegments() { boolean result = true; Vector<Long> unsentSegmentIds = new Vector<Long>(); mDb.openReadOnly(); try { Cursor cursor = mDb.fetchUnsentSegmentIds(); try { if (cursor != null && cursor.getCount() > 0) { // pd.setMessage("Sent. You have previously unsent notes; submitting those now."); while (!cursor.isAfterLast()) { unsentSegmentIds.add(Long.valueOf(cursor.getLong(0))); cursor.moveToNext(); } } } finally { cursor.close(); } } finally { mDb.close(); } for (Long segmentId : unsentSegmentIds) { result &= uploadOneSegment(segmentId); } return result; } @Override protected void onPreExecute() { Toast.makeText(mCtx.getApplicationContext(), "Submitting. Thanks for using ORCycle!", Toast.LENGTH_LONG) .show(); } @Override protected void onPostExecute(Boolean result) { } }