LocationStatsAggregator.java revision 5d42ffa9462f87edbbdc61a8719f6c521c700de5
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.bordeaux.services; 18 19import android.content.Context; 20import android.location.Criteria; 21import android.location.Location; 22import android.location.LocationListener; 23import android.location.LocationManager; 24import android.location.LocationProvider; 25import android.os.Bundle; 26import android.os.Handler; 27import android.os.HandlerThread; 28import android.os.Message; 29import android.os.Process; 30import android.util.Log; 31import java.util.HashMap; 32import java.util.Map; 33 34// TODO: add functionality to detect speed (use GPS) when needed 35// withouth draining the battery quickly 36public class LocationStatsAggregator extends Aggregator { 37 final String TAG = "LocationStatsAggregator"; 38 public static final String CURRENT_LOCATION = "Current Location"; 39 public static final String CURRENT_SPEED = "Current Speed"; 40 41 // TODO: Collect location on every minute 42 private static final long MINIMUM_TIME = 60000; // milliseconds 43 44 // reset best location provider on every 5 minutes 45 private static final int BEST_PROVIDER_DURATION = 300000; 46 47 private static final float MINIMUM_DISTANCE = 0f; // meter 48 49 private static final int LOCATION_CHANGE = 1; 50 51 // record time when the location provider is set 52 private long mProviderSetTime; 53 54 private Handler mHandler; 55 private HandlerThread mHandlerThread; 56 private LocationManager mLocationManager; 57 private ClusterManager mClusterManager; 58 59 public LocationStatsAggregator(final Context context) { 60 mLocationManager = 61 (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 62 setClusteringThread(context); 63 requestLocationUpdate(); 64 } 65 66 public String[] getListOfFeatures(){ 67 String[] list = { CURRENT_LOCATION } ; 68 return list; 69 } 70 71 public Map<String,String> getFeatureValue(String featureName) { 72 HashMap<String,String> feature = new HashMap<String,String>(); 73 74 if (featureName.equals(CURRENT_LOCATION)) { 75 76 // TODO: check last known location first before sending out location request. 77 /* 78 Location location = 79 mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 80 */ 81 82 // TODO: instead of outputing "unknow" should just not output anything. 83 feature.put(CURRENT_LOCATION, mClusterManager.getSemanticLocation()); 84 } 85 return (Map) feature; 86 } 87 88 private void setClusteringThread(Context context) { 89 mClusterManager = new ClusterManager(context); 90 91 mHandlerThread = new HandlerThread("Location Handler", 92 Process.THREAD_PRIORITY_BACKGROUND); 93 mHandlerThread.start(); 94 mHandler = new Handler(mHandlerThread.getLooper()) { 95 96 @Override 97 public void handleMessage(Message msg) { 98 if (!(msg.obj instanceof Location)) { 99 return; 100 } 101 Location location = (Location) msg.obj; 102 switch(msg.what) { 103 case LOCATION_CHANGE: 104 mClusterManager.addSample(location); 105 break; 106 default: 107 super.handleMessage(msg); 108 } 109 } 110 }; 111 } 112 113 private void requestLocationUpdate() { 114 Criteria criteria = new Criteria(); 115 criteria.setAccuracy(Criteria.ACCURACY_COARSE); 116 criteria.setPowerRequirement(Criteria.POWER_LOW); 117 /* 118 criteria.setAltitudeRequired(false); 119 criteria.setBearingRequired(false); 120 criteria.setSpeedRequired(true); 121 */ 122 criteria.setCostAllowed(true); 123 124 String bestProvider = mLocationManager.getBestProvider(criteria, false); 125 Log.i(TAG, "Best Location Provider: " + bestProvider); 126 127 String bestAvailableProvider = mLocationManager.getBestProvider(criteria, true); 128 Log.i(TAG, "Best Available Location Provider: " + bestAvailableProvider); 129 130 mProviderSetTime = System.currentTimeMillis(); 131 if (bestAvailableProvider != null) { 132 mLocationManager.requestLocationUpdates( 133 bestAvailableProvider, MINIMUM_TIME, MINIMUM_DISTANCE, mLocationListener); 134 } 135 } 136 137 private final LocationListener mLocationListener = new LocationListener() { 138 public void onLocationChanged(Location location) { 139 long currentTime = location.getTime(); 140 if (currentTime - mProviderSetTime < MINIMUM_TIME) { 141 return; 142 } 143 mHandler.sendMessage(mHandler.obtainMessage(LOCATION_CHANGE, location)); 144 // search again for the location service 145 if (currentTime - mProviderSetTime > BEST_PROVIDER_DURATION) { 146 mLocationManager.removeUpdates(this); 147 Log.e(TAG, "reselect best location provider"); 148 requestLocationUpdate(); 149 } 150 } 151 152 public void onStatusChanged(String provider, int status, Bundle extras) { } 153 154 public void onProviderEnabled(String provider) { } 155 156 public void onProviderDisabled(String provider) { } 157 }; 158} 159