package com.cos598b; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; 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; public class PredictionRequestReceiver extends BroadcastReceiver { private Context mContext; private int tolerance; private int timer; private boolean callbackPending; // handler and runnable to scan for wifi private Handler scanHandler = new Handler(); private Runnable scanRunnable = new Runnable() { @Override public void run() { doWifiScan(); } }; @Override public void onReceive(Context context, Intent intent) { mContext = context; tolerance = intent.getIntExtra("tolerance", 0); timer = 0; callbackPending = true; // callback immediately if wifi is turned off if (!isWifiEnabled()) { callback("wifi not enabled"); return; } Utils.toast(mContext, "tolerance is " + tolerance); // scan for wifi scanHandler.post(scanRunnable); // scan for location if (callbackPending) { doLocationScan(); } } private void callback(String reason) { if (callbackPending) { Intent callback_intent = new Intent("com.cos598b.callback"); callback_intent.putExtra("reason", reason); mContext.sendBroadcast(callback_intent); callbackPending = false; } } private void doLocationScan() { LocationManager lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setBearingRequired(true); criteria.setBearingAccuracy(Criteria.ACCURACY_HIGH); criteria.setSpeedRequired(true); criteria.setSpeedAccuracy(Criteria.ACCURACY_HIGH); LocationListener locationListener = new LocationListener() { @Override public void onLocationChanged(Location arg0) { onLocation(arg0); } @Override public void onProviderDisabled(String arg0) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } }; try { lm.requestSingleUpdate(criteria, locationListener, null); } catch (Exception e) { callback("location not available"); } } private void onLocation(Location location) { // get prediction int time_to_wifi = DatabaseHelper.predict(mContext, location.getLatitude(), location.getLongitude(), location.getBearing(), location.getSpeed(), location.getAccuracy(), System.currentTimeMillis()); // if prediction is too long, then callback if (time_to_wifi > tolerance - timer) { callback("wifi will not be available soon"); } else { // display prediction if (callbackPending) { Utils.toast(mContext, "Wifi unavailable, but expected in " + Integer.toString(time_to_wifi-timer) + " seconds"); } } } private void doWifiScan() { // scan WifiManager wm = (WifiManager) mContext.getSystemService (Context.WIFI_SERVICE); wm.startScan(); // if wifi is connected, then callback if (isConnectedWiFi() && wm.getConnectionInfo().getRssi() > Consts.MIN_WIFI_RSSI) { callback("wifi found"); } else { // increment timer timer = timer + Consts.WIFI_SCAN_FREQUENCY; // callback if timer > tolerance if (timer > tolerance) { callback("timer expired"); } else { // prepare for next scan scanHandler.postDelayed(scanRunnable, Consts.WIFI_SCAN_FREQUENCY*1000); } } } private boolean isConnectedWiFi() { ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo[] ni = cm.getAllNetworkInfo(); for (NetworkInfo n : ni) { if (n.getTypeName().equalsIgnoreCase("wifi") && n.isConnected()) { return true; } } return false; } private boolean isWifiEnabled() { WifiManager wm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); return wm.isWifiEnabled(); } }