1984e52f31d596840cfa51b1238e1c43d2e1918f8saberian/* 2984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * Copyright (C) 2012 The Android Open Source Project 3984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * 4984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * Licensed under the Apache License, Version 2.0 (the "License"); 5984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * you may not use this file except in compliance with the License. 6984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * You may obtain a copy of the License at 7984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * 8984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * http://www.apache.org/licenses/LICENSE-2.0 9984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * 10984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * Unless required by applicable law or agreed to in writing, software 11984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * distributed under the License is distributed on an "AS IS" BASIS, 12984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * See the License for the specific language governing permissions and 14984e52f31d596840cfa51b1238e1c43d2e1918f8saberian * limitations under the License. 15984e52f31d596840cfa51b1238e1c43d2e1918f8saberian */ 16984e52f31d596840cfa51b1238e1c43d2e1918f8saberian 17984e52f31d596840cfa51b1238e1c43d2e1918f8saberianpackage android.bordeaux.services; 18984e52f31d596840cfa51b1238e1c43d2e1918f8saberian 1947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Linimport android.app.AlarmManager; 2047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Linimport android.app.PendingIntent; 2147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Linimport android.content.BroadcastReceiver; 22f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.content.Context; 2347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Linimport android.content.Intent; 2447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Linimport android.content.IntentFilter; 25f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.location.Criteria; 26f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.location.Location; 27f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.location.LocationListener; 28f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.location.LocationManager; 29f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.location.LocationProvider; 30f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.os.Bundle; 31f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.os.Handler; 32f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.os.HandlerThread; 33f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.os.Message; 34f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linimport android.os.Process; 3547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Linimport android.os.SystemClock; 3647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Linimport android.text.format.Time; 37984e52f31d596840cfa51b1238e1c43d2e1918f8saberianimport android.util.Log; 38984e52f31d596840cfa51b1238e1c43d2e1918f8saberianimport java.util.HashMap; 399c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Huaimport java.util.List; 40984e52f31d596840cfa51b1238e1c43d2e1918f8saberianimport java.util.Map; 41984e52f31d596840cfa51b1238e1c43d2e1918f8saberian 425d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin// TODO: add functionality to detect speed (use GPS) when needed 435d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin// withouth draining the battery quickly 44f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Linpublic class LocationStatsAggregator extends Aggregator { 45984e52f31d596840cfa51b1238e1c43d2e1918f8saberian final String TAG = "LocationStatsAggregator"; 46984e52f31d596840cfa51b1238e1c43d2e1918f8saberian public static final String CURRENT_LOCATION = "Current Location"; 475d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin public static final String CURRENT_SPEED = "Current Speed"; 48c7c9cf164cc58d03156a53be35e58c3b75871a23Ruei-sung Lin public static final String UNKNOWN_LOCATION = "Unknown Location"; 495d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin 5047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private static final long REPEAT_INTERVAL = 120000; 515d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin 5247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private static final long FRESH_THRESHOLD = 90000; 53f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 545d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin private static final int LOCATION_CHANGE = 1; 55f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 565d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin // record time when the location provider is set 57f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin private long mProviderSetTime; 58f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 59f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin private Handler mHandler; 60f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin private HandlerThread mHandlerThread; 6147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private AlarmManager mAlarmManager; 62f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin private LocationManager mLocationManager; 6347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 64f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin private ClusterManager mClusterManager; 65f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 6647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private Criteria mCriteria = new Criteria(); 6747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 6847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private LocationUpdater mLocationUpdater; 6947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 7047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private Context mContext; 7147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private PendingIntent mPendingIntent; 7247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 739c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua // Fake location, used for testing. 749c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua private String mFakeLocation = null; 759c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua 76f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin public LocationStatsAggregator(final Context context) { 775d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin mLocationManager = 785d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 7947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mAlarmManager = 8047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 8147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 825d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin setClusteringThread(context); 8347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 8447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mCriteria.setAccuracy(Criteria.ACCURACY_COARSE); 8547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mCriteria.setPowerRequirement(Criteria.POWER_LOW); 8647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin /* 8747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mCriteria.setAltitudeRequired(false); 8847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mCriteria.setBearingRequired(false); 8947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mCriteria.setSpeedRequired(true); 9047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin */ 9147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mCriteria.setCostAllowed(true); 9247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 9347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 9447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin IntentFilter filter = new IntentFilter(LocationUpdater.LOCATION_UPDATE); 9547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mLocationUpdater = new LocationUpdater(); 9647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin context.registerReceiver(mLocationUpdater, filter); 9747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 9847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin Intent intent = new Intent(LocationUpdater.LOCATION_UPDATE); 9947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 10047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mContext = context; 10147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); 10247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 10347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 10447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin SystemClock.elapsedRealtime() + 30000, // 10547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin REPEAT_INTERVAL, 10647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mPendingIntent); 10747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 10847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 10947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin public void release() { 11047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mContext.unregisterReceiver(mLocationUpdater); 11147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mAlarmManager.cancel(mPendingIntent); 112f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin } 113f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 114984e52f31d596840cfa51b1238e1c43d2e1918f8saberian public String[] getListOfFeatures(){ 1155d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin String[] list = { CURRENT_LOCATION } ; 116984e52f31d596840cfa51b1238e1c43d2e1918f8saberian return list; 117984e52f31d596840cfa51b1238e1c43d2e1918f8saberian } 118f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 119984e52f31d596840cfa51b1238e1c43d2e1918f8saberian public Map<String,String> getFeatureValue(String featureName) { 120f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin HashMap<String,String> feature = new HashMap<String,String>(); 1215d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin 122f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin if (featureName.equals(CURRENT_LOCATION)) { 12378a66d98346a69f65e9d38bb0c96a5418c007197Ruei-sung Lin // TODO: check last known location first before sending out location request. 12478a66d98346a69f65e9d38bb0c96a5418c007197Ruei-sung Lin /* 12578a66d98346a69f65e9d38bb0c96a5418c007197Ruei-sung Lin Location location = 12678a66d98346a69f65e9d38bb0c96a5418c007197Ruei-sung Lin mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 12778a66d98346a69f65e9d38bb0c96a5418c007197Ruei-sung Lin */ 128c7c9cf164cc58d03156a53be35e58c3b75871a23Ruei-sung Lin String location = mClusterManager.getSemanticLocation(); 129c7c9cf164cc58d03156a53be35e58c3b75871a23Ruei-sung Lin if (!location.equals(UNKNOWN_LOCATION)) { 1309c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua if (mFakeLocation != null) { 1319c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua feature.put(CURRENT_LOCATION, mFakeLocation); 1329c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua } else { 1339c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua feature.put(CURRENT_LOCATION, location); 1349c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua } 135c7c9cf164cc58d03156a53be35e58c3b75871a23Ruei-sung Lin } 136f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin } 137f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin return (Map) feature; 138984e52f31d596840cfa51b1238e1c43d2e1918f8saberian } 139f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 1409c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua public List<String> getClusterNames() { 1419c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua return mClusterManager.getClusterNames(); 1429c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua } 1439c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua 1449c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua // set a fake location using cluster name. 1459c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua // Set an empty string "" to disable the fake location 1469c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua public void setFakeLocation(String name) { 1479c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua if (name != null && name.length() != 0) 1489c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua mFakeLocation = name; 1499c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua else mFakeLocation = null; 1509c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua } 1519c3a7dc466e2f8de02e15030b2b7f4096ba97e5aWei Hua 15247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private Location getLastKnownLocation() { 15347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin List<String> providers = mLocationManager.getAllProviders(); 15447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin Location bestResult = null; 15547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin float bestAccuracy = Float.MAX_VALUE; 15647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin long bestTime; 15747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 15847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin // get the latest location data 15947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin long currTime = System.currentTimeMillis(); 16047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin for (String provider : providers) { 16147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin Location location = mLocationManager.getLastKnownLocation(provider); 16247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 16347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin if (location != null) { 16447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin float accuracy = location.getAccuracy(); 16547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin long time = location.getTime(); 16647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 16747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin if (currTime - time < FRESH_THRESHOLD && accuracy < bestAccuracy) { 16847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin bestResult = location; 16947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin bestAccuracy = accuracy; 17047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin bestTime = time; 17147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 17247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 17347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 17447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin if (bestResult != null) { 17547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin Log.i(TAG, "found location for free: " + bestResult); 17647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 17747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin return bestResult; 17847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 17947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 18047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private class LocationUpdater extends BroadcastReceiver { 18147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin String TAG = "LocationUpdater"; 18247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 18347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin public static final String LOCATION_UPDATE = "android.bordeaux.services.LOCATION_UPDATE"; 18447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 18547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin @Override 18647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin public void onReceive(Context context, Intent intent) { 18747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin Location location = getLastKnownLocation(); 18847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 18947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin if (location == null) { 19047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin String provider = mLocationManager.getBestProvider(mCriteria, true); 19147c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin Log.i(TAG, "Best Available Location Provider: " + provider); 19247c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mLocationManager.requestSingleUpdate(provider, mLocationListener, 19347c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mHandlerThread.getLooper()); 19447c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } else { 19547c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mHandler.sendMessage(mHandler.obtainMessage(LOCATION_CHANGE, location)); 19647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 19747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 19847c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin } 19947c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 2005d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin private void setClusteringThread(Context context) { 2015d42ffa9462f87edbbdc61a8719f6c521c700de5Ruei-sung Lin mClusterManager = new ClusterManager(context); 202f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 203f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin mHandlerThread = new HandlerThread("Location Handler", 204f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin Process.THREAD_PRIORITY_BACKGROUND); 205f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin mHandlerThread.start(); 206f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin mHandler = new Handler(mHandlerThread.getLooper()) { 207f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 208f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin @Override 209f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin public void handleMessage(Message msg) { 210f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin if (!(msg.obj instanceof Location)) { 211f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin return; 212f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin } 213f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin Location location = (Location) msg.obj; 214f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin switch(msg.what) { 215f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin case LOCATION_CHANGE: 216f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin mClusterManager.addSample(location); 217f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin break; 218f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin default: 219f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin super.handleMessage(msg); 220f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin } 221f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin } 222f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin }; 223f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin } 224f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 225f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin private final LocationListener mLocationListener = new LocationListener() { 22647c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin private static final String TAG = "LocationListener"; 22747c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin 228f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin public void onLocationChanged(Location location) { 229f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin mHandler.sendMessage(mHandler.obtainMessage(LOCATION_CHANGE, location)); 23047c0dc05cde9e9d9cc57e1393429006bf8b23b32Ruei-sung Lin mLocationManager.removeUpdates(this); 231f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin } 232f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 233f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin public void onStatusChanged(String provider, int status, Bundle extras) { } 234f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 235f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin public void onProviderEnabled(String provider) { } 236f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin 237f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin public void onProviderDisabled(String provider) { } 238f0f78449e8ab7d63894964c54b6ef390ca9ce044Ruei-sung Lin }; 239984e52f31d596840cfa51b1238e1c43d2e1918f8saberian} 240