1c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li/*
2c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * Copyright (C) 2011 The Android Open Source Project
3c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li *
4c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * Licensed under the Apache License, Version 2.0 (the "License");
5c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * you may not use this file except in compliance with the License.
6c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * You may obtain a copy of the License at
7c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li *
8c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li *      http://www.apache.org/licenses/LICENSE-2.0
9c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li *
10c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * Unless required by applicable law or agreed to in writing, software
11c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * distributed under the License is distributed on an "AS IS" BASIS,
12c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * See the License for the specific language governing permissions and
14c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * limitations under the License.
15c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li */
16c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
17c343fa06491ee5677b735920032d92e055c16366Wu-cheng Lipackage com.android.camera;
18c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
19c343fa06491ee5677b735920032d92e055c16366Wu-cheng Liimport android.content.Context;
20c343fa06491ee5677b735920032d92e055c16366Wu-cheng Liimport android.location.Location;
21c343fa06491ee5677b735920032d92e055c16366Wu-cheng Liimport android.location.LocationProvider;
22c343fa06491ee5677b735920032d92e055c16366Wu-cheng Liimport android.os.Bundle;
23c343fa06491ee5677b735920032d92e055c16366Wu-cheng Liimport android.util.Log;
24c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
25c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li/**
26c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li * A class that handles everything about location.
27c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li */
28c343fa06491ee5677b735920032d92e055c16366Wu-cheng Lipublic class LocationManager {
29c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    private static final String TAG = "LocationManager";
30c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
31c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    private Context mContext;
32c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    private Listener mListener;
33c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    private android.location.LocationManager mLocationManager;
34c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    private boolean mRecordLocation;
35c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
36c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    LocationListener [] mLocationListeners = new LocationListener[] {
37c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            new LocationListener(android.location.LocationManager.GPS_PROVIDER),
38c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            new LocationListener(android.location.LocationManager.NETWORK_PROVIDER)
39c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    };
40c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
41c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    public interface Listener {
42c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        public void showGpsOnScreenIndicator(boolean hasSignal);
43c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        public void hideGpsOnScreenIndicator();
44c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li   }
45c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
46c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    public LocationManager(Context context, Listener listener) {
47c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        mContext = context;
48c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        mListener = listener;
49c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    }
50c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
51a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li    public Location getCurrentLocation() {
52a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        if (!mRecordLocation) return null;
53a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li
54a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        // go in best to worst order
55a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        for (int i = 0; i < mLocationListeners.length; i++) {
56a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li            Location l = mLocationListeners[i].current();
57a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li            if (l != null) return l;
58a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        }
59a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        Log.d(TAG, "No location received yet.");
60a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        return null;
61a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li    }
62a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li
63a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li    public void recordLocation(boolean recordLocation) {
64a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        if (mRecordLocation != recordLocation) {
65a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li            mRecordLocation = recordLocation;
66a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li            if (recordLocation) {
67a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li                startReceivingLocationUpdates();
68a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li            } else {
69a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li                stopReceivingLocationUpdates();
70a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li            }
71a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        }
72a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li    }
73a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li
74a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li    private void startReceivingLocationUpdates() {
75c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        if (mLocationManager == null) {
76c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            mLocationManager = (android.location.LocationManager)
77c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                    mContext.getSystemService(Context.LOCATION_SERVICE);
78c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
79c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        if (mLocationManager != null) {
80c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            try {
81c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                mLocationManager.requestLocationUpdates(
82c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        android.location.LocationManager.NETWORK_PROVIDER,
83c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        1000,
84c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        0F,
85c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        mLocationListeners[1]);
86c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            } catch (SecurityException ex) {
87c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                Log.i(TAG, "fail to request location update, ignore", ex);
88c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            } catch (IllegalArgumentException ex) {
89c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                Log.d(TAG, "provider does not exist " + ex.getMessage());
90c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            }
91c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            try {
92c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                mLocationManager.requestLocationUpdates(
93c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        android.location.LocationManager.GPS_PROVIDER,
94c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        1000,
95c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        0F,
96c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        mLocationListeners[0]);
97a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li                if (mListener != null) mListener.showGpsOnScreenIndicator(false);
98c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            } catch (SecurityException ex) {
99c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                Log.i(TAG, "fail to request location update, ignore", ex);
100c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            } catch (IllegalArgumentException ex) {
101c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                Log.d(TAG, "provider does not exist " + ex.getMessage());
102c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            }
103c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            Log.d(TAG, "startReceivingLocationUpdates");
104c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
105c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    }
106c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
107a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li    private void stopReceivingLocationUpdates() {
108c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        if (mLocationManager != null) {
109c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            for (int i = 0; i < mLocationListeners.length; i++) {
110c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                try {
111c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                    mLocationManager.removeUpdates(mLocationListeners[i]);
112c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                } catch (Exception ex) {
113c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                    Log.i(TAG, "fail to remove location listners, ignore", ex);
114c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                }
115c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            }
116c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            Log.d(TAG, "stopReceivingLocationUpdates");
117c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
118a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li        if (mListener != null) mListener.hideGpsOnScreenIndicator();
119c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    }
120c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
121c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    private class LocationListener
122c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            implements android.location.LocationListener {
123c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        Location mLastLocation;
124c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        boolean mValid = false;
125c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        String mProvider;
126c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
127c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        public LocationListener(String provider) {
128c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            mProvider = provider;
129c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            mLastLocation = new Location(mProvider);
130c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
131c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
132c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        @Override
133c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        public void onLocationChanged(Location newLocation) {
134c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            if (newLocation.getLatitude() == 0.0
135c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                    && newLocation.getLongitude() == 0.0) {
136c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                // Hack to filter out 0.0,0.0 locations
137c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                return;
138c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            }
139c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            // If GPS is available before start camera, we won't get status
140c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            // update so update GPS indicator when we receive data.
141a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li            if (mListener != null && mRecordLocation &&
142c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                    android.location.LocationManager.GPS_PROVIDER.equals(mProvider)) {
143c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                mListener.showGpsOnScreenIndicator(true);
144c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            }
145c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            if (!mValid) {
146c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                Log.d(TAG, "Got first location.");
147c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            }
148c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            mLastLocation.set(newLocation);
149c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            mValid = true;
150c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
151c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
152c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        @Override
153c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        public void onProviderEnabled(String provider) {
154c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
155c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
156c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        @Override
157c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        public void onProviderDisabled(String provider) {
158c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            mValid = false;
159c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
160c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
161c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        @Override
162c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        public void onStatusChanged(
163c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                String provider, int status, Bundle extras) {
164c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            switch(status) {
165c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                case LocationProvider.OUT_OF_SERVICE:
166c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                case LocationProvider.TEMPORARILY_UNAVAILABLE: {
167c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                    mValid = false;
168a93a4d60eacee4e12471b45f8691c14114e113a4Wu-cheng Li                    if (mListener != null && mRecordLocation &&
169c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                            android.location.LocationManager.GPS_PROVIDER.equals(provider)) {
170c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                        mListener.showGpsOnScreenIndicator(false);
171c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                    }
172c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                    break;
173c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li                }
174c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            }
175c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
176c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li
177c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        public Location current() {
178c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li            return mValid ? mLastLocation : null;
179c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li        }
180c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li    }
181c343fa06491ee5677b735920032d92e055c16366Wu-cheng Li}
182