/************************************ * TO DOS: * 1. Popup window for turning GPS on * 2. If user doesn't turn GPS on, then quit? * 3. If GPS not returning a location (e.g. indoors), then? In this case, it just ignores all this data. * 4. So far, only checking if Wifi is *connected*. Should check if any open Wifi is available? * 5. If there is movement in 60 seconds, but no movement in 5-second span, we can't detect direction. Currently, it uses the lat/long * from the previous 60 second span (less accurate since more motion in 60 seconds than 5). Is this okay, * or should we just discard that data? * 6. What if we go out of range of GPS and then get WiFi (e.g. enter a building and then get WiFi). In this * case, we wouldn't get any location updates, and will not be capture the fact that WiFi was found. */ package com.cos598b; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.location.LocationManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.StrictMode; import android.provider.Settings; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class Home extends Activity { // Dialog IDs private final int DIALOG_GPS_OFF = 0; // dialog for when GPS is off private final int DIALOG_PROGRESS_SEND = 1; // dialog for progress bar, when sending data /* is WiFi connected */ private boolean isConnectedWiFi() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo[] ni = cm.getAllNetworkInfo(); for (NetworkInfo n : ni) { if (n.getTypeName().equalsIgnoreCase("wifi") && n.isConnected()) { return true; } } return false; } /* is mobile data connected? */ private boolean isConnectedMobile() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo[] ni = cm.getAllNetworkInfo(); for (NetworkInfo n : ni) { if (n.getTypeName().equalsIgnoreCase("mobile") && n.isConnected()) { return true; } } return false; } /* stop WiFi, if enabled */ private void disableWiFi() { WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); if (wm.isWifiEnabled()) { wm.setWifiEnabled(false); } } /* start WiFi, if disabled */ private void enableWiFi() { WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); if (!wm.isWifiEnabled()) { wm.setWifiEnabled(true); } } private void stop3G() { // impossibru } /** * thread to send points to backend */ private class SendPointsThread extends Thread { @Override public void run(){ int total_send = DatabaseHelper.getNumRows(Home.this); int sent = 0; while (DatabaseHelper.getNumRows(Home.this) > 0) { Map<String, String> data = DatabaseHelper.popFew(Home.this); // Create a new HttpClient and Post Header HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(Consts.SEND_POINTS_URL); try { // Add data List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); nameValuePairs.add(new BasicNameValuePair("lat", data.get(DatabaseHelper.KEY_LAT))); nameValuePairs.add(new BasicNameValuePair("lng", data.get(DatabaseHelper.KEY_LNG))); nameValuePairs.add(new BasicNameValuePair("bearing", data.get(DatabaseHelper.KEY_BEARING))); nameValuePairs.add(new BasicNameValuePair("timestamp", data.get(DatabaseHelper.KEY_TIMESTAMP))); nameValuePairs.add(new BasicNameValuePair("wifi_power_levels", data.get(DatabaseHelper.KEY_WIFI_POWER_LEVELS))); nameValuePairs.add(new BasicNameValuePair("speed", data.get(DatabaseHelper.KEY_SPEED))); nameValuePairs.add(new BasicNameValuePair("accuracy", data.get(DatabaseHelper.KEY_ACCURACY))); nameValuePairs.add(new BasicNameValuePair("user_id", Utils.getDeviceID(Home.this))); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); // make attempts int attempt = 0; while (attempt < Consts.HTTP_MAX_ATTEMPTS) { HttpResponse response = httpclient.execute(httppost); if (response.getStatusLine().getStatusCode() == 200) { break; } else { attempt = attempt + 1; } } Message msg = progressHandler.obtainMessage(); sent += data.get(DatabaseHelper.KEY_LAT).split(",").length; msg.arg1 = sent/total_send * 100; progressHandler.sendMessage(msg); } catch (ClientProtocolException e) { Log.d("Network error", e.toString()); } catch (IOException e) { Log.d("Network error", e.toString()); } } } } SendPointsThread sendPointsThread; ProgressDialog progressDialog; final Handler progressHandler = new Handler() { @Override public void handleMessage(Message msg) { int total = msg.arg1; progressDialog.setProgress(total); if (total >= 100){ dismissDialog(DIALOG_PROGRESS_SEND); } } }; // send data points to back-end private void sendPoints() { if (DatabaseHelper.getNumRows(Home.this) <= 0) { return; } SendPointsThread thread = new SendPointsThread(); showDialog(DIALOG_PROGRESS_SEND); thread.start(); } // fetch predictions from back-end private void getPredictions() { HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet(Consts.PREDICTION_MODEL_URL); // make attempts int attempt = 0; while (attempt < Consts.HTTP_MAX_ATTEMPTS) { try { HttpResponse response = httpclient.execute(httpget); if (response.getStatusLine().getStatusCode() == 200) { InputStream instream = response.getEntity().getContent(); BufferedReader br = new BufferedReader(new InputStreamReader(instream, "UTF-8")); String line; List<Double> lat_list = new ArrayList<Double>(); List<Double> lng_list = new ArrayList<Double>(); List<Double> bearing_list = new ArrayList<Double>(); List<Integer> time_list = new ArrayList<Integer>(); while ((line = br.readLine()) != null) { String[] parameters = line.split(" "); lat_list.add(Double.parseDouble(parameters[0])); lng_list.add(Double.parseDouble(parameters[1])); bearing_list.add(Double.parseDouble(parameters[2])); time_list.add((int) Double.parseDouble(parameters[3])); } DatabaseHelper.addPredictions(this, lat_list, lng_list, bearing_list, time_list); break; } else { attempt = attempt + 1; } } catch (ClientProtocolException e) { attempt = attempt + 1; } catch (IOException e) { attempt = attempt + 1; } } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); setContentView(R.layout.main); findViewById(R.id.send_button).setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (isConnectedWiFi() || isConnectedMobile()) { sendPoints(); } else { Utils.toast(Home.this, "DroiDTN: Internet Connection is unavailable. Please try again later."); } } }); findViewById(R.id.get_button).setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (isConnectedWiFi() || isConnectedMobile()) { getPredictions(); Utils.toast(Home.this, "Prediction Model Updated"); } else { Utils.toast(Home.this, "DroiDTN: Internet Connection is unavailable. Please try again later."); } } }); findViewById(R.id.service_button).setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (MarkovService.isServiceRunning()) { ((Button)findViewById(R.id.service_button)).setText(R.string.service_not_running); MarkovService.stopService(Home.this); } else { ((Button)findViewById(R.id.service_button)).setText(R.string.service_running); MarkovService.startService(Home.this); } } }); // if GPS is disabled, ask user to turn it on // Runs only once, when activity is created // XXX: Alternately could put it in onResume() to constantly remind user LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { showDialog(DIALOG_GPS_OFF); } } // handler and runnable to update number of points private Handler updateHandler = new Handler(); private Runnable updateRunnable = new Runnable() { @Override public void run() { refreshNumPoints(); } }; /** * Called every time activity gets focus */ @Override protected void onResume() { super.onResume(); if (MarkovService.isServiceRunning()) { ((Button)findViewById(R.id.service_button)).setText(R.string.service_running); } else { ((Button)findViewById(R.id.service_button)).setText(R.string.service_not_running); } refreshNumPoints(); } /** * Called whenever activity loses focus * Stops the refreshing of number of data points */ @Override protected void onPause() { super.onPause(); updateHandler.removeCallbacks(updateRunnable); Log.d("Refresh", "Stop refreshing"); } /** * refresh the number of points collected * sets timer to refresh points again according to REFRESH_RATE */ private void refreshNumPoints() { int num_points = DatabaseHelper.getNumRows(this); TextView tv = (TextView) findViewById(R.id.num_rows); tv.setText(Integer.toString(num_points)); updateHandler.postDelayed(updateRunnable, Consts.REFRESH_RATE*1000); // update at twice the rate of points being found Log.d("Refresh", "Refreshed number of datapoints"); } /** * Dialog to ask user to turn on GPS */ @Override protected Dialog onCreateDialog(int id) { switch (id) { // if GPS is off case DIALOG_GPS_OFF: AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("GPS is turned off. Would you like to turn it on?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { Intent gpsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); gpsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(gpsIntent); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert= builder.create(); return alert; // progress bar for sending data case DIALOG_PROGRESS_SEND: progressDialog = new ProgressDialog(Home.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setMessage("Sending..."); progressDialog.setCancelable(false); return progressDialog; } return null; } }