edu.pdx.cecs.orcycle.UserFeedbackUploader.java Source code

Java tutorial

Introduction

Here is the source code for edu.pdx.cecs.orcycle.UserFeedbackUploader.java

Source

/**
 *  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.Map;
import java.util.Map.Entry;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;

public class UserFeedbackUploader extends AsyncTask<Long, Integer, Boolean> {

    private static final String MODULE_TAG = "UserFeedbackUploader";
    private static final int kSaveProtocolVersion4 = 4;
    private static final String boundary = "cycle*******notedata*******atlanta";
    private static final String fieldSep = "--cycle*******notedata*******atlanta\r\n";

    public static final String USER_FEEDBACK = "feedback";
    private final String userId;

    private Context mCtx = null;

    public UserFeedbackUploader(Context ctx, String userId) {
        super();
        this.mCtx = ctx;
        this.userId = userId;
    }

    /**
     *
     * @return
     * @throws JSONException
     */
    private JSONObject getUserJSON() throws JSONException {

        String userFeedback = null;
        JSONObject userJson = null;

        SharedPreferences settings = mCtx.getSharedPreferences(UserFeedbackActivity.PREFS_USER_FEEDBACK_UPLOAD,
                Context.MODE_PRIVATE);
        Map<String, ?> prefs = settings.getAll();

        for (Entry<String, ?> p : prefs.entrySet()) {
            int key = Integer.parseInt(p.getKey());
            // CharSequence value = (CharSequence) p.getValue();

            switch (key) {

            case UserFeedbackActivity.PREF_FEEDBACK:
                userFeedback = (String) p.getValue();
                break;
            }
        }

        if (null != userFeedback) {
            if (null != (userJson = new JSONObject())) {
                userJson.put(USER_FEEDBACK, userFeedback);
            }
        }
        return userJson;
    }

    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);
        }
    }

    boolean uploadUserInfoV4() {
        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");

            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
            JSONObject jsonUser;
            if (null != (jsonUser = getUserJSON())) {
                try {
                    String deviceId = userId;

                    dos.writeBytes(fieldSep + ContentField("user") + jsonUser.toString() + "\r\n");
                    dos.writeBytes(
                            fieldSep + ContentField("version") + String.valueOf(kSaveProtocolVersion4) + "\r\n");
                    dos.writeBytes(fieldSep + ContentField("device") + deviceId + "\r\n");
                    dos.writeBytes(fieldSep);
                    dos.flush();
                } catch (Exception ex) {
                    Log.e(MODULE_TAG, ex.getMessage());
                    return false;
                } finally {
                    dos.close();
                }
                int serverResponseCode = conn.getResponseCode();
                String serverResponseMessage = conn.getResponseMessage();
                // JSONObject responseData = new JSONObject(serverResponseMessage);
                Log.v("Jason", "HTTP Response is : " + serverResponseMessage + ": " + serverResponseCode);
                if (serverResponseCode == 201 || serverResponseCode == 202) {
                    // TODO: Record somehow that data was uploaded successfully
                    result = true;
                }
            } else {
                result = false;
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } catch (JSONException e) {
            e.printStackTrace();
            return false;
        }
        return result;
    }

    private String ContentField(String type) {
        return "Content-Disposition: form-data; name=\"" + type + "\"\r\n\r\n";
    }

    @Override
    protected Boolean doInBackground(Long... dummy) {

        Boolean result = false;

        try {
            result = uploadUserInfoV4();
        } catch (Exception ex) {
            Log.e(MODULE_TAG, ex.getMessage());
        }

        return result;
    }

    @Override
    protected void onPreExecute() {
        Toast.makeText(mCtx.getApplicationContext(), "Submitting feedback. Thanks for using ORcycle!",
                Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onPostExecute(Boolean result) {
        try {
            if (result) {
                Toast.makeText(mCtx.getApplicationContext(), "User feedback uploaded successfully.",
                        Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(mCtx.getApplicationContext(), "ORcycle couldn't upload the information.",
                        Toast.LENGTH_LONG).show();
            }
        } catch (Exception e) {
            // Just don't toast if the view has gone out of context
        }
    }
}