Java tutorial
/** * AirProbe * Air quality application for Android, developed as part of * EveryAware project (<http://www.everyaware.eu>). * * Copyright (C) 2014 CSP Innovazione nelle ICT. All rights reserved. * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * * For any inquiry please write to <devel@csp.it> * * CONTRIBUTORS * * This program was made with the contribution of: * Fabio Saracino <fabio.saracino@csp.it> * Patrick Facco <patrick.facco@csp.it> * * * SOURCE CODE * * The source code of this program is available at * <https://github.com/CSPICT/airprobe> */ package org.csp.everyaware.internet; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.URI; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.zip.GZIPOutputStream; import javax.net.ssl.HttpsURLConnection; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.ParseException; import org.apache.http.ProtocolException; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.RedirectHandler; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.HttpHostConnectException; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import org.csp.everyaware.Constants; import org.csp.everyaware.R; import org.csp.everyaware.Start; import org.csp.everyaware.Utils; import org.csp.everyaware.db.DbManager; import org.csp.everyaware.db.Record; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.Service; import android.content.Intent; import android.os.AsyncTask; import android.os.Handler; import android.os.IBinder; import android.util.Log; public class StoreAndForwardService extends Service { private Handler mHandler; private boolean mConnectivityOn; private DbManager mDbManager; private List<Record> mToSendRecords; private List<Record> mAllLoadedRecords; private PostDataThread mPostDataThread; @Override public void onCreate() { Log.d("StoreAndForwardService", "***************************** onCreate() ***************************"); mHandler = new Handler(); mDbManager = DbManager.getInstance(getApplicationContext()); mPostDataThread = new PostDataThread(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("StoreAndForwardService", "*************************** onStartCommand() ***********************"); mHandler.postDelayed(mSendRecordsRunnable, Utils.getStoreForwInterval(getApplicationContext())); return super.onStartCommand(intent, flags, startId); } public void onStart(Intent intent, int startId) { Log.d("StoreAndForwardService", "****************************** onStart() ***************************"); super.onStart(intent, startId); } @Override public void onDestroy() { Log.d("StoreAndForwardService", "***************************** onDestroy() *************************"); mHandler.removeCallbacks(mSendRecordsRunnable); } @Override public IBinder onBind(Intent arg0) { return null; } /************************* RUNNABLE CHE INVIA RECORDS AL SERVER ****************************************/ private Runnable mSendRecordsRunnable = new Runnable() { @Override public void run() { Log.d("SendRecordsRunnable", "run() *******************************"); if ((mToSendRecords != null) && (mToSendRecords.size() > 0)) { Log.d("SendRecordsRunnable", "run()--> mToSendsRecords still contains data. This runnable will be recalled after N secs"); mHandler.postDelayed(this, Constants.storeForwHistFreqs); } else { //read network type index on which upload data is allowed: 0 - only wifi; 1 - both wifi and mobile int networkTypeIndex = Utils.getUploadNetworkTypeIndex(getApplicationContext()); //1 - is internet connection available? boolean[] connectivity = Utils.haveNetworkConnection(getApplicationContext()); //if user wants to upload only on wifi networks, connectivity[0] (network connectivity) must be true if (networkTypeIndex == 0) { if (connectivity[0]) mConnectivityOn = true; else mConnectivityOn = false; } else //if user wants to upload both on wifi/mobile networks mConnectivityOn = connectivity[0] || connectivity[1]; if (mConnectivityOn) { sendBroadcast(new Intent(Constants.INTERNET_ON)); Utils.uploadOn = Constants.INTERNET_ON_INT; } else { sendBroadcast(new Intent(Constants.INTERNET_OFF)); Utils.uploadOn = Constants.INTERNET_OFF_INT; } Log.d("SendRecordsRunnable", "run()--> Internet connection on: " + mConnectivityOn); if (mConnectivityOn) { if (mDbManager == null) mDbManager = DbManager.getInstance(getApplicationContext()); //if store'n'forward interval is 1 sec, load only records marked with actual session Id if (Utils.getStoreForwInterval(getApplicationContext()) == 1000) //2 - load from DB the N oldest record not yet sent to server mAllLoadedRecords = mDbManager.loadOlderNotUploadedRecords(Constants.REC_TO_UPLOAD_MAX_NUM, true); else { //2 - load from DB the N oldest record not yet sent to server if (Utils.historyDownloadMode) mAllLoadedRecords = mDbManager .loadOlderNotUploadedRecords(Constants.REC_TO_UPLOAD_MAX_NUM * 4, false); else mAllLoadedRecords = mDbManager .loadOlderNotUploadedRecords(Constants.REC_TO_UPLOAD_MAX_NUM, false); } //if there are records to send, send them, but, from ap 1.4, check if they are all of the //same semantic session seed (that can be an empty string if the are recorded out of a semantic //window) //only record in the mToSendRecords array will be sent to the server if ((mAllLoadedRecords != null) && (mAllLoadedRecords.size() > 0)) { mToSendRecords = new ArrayList<Record>(); String semanticSessionSeed = ""; int k = 0; Record temp = null; boolean stop = false; while ((k < mAllLoadedRecords.size()) && (!stop)) { temp = mAllLoadedRecords.get(k); //initialize value with semantic session seed from the first record if (k == 0) semanticSessionSeed = temp.mSemanticSessionSeed; //if actual record contains the same session seed of the first record, //add to array of record to be sent if (semanticSessionSeed.equals(temp.mSemanticSessionSeed)) mToSendRecords.add(temp); else //else stop! stop = true; k++; } Log.d("SendRecordsRunnable", "run()--> # all loaded records: " + mAllLoadedRecords.size() + " - # to send records: " + mToSendRecords.size()); /*** LOGGED USER ACCESS TOKEN ***/ //check if airprobe has been activated if (Utils.getAccountActivationState(getApplicationContext())) { //check if access token is available and valid. If it is expired (creation time + expires in is > actual time), ask for a new one if (checkIfAccessTokenIsValid()) { Log.d("SendRecordsRunnable", "run()--> access token is still valid"); try { //3 - send data to server in a gzip http compression format sendBroadcast(new Intent(Constants.UPLOAD_ON)); //send msg to UI thread Utils.uploadOn = Constants.UPLOAD_ON_INT; mPostDataThread = new PostDataThread(); mPostDataThread.start(); } catch (Exception e) { e.printStackTrace(); } finally { //5 - next runnable call is scheduled if (!Utils.historyDownloadMode) mHandler.postDelayed(this, Utils.getStoreForwInterval(getApplicationContext())); else mHandler.postDelayed(this, Constants.storeForwHistFreqs); } } //if AirProbe has been activated but access token is exipired, require new access token and send data else { Log.d("SendRecordsRunnable", "run()--> access token expired - ask for new one"); new RefreshTokenTask().execute(); } } /*** CLIENT ACCESS TOKEN ***/ //if AirProbe has not been activated, check if anonymous client access token is valid and use it to send data else { //check if access token for client is available and valid. If it is expired (creation time + expires in is > actual time), ask for a new one if (checkIfAccessTokenIsValidForClient()) { Log.d("SendRecordsRunnable", "run()--> access token FOR CLIENT is still valid"); try { //3 - send data to server in a gzip http compression format sendBroadcast(new Intent(Constants.UPLOAD_ON)); //send msg to UI thread Utils.uploadOn = Constants.UPLOAD_ON_INT; mPostDataThread = new PostDataThread(); mPostDataThread.start(); } catch (Exception e) { e.printStackTrace(); } finally { //5 - next runnable call is scheduled if (!Utils.historyDownloadMode) mHandler.postDelayed(this, Utils.getStoreForwInterval(getApplicationContext())); else mHandler.postDelayed(this, Constants.storeForwHistFreqs); } } //if AirProbe has not been activated and access token for client is exipired, require new access token for client and send data else { Log.d("SendRecordsRunnable", "run()--> access token for client expired - ask for new one"); new RefreshTokenTaskForClient().execute(); } } } else { sendBroadcast(new Intent(Constants.FINISHED_UPLOAD)); Utils.uploadOn = Constants.INTERNET_ON_INT; Log.d("SendRecordsRunnable", "run()--> No records to send"); //next runnable call is scheduled if (!Utils.historyDownloadMode) mHandler.postDelayed(this, Utils.getStoreForwInterval(getApplicationContext())); else mHandler.postDelayed(this, Constants.storeForwHistFreqs); } } else { Log.d("SendRecordsRunnable", "run()--> No internet connectivity"); //next runnable call is scheduled if (!Utils.historyDownloadMode) mHandler.postDelayed(this, Utils.getStoreForwInterval(getApplicationContext())); else mHandler.postDelayed(this, Constants.storeForwHistFreqs); } } } }; /********************** CALLS postData() FUNCTION *************************************************/ private class PostDataThread extends Thread { @Override public void run() { int statusCode = -1; //int statusCodeTags = -1; try { Thread.currentThread().sleep(0); //helpful for icon on/off sync if (Utils.report_url == null) { getServer(); if (Utils.report_url != null) { //statusCode = postData(); statusCode = postSecureData(); postSecureTags(); //postTags(); } } else { //statusCode = postData(); statusCode = postSecureData(); //postTags(); postSecureTags(); } } catch (InterruptedException e) { e.printStackTrace(); } //this exception is invoked when internet connection is up but traffic is not allowed //(for example, for networks that needs login but user is not logged) catch (HttpHostConnectException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } Log.d("PostDataThread", "run()--> status code: " + statusCode); /**********************/ //4 - if server response is HTTP 200 OK, mark sent records on db with timestamp // at the moment of data post if (statusCode == Constants.STATUS_OK) { long uploadSysTs = System.currentTimeMillis(); //actual system timestamp Log.d("PostDataThread", "run()--> # records to update with upload sys ts: " + mToSendRecords.size()); int size = mDbManager.updateUploadedRecord(mToSendRecords, uploadSysTs); //increment number of uploaded records stored on DB by 'size' quantity Utils.incrUploadedRecCount(getApplicationContext(), size); } //4b - if server response is HTTP 401 OK, access_token is expired and before sending again data // I need to require a new access token to server if (statusCode == Constants.STATUS_UNAUTHORIZED) { Log.d("PostDataThread", "run()--> STATUS_UNAUTHORIZED"); //do nothing in this case. This call to send record runnable isn't useful } //5 - cleaning of array to free memory if (mAllLoadedRecords != null) mAllLoadedRecords.clear(); if (mToSendRecords != null) mToSendRecords.clear(); //send msg to UI thread sendBroadcast(new Intent(Constants.UPLOAD_OFF)); Utils.uploadOn = Constants.INTERNET_ON_INT; synchronized (Start.class) { mPostDataThread = null; } } } /*************** SCRIVE FILE DI TESTO CONTENENTE OGGETTI JSON *****************************************/ public void writeTextFile(File txtFile) throws IOException { BufferedWriter bW = null; try { bW = new BufferedWriter(new FileWriter(txtFile)); bW.write("["); for (int i = 0; i < mToSendRecords.size(); i++) { bW.write(mToSendRecords.get(i).toJson().toString()); if (i != mToSendRecords.size() - 1) bW.write(","); bW.write("\n"); } bW.write("]"); } finally { try { if (bW != null) bW.close(); } catch (IOException e) { e.printStackTrace(); } } } /***************** METODO CHE COMPRIME UN FILE DI TESTO IN UNO ZIP **********************************/ /* private void compressFile(String inputFilename, String outputFilename) throws IOException { // Create a buffer for reading the files byte[] buf = new byte[1024]; // Create the ZIP file ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputFilename)); // Compress the files FileInputStream in = new FileInputStream(inputFilename); int index = inputFilename.lastIndexOf(File.separator); inputFilename = inputFilename.substring(index+1); // Add ZIP entry to output stream. out.putNextEntry(new ZipEntry(inputFilename)); // Transfer bytes from the file to the ZIP file int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } // Complete the entry out.closeEntry(); in.close(); // Complete the ZIP file out.close(); }*/ /************************ NEW TOKEN REQUEST *******************************************/ private class RefreshTokenTask extends AsyncTask<Void, Void, Boolean> { private boolean success = false; @Override protected Boolean doInBackground(Void... params) { try { //doHttpPost(); doSecureHttpPost(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e1) { e1.printStackTrace(); } catch (OutOfMemoryError e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } return success; } //if access token needed to be updated, the send of actual set of records is performed here @Override protected void onPostExecute(Boolean success) { Log.d("RefreshTokenTask", "onPostExecute()"); try { if (success) { //3 - send data to server in a gzip http compression format sendBroadcast(new Intent(Constants.UPLOAD_ON)); //send msg to UI thread Utils.uploadOn = Constants.UPLOAD_ON_INT; mPostDataThread = new PostDataThread(); mPostDataThread.start(); } else { if (mAllLoadedRecords != null) mAllLoadedRecords.clear(); //cleaning of array to free memory if (mToSendRecords != null) mToSendRecords.clear(); //send msg to UI thread sendBroadcast(new Intent(Constants.UPLOAD_OFF)); Utils.uploadOn = Constants.INTERNET_ON_INT; } } catch (Exception e) { e.printStackTrace(); } finally { //5 - next runnable call is scheduled if (!Utils.historyDownloadMode) mHandler.postDelayed(mSendRecordsRunnable, Utils.getStoreForwInterval(getApplicationContext())); else mHandler.postDelayed(mSendRecordsRunnable, Constants.storeForwHistFreqs); } } //makes a not secure (http://) post with hidden parameters to request the couple <access_token, refresh_token> //not used but do not delete it private void doHttpPost() throws ClientProtocolException, IOException, JSONException, OutOfMemoryError, IllegalArgumentException { int statusCode = -1; //http post to hide sent params DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(Constants.REFRESH_TOKEN_URL); // Add data List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token")); nameValuePairs.add(new BasicNameValuePair("client_id", "airprobe_android_client")); nameValuePairs.add(new BasicNameValuePair("client_secret", Constants.SECRET_KEY)); nameValuePairs .add(new BasicNameValuePair("refresh_token", Utils.getRefreshToken(getApplicationContext()))); httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); // Execute HTTP Post Request HttpResponse response = httpClient.execute(httpPost); //copio la entity response su output stream, ottenendo una stringa ByteArrayOutputStream out = new ByteArrayOutputStream(); response.getEntity().writeTo(out); String responseString = out.toString(); Log.d("RefreshTokenTask", "doHttpPost()--> " + responseString); statusCode = response.getStatusLine().getStatusCode(); //se la risposta dal server 'HTTP 200 OK' if (statusCode == Constants.STATUS_OK) { if (response.getEntity() != null) { JSONObject json = new JSONObject(responseString); String accessToken = json.getString("access_token"); String refreshToken = json.getString("refresh_token"); String tokenType = json.getString("token_type"); int expiresIn = json.getInt("expires_in"); Log.d("RefreshTokenTask", "doHttpPost()--> " + accessToken + " " + refreshToken + " " + tokenType + " " + expiresIn); //save account credentials in shared preferences Utils.setCredentialsData(getApplicationContext(), accessToken, refreshToken, tokenType, expiresIn, System.currentTimeMillis() / 1000); success = true; } } else { if (response.getEntity() != null) { JSONObject json = new JSONObject(responseString); String error = json.getString("error"); String errorDescr = json.getString("error_description"); Log.d("RefreshTokenTask", "doHttpPost()--> " + error + " " + errorDescr); success = false; } } } //makes a secure (https://) http post to request the couple <access_token, refresh_token> private void doSecureHttpPost() throws ClientProtocolException, IOException, JSONException, OutOfMemoryError, IllegalArgumentException { String urlString = Constants.REFRESH_TOKEN_URL; String urlParameters = "?grant_type=refresh_token&client_id=airprobe_android_client&client_secret=" + Constants.SECRET_KEY + "&refresh_token=" + Utils.getRefreshToken(getApplicationContext()); URL url = new URL(urlString + urlParameters); //URL url = new URL(Constants.REFRESH_TOKEN_URL); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setUseCaches(false); con.setDoInput(true); con.setDoOutput(true); int responseCode = con.getResponseCode(); //Log.d("RefreshTokenTask", "doSecureHttpPost()--> Sending 'POST' request to URL : " + url); //Log.d("RefreshTokenTask", "doSecureHttpPost()--> Post parameters : " + urlParameters); Log.d("RefreshTokenTask", "doSecureHttpPost()--> Response Code : " + responseCode); String responseString = getStringFromInputStream(con.getInputStream()); Log.d("RefreshTokenTask", "doSecureHttpPost()--> " + responseString); //se la risposta dal server 'HTTP 200 OK' if (responseCode == Constants.STATUS_OK) { JSONObject json = new JSONObject(responseString); String accessToken = json.getString("access_token"); String refreshToken = json.getString("refresh_token"); String tokenType = json.getString("token_type"); int expiresIn = json.getInt("expires_in"); Log.d("RefreshTokenTask", "doSecureHttpPost()--> " + accessToken + " " + refreshToken + " " + tokenType + " " + expiresIn); //save account credentials in shared preferences Utils.setCredentialsData(getApplicationContext(), accessToken, refreshToken, tokenType, expiresIn, System.currentTimeMillis() / 1000); success = true; } else { JSONObject json = new JSONObject(responseString); String error = json.getString("error"); String errorDescr = json.getString("error_description"); Log.d("RefreshTokenTask", "doSecureHttpPost()--> " + error + " " + errorDescr); success = false; } } private String getStringFromInputStream(InputStream is) { BufferedReader br = null; StringBuilder sb = new StringBuilder(); String line; try { br = new BufferedReader(new InputStreamReader(is)); while ((line = br.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } } private class RefreshTokenTaskForClient extends AsyncTask<Void, Void, Boolean> { private boolean success = false; @Override protected Boolean doInBackground(Void... params) { try { doSecureHttpPostForClient(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e1) { e1.printStackTrace(); } catch (OutOfMemoryError e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } return success; } //if access token needed to be updated, the send of actual set of records is performed here @Override protected void onPostExecute(Boolean success) { Log.d("RefreshTokenTaskForClient", "onPostExecute()"); try { if (success) { //3 - send data to server in a gzip http compression format sendBroadcast(new Intent(Constants.UPLOAD_ON)); //send msg to UI thread Utils.uploadOn = Constants.UPLOAD_ON_INT; mPostDataThread = new PostDataThread(); mPostDataThread.start(); } else { if (mAllLoadedRecords != null) mAllLoadedRecords.clear(); //cleaning of array to free memory if (mToSendRecords != null) mToSendRecords.clear(); //send msg to UI thread sendBroadcast(new Intent(Constants.UPLOAD_OFF)); Utils.uploadOn = Constants.INTERNET_ON_INT; } } catch (Exception e) { e.printStackTrace(); } finally { //5 - next runnable call is scheduled if (!Utils.historyDownloadMode) mHandler.postDelayed(mSendRecordsRunnable, Utils.getStoreForwInterval(getApplicationContext())); else mHandler.postDelayed(mSendRecordsRunnable, Constants.storeForwHistFreqs); } } //makes a secure (https://) http post to request the couple <access_token, refresh_token> private void doSecureHttpPostForClient() throws ClientProtocolException, IOException, JSONException, OutOfMemoryError, IllegalArgumentException { String urlString = Constants.REFRESH_TOKEN_URL; String urlParameters = "?grant_type=client_credentials&client_id=airprobe_android_client&client_secret=" + Constants.SECRET_KEY; URL url = new URL(urlString + urlParameters); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setUseCaches(false); con.setDoInput(true); con.setDoOutput(true); int responseCode = con.getResponseCode(); //Log.d("RefreshTokenTaskForClient", "doSecureHttpPostForClient()--> Sending 'POST' request to URL : " + url); //Log.d("RefreshTokenTaskForClient", "doSecureHttpPostForClient()--> Post parameters : " + urlParameters); Log.d("RefreshTokenTaskForClient", "doSecureHttpPostForClient()--> Response Code : " + responseCode); String responseString = getStringFromInputStream(con.getInputStream()); Log.d("RefreshTokenTaskForClient", "doSecureHttpPostForClient()--> " + responseString); //se la risposta dal server 'HTTP 200 OK' if (responseCode == Constants.STATUS_OK) { JSONObject json = new JSONObject(responseString); String accessToken = json.getString("access_token"); //String refreshToken = json.getString("refresh_token"); String tokenType = json.getString("token_type"); int expiresIn = json.getInt("expires_in"); Log.d("RefreshTokenTaskForClient", "doSecureHttpPostForClient()--> " + accessToken + " " + tokenType + " " + expiresIn); //save account credentials in shared preferences Utils.setCredentialsDataForClient(getApplicationContext(), accessToken, tokenType, expiresIn, System.currentTimeMillis() / 1000); success = true; } else { JSONObject json = new JSONObject(responseString); String error = json.getString("error"); String errorDescr = json.getString("error_description"); Log.d("RefreshTokenTaskForClient", "doSecureHttpPostForClient()--> " + error + " " + errorDescr); success = false; } } private String getStringFromInputStream(InputStream is) { BufferedReader br = null; StringBuilder sb = new StringBuilder(); String line; try { br = new BufferedReader(new InputStreamReader(is)); while ((line = br.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } } /***************** GET ENDPOINT ADDRESS FROM REDIRECT SERVER **************************/ public void getServer() throws IllegalArgumentException, ClientProtocolException, HttpHostConnectException, IOException { Log.d("StoreAndForwardService", "getServer()"); DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(Constants.REDIRECT_ADDR); httpClient.setRedirectHandler(new RedirectHandler() { @Override public URI getLocationURI(HttpResponse response, HttpContext context) throws ProtocolException { Log.d("StoreAndForwardService", "getServer() - getLocationURI()"); return null; } @Override public boolean isRedirectRequested(HttpResponse response, HttpContext context) throws ParseException { String responseBody = null; try { responseBody = EntityUtils.toString(response.getEntity()); } catch (IOException e) { e.printStackTrace(); } catch (OutOfMemoryError e) { e.printStackTrace(); } if (responseBody != null) { Log.d("StoreAndForwardService", "getServer() - isRedirectRequested()--> status line: " + response.getStatusLine()); if (response.getStatusLine().getStatusCode() == 302) { Header[] locHeader = response.getHeaders("Location"); if ((locHeader != null) && (locHeader.length > 0)) { Utils.report_url = locHeader[0].getValue(); Log.d("StoreAndForwardService", "getServer() - isRedirectRequested()--> report url: " + Utils.report_url); } Header[] countryHeader = response.getHeaders("Country"); if ((countryHeader != null) && (countryHeader.length > 0)) { Utils.report_country = countryHeader[0].getValue(); Log.d("StoreAndForwardService", "getServer() - isRedirectRequested()--> report country: " + Utils.report_country); } } else Log.d("StoreAndForwardService", "getServer() - isRedirectRequested()--> redirect server response is WRONG!"); } else Log.d("StoreAndForwardService", "getServer() - isRedirectRequested()--> response body from redirect server is NULL!"); return false; } }); httpClient.execute(httpPost); } /********************** SEND DATA TO SERVER *******************************************************/ //create an array of json objects containing records, compress it in gzip http compression format and send it to server public int postData() throws IllegalArgumentException, ClientProtocolException, HttpHostConnectException, IOException { Log.d("StoreAndForwardService", "postData()"); //get size of array of records to send and reference to the last record int size = mToSendRecords.size(); if (size == 0) return -1; int sepIndex = 1; //default is '.' separator (see Constants.separators array) if ((Utils.report_country != null) && (Utils.report_country.equals("IT"))) sepIndex = 0; //0 is for '-' separator (for italian CSP server) Record lastToSendRecord = mToSendRecords.get(size - 1); Log.d("StoreAndForwardService", "postData()--> # of records: " + size); //save timestamp long lastTimestamp = 0; if (lastToSendRecord.mSysTimestamp > 0) lastTimestamp = lastToSendRecord.mSysTimestamp; else lastTimestamp = lastToSendRecord.mBoxTimestamp; String lastTsFormatted = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSSz", Locale.US) .format(new Date(lastTimestamp)); //********* MAKING OF HTTP HEADER ************** DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(Utils.report_url); httpPost.setHeader("Content-Encoding", "gzip"); httpPost.setHeader("Content-Type", "application/json"); httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("User-Agent", "AirProbe" + Utils.appVer); //******** authorization bearer header ******** //air probe can be used also anymously. If account activation state is true (--> AirProbe activated) add this header if (Utils.getAccountActivationState(getApplicationContext())) httpPost.setHeader("Authorization", "Bearer " + Utils.getAccessToken(getApplicationContext())); //******** meta header (for new version API V1) httpPost.setHeader("meta" + Constants.separators[sepIndex] + "timestampRecorded", lastTsFormatted); //httpPost.setHeader("meta"+Constants.separators[sepIndex]+"sessionId", lastToSendRecord.mSessionId); //deprecated from AP 1.4 httpPost.setHeader("meta" + Constants.separators[sepIndex] + "deviceId", Utils.deviceID); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "installId", Utils.installID); //httpPost.setHeader("meta"+Constants.separators[sepIndex]+"userFeedId", ""); //httpPost.setHeader("meta"+Constants.separators[sepIndex]+"eventFeedId", ""); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "visibilityEvent", Constants.DATA_VISIBILITY[0]); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "visibilityGlobal", Constants.DATA_VISIBILITY[0]); //set meta.visibilityGlobal=DETAILS for testing (to retrieve data after insertion) /* from AP 1.4 */ if ((lastToSendRecord.mBoxMac != null) && (!lastToSendRecord.mBoxMac.equals(""))) { httpPost.setHeader("meta" + Constants.separators[sepIndex] + "sourceId", lastToSendRecord.mBoxMac); } httpPost.setHeader("meta" + Constants.separators[sepIndex] + "sourceSessionId" + Constants.separators[sepIndex] + "seed", lastToSendRecord.mSourceSessionSeed); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "sourceSessionId" + Constants.separators[sepIndex] + "number", String.valueOf(lastToSendRecord.mSourceSessionNumber)); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "sourceSessionPointNumber", String.valueOf(lastToSendRecord.mSourcePointNumber)); if ((lastToSendRecord.mSemanticSessionSeed != null) && (!lastToSendRecord.mSemanticSessionSeed.equals(""))) { httpPost.setHeader("meta" + Constants.separators[sepIndex] + "semanticSessionId" + Constants.separators[sepIndex] + "seed", lastToSendRecord.mSemanticSessionSeed); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "semanticSessionId" + Constants.separators[sepIndex] + "number", String.valueOf(lastToSendRecord.mSemanticSessionNumber)); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "semanticSessionPointNumber", String.valueOf(lastToSendRecord.mSemanticPointNumber)); } httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "typeVersion", "30"); //update by increment this field on header changes /* end of from AP 1.4 */ //******** data header (for new version API V1) httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "type", "airprobe_report"); httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "format", "json"); //httpPost.setHeader("data"+Constants.separators[sepIndex]+"contentDetails"+Constants.separators[sepIndex]+"specification", "a-3"); //deprecated from ap v1.4 if (size > 1) httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "list", "true"); else httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "list", "false"); httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "listSize", String.valueOf(size)); //******** geo header (for new version API V1) //add the right provider to header if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[0])) //sensor box { httpPost.setHeader("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mBoxLon)); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mBoxLat)); if (lastToSendRecord.mBoxAcc != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "hdop", String.valueOf(lastToSendRecord.mBoxAcc)); //from AP 1.4 if (lastToSendRecord.mBoxAltitude != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mBoxAltitude)); //from AP 1.4 if (lastToSendRecord.mBoxSpeed != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mBoxSpeed)); //from AP 1.4 if (lastToSendRecord.mBoxBear != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mBoxBear)); //from AP 1.4 httpPost.setHeader("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } else if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[1])) //phone { httpPost.setHeader("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mPhoneLon)); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mPhoneLat)); if (lastToSendRecord.mPhoneAcc != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "accuracy", String.valueOf(lastToSendRecord.mPhoneAcc)); if (lastToSendRecord.mPhoneAltitude != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mPhoneAltitude)); //from AP 1.4 if (lastToSendRecord.mPhoneSpeed != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mPhoneSpeed)); //from AP 1.4 if (lastToSendRecord.mPhoneBear != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mPhoneBear)); //from AP 1.4 httpPost.setHeader("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } else if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[2])) //network { httpPost.setHeader("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mNetworkLon)); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mNetworkLat)); if (lastToSendRecord.mNetworkAcc != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "accuracy", String.valueOf(lastToSendRecord.mNetworkAcc)); if (lastToSendRecord.mNetworkAltitude != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mNetworkAltitude)); //from AP 1.4 if (lastToSendRecord.mNetworkSpeed != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mNetworkSpeed)); //from AP 1.4 if (lastToSendRecord.mNetworkBear != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mNetworkBear)); //from AP 1.4 httpPost.setHeader("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } //******** MAKING OF HTTP CONTENT (JSON) ************* //writing string content as an array of json object StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0; i < mToSendRecords.size(); i++) { sb.append(mToSendRecords.get(i).toJson().toString()); if ((size != 0) && (i != size - 1)) sb.append(","); sb.append("\n"); } sb.append("]"); Log.d("StoreAndForwardService", "postData()--> json: " + sb.toString()); Log.d("StoreAndForwardService", "postData()--> access token: " + Utils.getAccessToken(getApplicationContext())); //compress json content into byte array entity byte[] contentGzippedBytes = zipStringToBytes(sb.toString()); ByteArrayEntity byteArrayEntity = new ByteArrayEntity(contentGzippedBytes); byteArrayEntity.setChunked(false); //IMPORTANT: put false for smartcity.csp.it server httpPost.setEntity(byteArrayEntity); Log.d("StoreAndForwardService", "postData()--> Content length: " + httpPost.getEntity().getContentLength()); Log.d("StoreAndForwardService", "postData()--> Method: " + httpPost.getMethod()); //do http post (it performs asynchronously) HttpResponse response = httpClient.execute(httpPost); sb = null; //server response Log.d("StoreAndForwardService", "postData()--> status line: " + response.getStatusLine()); httpClient.getConnectionManager().shutdown(); //server response, status line StatusLine statusLine = response.getStatusLine(); Log.d("StoreAndForwardService", "postData()--> status code: " + statusLine.getStatusCode()); return statusLine.getStatusCode(); } //create an array of json objects containing records, compress it in gzip http compression format and send it to server //makes a secure (https://) http post public int postSecureData() throws IllegalArgumentException, ClientProtocolException, HttpHostConnectException, IOException { Log.d("StoreAndForwardService", "postSecureData()"); //get size of array of records to send and reference to the last record int size = mToSendRecords.size(); if (size == 0) return -1; int sepIndex = 1; //default is '.' separator (see Constants.separators array) if ((Utils.report_country != null) && (Utils.report_country.equals("IT"))) sepIndex = 0; //0 is for '-' separator (for italian CSP server) Record lastToSendRecord = mToSendRecords.get(size - 1); Log.d("StoreAndForwardService", "postSecureData()--> # of records: " + size); //save timestamp long lastTimestamp = 0; if (lastToSendRecord.mSysTimestamp > 0) lastTimestamp = lastToSendRecord.mSysTimestamp; else lastTimestamp = lastToSendRecord.mBoxTimestamp; String lastTsFormatted = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSSz", Locale.US) .format(new Date(lastTimestamp)); //********* MAKING OF HTTP HEADER ************** URL url = new URL(Utils.report_url); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setUseCaches(false); con.setDoInput(true); con.setDoOutput(true); con.setRequestProperty("Content-Encoding", "gzip"); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Accept", "application/json"); con.setRequestProperty("User-Agent", "AirProbe" + Utils.appVer); //******** authorization bearer header ******** //air probe can be used also anymously. If account activation state is true (--> AirProbe activated) add this header if (Utils.getAccountActivationState(getApplicationContext())) con.setRequestProperty("Authorization", "Bearer " + Utils.getAccessToken(getApplicationContext())); else if (Utils.getAccountActivationStateForClient(getApplicationContext())) con.setRequestProperty("Authorization", "Bearer " + Utils.getAccessTokenForClient(getApplicationContext())); //******** meta header (for new version API V1) con.setRequestProperty("meta" + Constants.separators[sepIndex] + "timestampRecorded", lastTsFormatted); //con.setRequestProperty("meta"+Constants.separators[sepIndex]+"sessionId", lastToSendRecord.mSessionId); //deprecated from AP 1.4 con.setRequestProperty("meta" + Constants.separators[sepIndex] + "deviceId", Utils.deviceID); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "installId", Utils.installID); //con.setRequestProperty("meta"+Constants.separators[sepIndex]+"userFeedId", ""); //con.setRequestProperty("meta"+Constants.separators[sepIndex]+"eventFeedId", ""); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "visibilityEvent", Constants.DATA_VISIBILITY[0]); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "visibilityGlobal", Constants.DATA_VISIBILITY[0]); //set meta.visibilityGlobal=DETAILS for testing (to retrieve data after insertion) /* from AP 1.4 */ if ((lastToSendRecord.mBoxMac != null) && (!lastToSendRecord.mBoxMac.equals(""))) { Log.d("StoreAndForwardService", "postSecureData()--> box mac address: " + lastToSendRecord.mBoxMac); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "sourceId", lastToSendRecord.mBoxMac); } else con.setRequestProperty("meta" + Constants.separators[sepIndex] + "sourceId", Utils.getDeviceAddress(getApplicationContext())); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "sourceSessionId" + Constants.separators[sepIndex] + "seed", lastToSendRecord.mSourceSessionSeed); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "sourceSessionId" + Constants.separators[sepIndex] + "number", String.valueOf(lastToSendRecord.mSourceSessionNumber)); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "sourceSessionPointNumber", String.valueOf(lastToSendRecord.mSourcePointNumber)); if ((lastToSendRecord.mSemanticSessionSeed != null) && (!lastToSendRecord.mSemanticSessionSeed.equals(""))) { con.setRequestProperty("meta" + Constants.separators[sepIndex] + "semanticSessionId" + Constants.separators[sepIndex] + "seed", lastToSendRecord.mSemanticSessionSeed); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "semanticSessionId" + Constants.separators[sepIndex] + "number", String.valueOf(lastToSendRecord.mSemanticSessionNumber)); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "semanticSessionPointNumber", String.valueOf(lastToSendRecord.mSemanticPointNumber)); } con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "typeVersion", "30"); //update by increment this field on header changes /* end of from AP 1.4 */ //******** data header (for new version API V1) con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "type", "airprobe_report"); con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "format", "json"); //con.setRequestProperty("data"+Constants.separators[sepIndex]+"contentDetails"+Constants.separators[sepIndex]+"specification", "a-3"); //deprecated from AP 1.4 if (size > 1) con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "list", "true"); else con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "list", "false"); con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "listSize", String.valueOf(size)); //******** geo header (for new version API V1) //add the right provider to header if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[0])) //sensor box { con.setRequestProperty("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mBoxLon)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mBoxLat)); if (lastToSendRecord.mBoxAcc != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "hdop", String.valueOf(lastToSendRecord.mBoxAcc)); //from AP 1.4 if (lastToSendRecord.mBoxAltitude != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mBoxAltitude)); //from AP 1.4 if (lastToSendRecord.mBoxSpeed != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mBoxSpeed)); //from AP 1.4 if (lastToSendRecord.mBoxBear != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mBoxBear)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } else if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[1])) //phone { con.setRequestProperty("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mPhoneLon)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mPhoneLat)); if (lastToSendRecord.mPhoneAcc != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "accuracy", String.valueOf(lastToSendRecord.mPhoneAcc)); if (lastToSendRecord.mPhoneAltitude != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mPhoneAltitude)); //from AP 1.4 if (lastToSendRecord.mPhoneSpeed != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mPhoneSpeed)); //from AP 1.4 if (lastToSendRecord.mPhoneBear != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mPhoneBear)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } else if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[2])) //network { con.setRequestProperty("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mNetworkLon)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mNetworkLat)); if (lastToSendRecord.mNetworkAcc != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "accuracy", String.valueOf(lastToSendRecord.mNetworkAcc)); if (lastToSendRecord.mNetworkAltitude != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mNetworkAltitude)); //from AP 1.4 if (lastToSendRecord.mNetworkSpeed != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mNetworkSpeed)); //from AP 1.4 if (lastToSendRecord.mNetworkBear != 0) con.setRequestProperty("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mNetworkBear)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } //******** MAKING OF HTTP CONTENT (JSON) ************* //writing string content as an array of json object StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0; i < mToSendRecords.size(); i++) { sb.append(mToSendRecords.get(i).toJson().toString()); if ((size != 0) && (i != size - 1)) sb.append(","); sb.append("\n"); } sb.append("]"); //Log.d("StoreAndForwardService", "postSecureData()--> json: " +sb.toString()); //Log.d("StoreAndForwardService", "postSecureData()--> access token: "+Utils.getAccessToken(getApplicationContext())); //compress json content into byte array entity byte[] contentGzippedBytes = zipStringToBytes(sb.toString()); //write json compressed content into output stream OutputStream outputStream = con.getOutputStream(); outputStream.write(contentGzippedBytes); outputStream.flush(); outputStream.close(); int responseCode = con.getResponseCode(); Log.d("StoreAndForwardService", "postSecureData()--> response code: " + responseCode); sb = null; return responseCode; } //create an array of json objects containing only tags, compress it in gzip http compression format and send it to server public void postTags() throws IllegalArgumentException, ClientProtocolException, HttpHostConnectException, IOException { Log.d("StoreAndForwardService", "postTags()"); int sepIndex = 1; //default is '.' separator (see Constants.separators array) if ((Utils.report_country != null) && (Utils.report_country.equals("IT"))) sepIndex = 0; //0 is for '-' separator (for italian CSP server) List<String> sids = mDbManager.getSidsOfRecordsWithTags(); if ((sids != null) && (sids.size() > 0)) { for (int i = 0; i < sids.size(); i++) { String sessionId = (String) sids.get(i); //load records containing user tags with actual session id List<Record> recordsWithTags = mDbManager.loadRecordsWithTagBySessionId(sessionId); if ((recordsWithTags != null) && (recordsWithTags.size() > 0)) { //get size of array of records containing tags and reference to the last record int size = recordsWithTags.size(); //obtain reference to the last record of serie Record lastToSendRecord = recordsWithTags.get(size - 1); Log.d("StoreAndForwardService", "postTags()--> # of records containing tags: " + size); //save timestamp of last record containing tags long lastTimestamp = 0; if (lastToSendRecord.mSysTimestamp > 0) lastTimestamp = lastToSendRecord.mSysTimestamp; else lastTimestamp = lastToSendRecord.mBoxTimestamp; String lastTsFormatted = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSSz", Locale.US) .format(new Date(lastTimestamp)); //********* MAKING OF HTTP HEADER ************** DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(Utils.report_url); httpPost.setHeader("Content-Encoding", "gzip"); httpPost.setHeader("Content-Type", "application/json"); httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("User-Agent", "AirProbe" + Utils.appVer); // ******* authorization bearer header ******** httpPost.setHeader("Authorization", "Bearer " + Utils.getAccessToken(getApplicationContext())); //******** meta header (for new version API V1) httpPost.setHeader("meta" + Constants.separators[sepIndex] + "timestampRecorded", lastTsFormatted); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "deviceId", Utils.deviceID); httpPost.setHeader("meta" + Constants.separators[sepIndex] + "installId", Utils.installID); //******** data header (for new version API V1) //httpPost.setHeader("data"+Constants.separators[sepIndex]+"extendedPacketId", ""); //httpPost.setHeader("data"+Constants.separators[sepIndex]+"extendedPacketPointId", ""); //httpPost.setHeader("data"+Constants.separators[sepIndex]+"extendedSessionId", ""); //deprecated from AP 1.4 httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "type", "airprobe_tags"); httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "format", "json"); //httpPost.setHeader("data"+Constants.separators[sepIndex]+"contentDetails"+Constants.separators[sepIndex]+"specification", "at-3"); //deprecated from AP 1.4 if (size > 1) httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "list", "true"); else httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "list", "false"); httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "listSize", String.valueOf(size)); /* from AP 1.4 */ if ((lastToSendRecord.mBoxMac != null) && (!lastToSendRecord.mBoxMac.equals(""))) httpPost.setHeader("meta" + Constants.separators[sepIndex] + "sourceId", lastToSendRecord.mBoxMac); httpPost.setHeader("data" + Constants.separators[sepIndex] + "extendedSourceSessionId" + Constants.separators[sepIndex] + "seed", lastToSendRecord.mSourceSessionSeed); httpPost.setHeader( "data" + Constants.separators[sepIndex] + "extendedSourceSessionId" + Constants.separators[sepIndex] + "number", String.valueOf(lastToSendRecord.mSourceSessionNumber)); if ((lastToSendRecord.mSemanticSessionSeed != null) && (!lastToSendRecord.mSemanticSessionSeed.equals(""))) { httpPost.setHeader( "data" + Constants.separators[sepIndex] + "extendedSemanticSessionId" + Constants.separators[sepIndex] + "seed", lastToSendRecord.mSemanticSessionSeed); httpPost.setHeader( "data" + Constants.separators[sepIndex] + "extendedSemanticSessionId" + Constants.separators[sepIndex] + "number", String.valueOf(lastToSendRecord.mSemanticSessionNumber)); } httpPost.setHeader("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "typeVersion", "30"); //update by increment this field on header changes /* end of from AP 1.4 */ //******** geo header (for new version API V1) //add the right provider to header if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[0])) //sensor box { httpPost.setHeader("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mBoxLon)); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mBoxLat)); if (lastToSendRecord.mBoxAcc != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "hdop", String.valueOf(lastToSendRecord.mBoxAcc)); //from AP 1.4 if (lastToSendRecord.mBoxAltitude != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mBoxAltitude)); //from AP 1.4 if (lastToSendRecord.mBoxSpeed != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mBoxSpeed)); //from AP 1.4 if (lastToSendRecord.mBoxBear != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mBoxBear)); //from AP 1.4 httpPost.setHeader("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } else if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[1])) //phone { httpPost.setHeader("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mPhoneLon)); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mPhoneLat)); if (lastToSendRecord.mPhoneAcc != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "accuracy", String.valueOf(lastToSendRecord.mPhoneAcc)); if (lastToSendRecord.mPhoneAltitude != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mPhoneAltitude)); //from AP 1.4 if (lastToSendRecord.mPhoneSpeed != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mPhoneSpeed)); //from AP 1.4 if (lastToSendRecord.mPhoneBear != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mPhoneBear)); //from AP 1.4 httpPost.setHeader("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } else if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[2])) //network { httpPost.setHeader("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mNetworkLon)); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mNetworkLat)); if (lastToSendRecord.mNetworkAcc != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "accuracy", String.valueOf(lastToSendRecord.mNetworkAcc)); if (lastToSendRecord.mNetworkAltitude != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mNetworkAltitude)); //from AP 1.4 if (lastToSendRecord.mNetworkSpeed != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mNetworkSpeed)); //from AP 1.4 if (lastToSendRecord.mNetworkBear != 0) httpPost.setHeader("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mNetworkBear)); //from AP 1.4 httpPost.setHeader("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); httpPost.setHeader("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } //******** MAKING OF HTTP CONTENT (JSON) ************* //writing string content as an array of json object StringBuilder sb = new StringBuilder(); sb.append("["); JSONObject object = new JSONObject(); try { object.put("timestamp", lastTimestamp); JSONArray locations = new JSONArray(); //sensor box gps data if (lastToSendRecord.mBoxLat != 0) { JSONObject boxLocation = new JSONObject(); boxLocation.put("latitude", lastToSendRecord.mBoxLat); boxLocation.put("longitude", lastToSendRecord.mBoxLon); if (lastToSendRecord.mBoxAcc != 0) boxLocation.put("hdpop", lastToSendRecord.mBoxAcc); if (lastToSendRecord.mBoxAltitude != 0) boxLocation.put("altitude", lastToSendRecord.mBoxAltitude); if (lastToSendRecord.mBoxSpeed != 0) boxLocation.put("speed", lastToSendRecord.mBoxSpeed); if (lastToSendRecord.mBoxBear != 0) boxLocation.put("bearing", lastToSendRecord.mBoxBear); boxLocation.put("provider", Constants.GPS_PROVIDERS[0]); boxLocation.put("timestamp", lastToSendRecord.mBoxTimestamp); locations.put(0, boxLocation); } //phone gps data if (lastToSendRecord.mPhoneLat != 0) { JSONObject phoneLocation = new JSONObject(); phoneLocation.put("latitude", lastToSendRecord.mPhoneLat); phoneLocation.put("longitude", lastToSendRecord.mPhoneLon); if (lastToSendRecord.mPhoneAcc != 0) phoneLocation.put("accuracy", lastToSendRecord.mPhoneAcc); if (lastToSendRecord.mPhoneAltitude != 0) phoneLocation.put("altitude", lastToSendRecord.mPhoneAltitude); if (lastToSendRecord.mPhoneSpeed != 0) phoneLocation.put("speed", lastToSendRecord.mPhoneSpeed); if (lastToSendRecord.mPhoneBear != 0) phoneLocation.put("bearing", lastToSendRecord.mPhoneBear); phoneLocation.put("provider", Constants.GPS_PROVIDERS[1]); phoneLocation.put("timestamp", lastToSendRecord.mPhoneTimestamp); locations.put(1, phoneLocation); } //network gps data if (lastToSendRecord.mNetworkLat != 0) { JSONObject netLocation = new JSONObject(); netLocation.put("latitude", lastToSendRecord.mNetworkLat); netLocation.put("longitude", lastToSendRecord.mNetworkLon); if (lastToSendRecord.mNetworkAcc != 0) netLocation.put("accuracy", lastToSendRecord.mNetworkAcc); if (lastToSendRecord.mNetworkAltitude != 0) netLocation.put("altitude", lastToSendRecord.mNetworkAltitude); if (lastToSendRecord.mNetworkSpeed != 0) netLocation.put("speed", lastToSendRecord.mNetworkSpeed); if (lastToSendRecord.mNetworkBear != 0) netLocation.put("bearing", lastToSendRecord.mNetworkBear); netLocation.put("provider", Constants.GPS_PROVIDERS[2]); netLocation.put("timestamp", lastToSendRecord.mNetworkTimestamp); locations.put(2, netLocation); } object.put("locations", locations); } catch (JSONException e) { e.printStackTrace(); } String concatOfTags = ""; //put the tags of all records in concatOfTags string for (int j = 0; j < recordsWithTags.size(); j++) { if ((recordsWithTags.get(j).mUserData1 != null) && (!recordsWithTags.get(j).mUserData1.equals(""))) concatOfTags += recordsWithTags.get(j).mUserData1 + " "; } Log.d("StoreAndForwardService", "postTags()--> concat of tags: " + concatOfTags); try { String[] tags = concatOfTags.split(" "); JSONArray tagsArray = new JSONArray(); if ((tags != null) && (tags.length > 0)) { for (int k = 0; k < tags.length; k++) { if (!tags[k].equals("")) tagsArray.put(k, tags[k]); } } object.put("tags", tagsArray); //object.put("tags_cause", null); //object.put("tags_location", null); //object.put("tags_perception", null); } catch (JSONException e) { e.printStackTrace(); } sb.append(object.toString()); sb.append("]"); //Log.d("StoreAndForwardService", "]"); Log.d("StoreAndForwardService", "postTags()--> json to string: " + sb.toString()); byte[] contentGzippedBytes = zipStringToBytes(sb.toString()); ByteArrayEntity byteArrayEntity = new ByteArrayEntity(contentGzippedBytes); byteArrayEntity.setChunked(false); //IMPORTANT: must put false for smartcity.csp.it server //IMPORTANT: do not set the content-Length, because is embedded in Entity //httpPost.setHeader("Content-Length", byteArrayEntity.getContentLength()+""); httpPost.setEntity(byteArrayEntity); Log.d("StoreAndForwardService", "postTags()--> Content length: " + httpPost.getEntity().getContentLength()); Log.d("StoreAndForwardService", "postTags()--> Method: " + httpPost.getMethod()); //do http post (it performs asynchronously) HttpResponse response = httpClient.execute(httpPost); sb = null; //server response //String responseBody = EntityUtils.toString(response.getEntity()); //Log.d("StoreAndForwardService", "postTags()--> response: " +responseBody); Log.d("StoreAndForwardService", "postTags()--> status line: " + response.getStatusLine()); httpClient.getConnectionManager().shutdown(); //server response, status line StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == Constants.STATUS_OK) { Log.d("StoreAndForwardService", "postTags()--> STATUS OK"); mDbManager.deleteRecordsWithTagsBySessionId(sessionId); } else Log.d("StoreAndForwardService", "postTags()--> status error code: " + statusCode); } else Log.d("StoreAndForwardService", "postTags()--> no tags to send"); } } } //create an array of json objects containing only tags, compress it in gzip http compression format and send it to server public void postSecureTags() throws IllegalArgumentException, ClientProtocolException, HttpHostConnectException, IOException { Log.d("StoreAndForwardService", "postSecureTags()"); int sepIndex = 1; //default is '.' separator (see Constants.separators array) if ((Utils.report_country != null) && (Utils.report_country.equals("IT"))) sepIndex = 0; //0 is for '-' separator (for italian CSP server) List<String> sids = mDbManager.getSidsOfRecordsWithTags(); if ((sids != null) && (sids.size() > 0)) { for (int i = 0; i < sids.size(); i++) { String sessionId = (String) sids.get(i); //load records containing user tags with actual session id List<Record> recordsWithTags = mDbManager.loadRecordsWithTagBySessionId(sessionId); if ((recordsWithTags != null) && (recordsWithTags.size() > 0)) { //get size of array of records containing tags and reference to the last record int size = recordsWithTags.size(); //obtain reference to the last record of serie Record lastToSendRecord = recordsWithTags.get(size - 1); Log.d("StoreAndForwardService", "postSecureTags()--> # of records containing tags: " + size); //save timestamp of last record containing tags long lastTimestamp = 0; if (lastToSendRecord.mSysTimestamp > 0) lastTimestamp = lastToSendRecord.mSysTimestamp; else lastTimestamp = lastToSendRecord.mBoxTimestamp; String lastTsFormatted = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSSz", Locale.US) .format(new Date(lastTimestamp)); //********* MAKING OF HTTP HEADER ************** URL url = new URL(Utils.report_url); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setUseCaches(false); con.setDoInput(true); con.setDoOutput(true); con.setRequestProperty("Content-Encoding", "gzip"); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Accept", "application/json"); con.setRequestProperty("User-Agent", "AirProbe" + Utils.appVer); //******** authorization bearer header ******** if (Utils.getAccountActivationState(getApplicationContext())) con.setRequestProperty("Authorization", "Bearer " + Utils.getAccessToken(getApplicationContext())); else if (Utils.getAccountActivationStateForClient(getApplicationContext())) con.setRequestProperty("Authorization", "Bearer " + Utils.getAccessTokenForClient(getApplicationContext())); //******** meta header (for new version API V1) con.setRequestProperty("meta" + Constants.separators[sepIndex] + "timestampRecorded", lastTsFormatted); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "deviceId", Utils.deviceID); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "installId", Utils.installID); //******** data header (for new version API V1) //con.setRequestProperty("data"+Constants.separators[sepIndex]+"extendedPacketId", ""); //con.setRequestProperty("data"+Constants.separators[sepIndex]+"extendedPacketPointId", ""); //con.setRequestProperty("data"+Constants.separators[sepIndex]+"extendedSessionId", ""); //deprecated from AP 1.4 con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "type", "airprobe_tags"); con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "format", "json"); //con.setRequestProperty("data"+Constants.separators[sepIndex]+"contentDetails"+Constants.separators[sepIndex]+"specification", "at-3"); //update by increment this field on header changes if (size > 1) con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "list", "true"); else con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "list", "false"); con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "listSize", String.valueOf(size)); /* from AP 1.4 */ if ((lastToSendRecord.mBoxMac != null) && (!lastToSendRecord.mBoxMac.equals(""))) { Log.d("StoreAndForwardService", "postSecureData()--> box mac address: " + lastToSendRecord.mBoxMac); con.setRequestProperty("meta" + Constants.separators[sepIndex] + "sourceId", lastToSendRecord.mBoxMac); } else con.setRequestProperty("meta" + Constants.separators[sepIndex] + "sourceId", Utils.getDeviceAddress(getApplicationContext())); con.setRequestProperty("data" + Constants.separators[sepIndex] + "extendedSourceSessionId" + Constants.separators[sepIndex] + "seed", lastToSendRecord.mSourceSessionSeed); con.setRequestProperty( "data" + Constants.separators[sepIndex] + "extendedSourceSessionId" + Constants.separators[sepIndex] + "number", String.valueOf(lastToSendRecord.mSourceSessionNumber)); if ((lastToSendRecord.mSemanticSessionSeed != null) && (!lastToSendRecord.mSemanticSessionSeed.equals(""))) { con.setRequestProperty( "data" + Constants.separators[sepIndex] + "extendedSemanticSessionId" + Constants.separators[sepIndex] + "seed", lastToSendRecord.mSemanticSessionSeed); con.setRequestProperty( "data" + Constants.separators[sepIndex] + "extendedSemanticSessionId" + Constants.separators[sepIndex] + "number", String.valueOf(lastToSendRecord.mSemanticSessionNumber)); } con.setRequestProperty("data" + Constants.separators[sepIndex] + "contentDetails" + Constants.separators[sepIndex] + "typeVersion", "30"); //update by increment this field on header changes /* end of from AP 1.4 */ //******** geo header (for new version API V1) //add the right provider to header if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[0])) //sensor box { con.setRequestProperty("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mBoxLon)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mBoxLat)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } else if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[1])) //phone { con.setRequestProperty("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mPhoneLon)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mPhoneLat)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "accuracy", String.valueOf(lastToSendRecord.mPhoneAcc)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mPhoneAltitude)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mPhoneSpeed)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mPhoneBear)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } else if (lastToSendRecord.mGpsProvider.equals(Constants.GPS_PROVIDERS[2])) //network { con.setRequestProperty("geo" + Constants.separators[sepIndex] + "longitude", String.valueOf(lastToSendRecord.mNetworkLon)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "latitude", String.valueOf(lastToSendRecord.mNetworkLat)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "accuracy", String.valueOf(lastToSendRecord.mNetworkAcc)); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "altitude", String.valueOf(lastToSendRecord.mNetworkAltitude)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "speed", String.valueOf(lastToSendRecord.mNetworkSpeed)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "bearing", String.valueOf(lastToSendRecord.mNetworkBear)); //from AP 1.4 con.setRequestProperty("geo" + Constants.separators[sepIndex] + "provider", lastToSendRecord.mGpsProvider); con.setRequestProperty("geo" + Constants.separators[sepIndex] + "timestamp", lastTsFormatted); } //******** MAKING OF HTTP CONTENT (JSON) ************* //writing string content as an array of json object StringBuilder sb = new StringBuilder(); sb.append("["); JSONObject object = new JSONObject(); try { object.put("timestamp", lastTimestamp); JSONArray locations = new JSONArray(); //sensor box gps data if (lastToSendRecord.mBoxLat != 0) { JSONObject boxLocation = new JSONObject(); boxLocation.put("latitude", lastToSendRecord.mBoxLat); boxLocation.put("longitude", lastToSendRecord.mBoxLon); //boxLocation.put("accuracy", "null"); //boxLocation.put("altitude", "null"); //boxLocation.put("speed", "null"); //boxLocation.put("bearing", "null"); boxLocation.put("provider", Constants.GPS_PROVIDERS[0]); boxLocation.put("timestamp", lastToSendRecord.mBoxTimestamp); locations.put(0, boxLocation); } //phone gps data if (lastToSendRecord.mPhoneLat != 0) { JSONObject phoneLocation = new JSONObject(); phoneLocation.put("latitude", lastToSendRecord.mPhoneLat); phoneLocation.put("longitude", lastToSendRecord.mPhoneLon); phoneLocation.put("accuracy", lastToSendRecord.mAccuracy); phoneLocation.put("altitude", lastToSendRecord.mPhoneAltitude); phoneLocation.put("speed", lastToSendRecord.mPhoneSpeed); phoneLocation.put("bearing", lastToSendRecord.mPhoneBear); phoneLocation.put("provider", Constants.GPS_PROVIDERS[1]); phoneLocation.put("timestamp", lastToSendRecord.mPhoneTimestamp); locations.put(1, phoneLocation); } //network gps data if (lastToSendRecord.mNetworkLat != 0) { JSONObject netLocation = new JSONObject(); netLocation.put("latitude", lastToSendRecord.mNetworkLat); netLocation.put("longitude", lastToSendRecord.mNetworkLon); netLocation.put("accuracy", lastToSendRecord.mNetworkAcc); netLocation.put("altitude", lastToSendRecord.mNetworkAltitude); netLocation.put("speed", lastToSendRecord.mNetworkSpeed); netLocation.put("bearing", lastToSendRecord.mNetworkBear); netLocation.put("provider", Constants.GPS_PROVIDERS[2]); netLocation.put("timestamp", lastToSendRecord.mNetworkTimestamp); locations.put(2, netLocation); } object.put("locations", locations); } catch (JSONException e) { e.printStackTrace(); } String concatOfTags = ""; //put the tags of all records in concatOfTags string for (int j = 0; j < recordsWithTags.size(); j++) { if ((recordsWithTags.get(j).mUserData1 != null) && (!recordsWithTags.get(j).mUserData1.equals(""))) concatOfTags += recordsWithTags.get(j).mUserData1 + " "; } Log.d("StoreAndForwardService", "postSecureTags()--> concat of tags: " + concatOfTags); try { String[] tags = concatOfTags.split(" "); JSONArray tagsArray = new JSONArray(); if ((tags != null) && (tags.length > 0)) { for (int k = 0; k < tags.length; k++) { if (!tags[k].equals("")) tagsArray.put(k, tags[k]); } } object.put("tags", tagsArray); //object.put("tags_cause", null); //object.put("tags_location", null); //object.put("tags_perception", null); } catch (JSONException e) { e.printStackTrace(); } sb.append(object.toString()); sb.append("]"); Log.d("StoreAndForwardService", "postSecureTags()--> json to string: " + sb.toString()); //compress json content into byte array entity byte[] contentGzippedBytes = zipStringToBytes(sb.toString()); //write json compressed content into output stream OutputStream outputStream = con.getOutputStream(); outputStream.write(contentGzippedBytes); outputStream.flush(); outputStream.close(); int responseCode = con.getResponseCode(); Log.d("StoreAndForwardService", "postSecureTags()--> response code: " + responseCode); sb = null; if (responseCode == Constants.STATUS_OK) { Log.d("StoreAndForwardService", "postSecureTags()--> STATUS OK"); mDbManager.deleteRecordsWithTagsBySessionId(sessionId); } else Log.d("StoreAndForwardService", "postSecureTags()--> status error code: " + responseCode); } else Log.d("StoreAndForwardService", "postTags()--> no tags to send"); } } } public static byte[] zipStringToBytes(String input) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); //BufferedOutputStream buffs = new BufferedOutputStream (new GZIPOutputStream (bos)); //use PrintStream to avod converting a String into byte array, that can cause out of memory error final PrintStream printStream = new PrintStream(new GZIPOutputStream(bos)); printStream.print(input); printStream.close(); //buffs.write (input. getBytes ()); //buffs.close (); byte[] retval = bos.toByteArray(); bos.close(); return retval; } //check if actual access token is valid: creation time + expiresIn field must be > actual time public boolean checkIfAccessTokenIsValid() { long creationTime = Utils.getCreationTime(getApplicationContext()); if (creationTime < 0) return false; long expiresIn = Utils.getExpiresIn(getApplicationContext()); if (expiresIn < 0) return false; expiresIn -= 1000; long actualTime = System.currentTimeMillis() / 1000; //not valid date? if (actualTime <= 0) return false; //Log.d("StoreAndForwardService", "checkIfAccessTokenIsValid()--> creationTime: "+creationTime+" expiresIn: "+expiresIn+" actualTime: "+actualTime); if (creationTime + expiresIn > actualTime) { Log.d("StoreAndForwardService", "checkIfAccessTokenIsValid()--> STILL VALID ACCESS TOKEN - creationTime + expiresIn " + (creationTime + expiresIn) + " actualTime: " + actualTime); return true; } else return false; } //check if actual access token is valid: creation time + expiresIn field must be > actual time public boolean checkIfAccessTokenIsValidForClient() { long creationTime = Utils.getCreationTimeForClient(getApplicationContext()); if (creationTime < 0) return false; long expiresIn = Utils.getExpiresInForClient(getApplicationContext()); if (expiresIn < 0) return false; expiresIn -= 1000; long actualTime = System.currentTimeMillis() / 1000; //not valid date? if (actualTime <= 0) return false; //Log.d("StoreAndForwardService", "checkIfAccessTokenIsValidForClient()--> creationTime: "+creationTime+" expiresIn: "+expiresIn+" actualTime: "+actualTime); if (creationTime + expiresIn > actualTime) { Log.d("StoreAndForwardService", "checkIfAccessTokenIsValidForClient()--> STILL VALID ACCESS TOKEN - creationTime + expiresIn " + (creationTime + expiresIn) + " actualTime: " + actualTime); return true; } else return false; } }