ComprehensiveCountryDetector.java revision a58a8751b4c2ce457f0082a0baaee61312d56195
1a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao/* 2a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Copyright (C) 2010 The Android Open Source Project 3a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 4a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Licensed under the Apache License, Version 2.0 (the "License"); 5a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * you may not use this file except in compliance with the License. 6a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * You may obtain a copy of the License at 7a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 8a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * http://www.apache.org/licenses/LICENSE-2.0 9a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 10a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Unless required by applicable law or agreed to in writing, software 11a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * distributed under the License is distributed on an "AS IS" BASIS, 12a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * See the License for the specific language governing permissions and 14a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * limitations under the License 15a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 16a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 17a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taopackage com.android.server.location; 18a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 19a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport java.util.Locale; 20a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport java.util.Timer; 21a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport java.util.TimerTask; 22a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 23a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.content.Context; 24a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.location.Country; 25a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.location.CountryListener; 26a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.location.Geocoder; 27a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.provider.Settings; 28a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.telephony.PhoneStateListener; 29a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.telephony.ServiceState; 30a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.telephony.TelephonyManager; 31a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.text.TextUtils; 32a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.util.Slog; 33a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 34a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao/** 35a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * This class is used to detect the country where the user is. The sources of 36a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * country are queried in order of reliability, like 37a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <ul> 38a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Mobile network</li> 39a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Location</li> 40a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>SIM's country</li> 41a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Phone's locale</li> 42a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * </ul> 43a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 44a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Call the {@link #detectCountry()} to get the available country immediately. 45a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 46a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * To be notified of the future country change, using the 47a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * {@link #setCountryListener(CountryListener)} 48a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 49a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Using the {@link #stop()} to stop listening to the country change. 50a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 51a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * The country information will be refreshed every 52a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * {@link #LOCATION_REFRESH_INTERVAL} once the location based country is used. 53a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 54a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @hide 55a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 56a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taopublic class ComprehensiveCountryDetector extends CountryDetectorBase { 57a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 58a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final static String TAG = "ComprehensiveCountryDetector"; 59a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 60a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 61a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * The refresh interval when the location based country was used 62a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 63a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final static long LOCATION_REFRESH_INTERVAL = 1000 * 60 * 60 * 24; // 1 day 64a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 65a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected CountryDetectorBase mLocationBasedCountryDetector; 66a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Timer mLocationRefreshTimer; 67a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 68a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final int mPhoneType; 69a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private Country mCountry; 70a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private TelephonyManager mTelephonyManager; 71a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private Country mCountryFromLocation; 72a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private boolean mStopped = false; 73a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private ServiceState mLastState; 74a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 75a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 76a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 77a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void onServiceStateChanged(ServiceState serviceState) { 78a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // TODO: Find out how often we will be notified, if this method is called too 79a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // many times, let's consider querying the network. 80a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Slog.d(TAG, "onServiceStateChanged"); 81a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // We only care the state change 82a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLastState == null || mLastState.getState() != serviceState.getState()) { 83a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao detectCountry(true, true); 84a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLastState = new ServiceState(serviceState); 85a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 86a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 87a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }; 88a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 89a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 90a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * The listener for receiving the notification from LocationBasedCountryDetector. 91a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 92a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private CountryListener mLocationBasedCountryDetectionListener = new CountryListener() { 93a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void onCountryDetected(Country country) { 94a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mCountryFromLocation = country; 95a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Don't start the LocationBasedCountryDetector. 96a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao detectCountry(true, false); 97a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao stopLocationBasedDetector(); 98a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 99a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }; 100a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 101a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public ComprehensiveCountryDetector(Context context) { 102a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao super(context); 103a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 104a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mPhoneType = mTelephonyManager.getPhoneType(); 105a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 106a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 107a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 108a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public Country detectCountry() { 109a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Don't start the LocationBasedCountryDetector if we have been stopped. 110a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return detectCountry(false, !mStopped); 111a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 112a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 113a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 114a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void stop() { 115a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Slog.i(TAG, "Stop the detector."); 116a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao cancelLocationRefresh(); 117a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao removePhoneStateListener(); 118a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao stopLocationBasedDetector(); 119a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListener = null; 120a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mStopped = true; 121a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 122a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 123a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 124a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Get the country from different sources in order of the reliability. 125a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 126a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private Country getCountry() { 127a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Country result = null; 128a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao result = getNetworkBasedCountry(); 129a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (result == null) { 130a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao result = getLastKnownLocationBasedCountry(); 131a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 132a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (result == null) { 133a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao result = getSimBasedCountry(); 134a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 135a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (result == null) { 136a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao result = getLocaleCountry(); 137a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 138a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return result; 139a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 140a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 141a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 142a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the country from the mobile network. 143a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 144a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Country getNetworkBasedCountry() { 145a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao String countryIso = null; 146a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // TODO: The document says the result may be unreliable on CDMA networks. Shall we use 147a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // it on CDMA phone? We may test the Android primarily used countries. 148a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mPhoneType == TelephonyManager.PHONE_TYPE_GSM) { 149a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao countryIso = mTelephonyManager.getNetworkCountryIso(); 150a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (!TextUtils.isEmpty(countryIso)) { 151a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return new Country(countryIso, Country.COUNTRY_SOURCE_NETWORK); 152a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 153a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 154a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return null; 155a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 156a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 157a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 158a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the cached location based country. 159a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 160a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Country getLastKnownLocationBasedCountry() { 161a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return mCountryFromLocation; 162a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 163a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 164a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 165a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the country from SIM card 166a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 167a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Country getSimBasedCountry() { 168a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao String countryIso = null; 169a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao countryIso = mTelephonyManager.getSimCountryIso(); 170a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (!TextUtils.isEmpty(countryIso)) { 171a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return new Country(countryIso, Country.COUNTRY_SOURCE_SIM); 172a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 173a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return null; 174a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 175a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 176a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 177a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the country from the system's locale. 178a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 179a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected Country getLocaleCountry() { 180a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Locale defaultLocale = Locale.getDefault(); 181a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (defaultLocale != null) { 182a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return new Country(defaultLocale.getCountry(), Country.COUNTRY_SOURCE_LOCALE); 183a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } else { 184a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return null; 185a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 186a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 187a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 188a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 189a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @param notifyChange indicates whether the listener should be notified the change of the 190a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * country 191a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @param startLocationBasedDetection indicates whether the LocationBasedCountryDetector could 192a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * be started if the current country source is less reliable than the location. 193a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the current available UserCountry 194a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 195a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private Country detectCountry(boolean notifyChange, boolean startLocationBasedDetection) { 196a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Country country = getCountry(); 197a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao runAfterDetectionAsync(mCountry != null ? new Country(mCountry) : mCountry, country, 198a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao notifyChange, startLocationBasedDetection); 199a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mCountry = country; 200a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return mCountry; 201a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 202a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 203a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 204a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Run the tasks in the service's thread. 205a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 206a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected void runAfterDetectionAsync(final Country country, final Country detectedCountry, 207a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao final boolean notifyChange, final boolean startLocationBasedDetection) { 208a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mHandler.post(new Runnable() { 209a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void run() { 210a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao runAfterDetection( 211a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao country, detectedCountry, notifyChange, startLocationBasedDetection); 212a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 213a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }); 214a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 215a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 216a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 217a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void setCountryListener(CountryListener listener) { 218a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao CountryListener prevListener = mListener; 219a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListener = listener; 220a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mListener == null) { 221a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Stop listening all services 222a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao removePhoneStateListener(); 223a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao stopLocationBasedDetector(); 224a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao cancelLocationRefresh(); 225a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } else if (prevListener == null) { 226a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao addPhoneStateListener(); 227a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao detectCountry(false, true); 228a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 229a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 230a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 231a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao void runAfterDetection(final Country country, final Country detectedCountry, 232a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao final boolean notifyChange, final boolean startLocationBasedDetection) { 233a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (notifyChange) { 234a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao notifyIfCountryChanged(country, detectedCountry); 235a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 236a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (startLocationBasedDetection && (detectedCountry == null 237a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao || detectedCountry.getSource() > Country.COUNTRY_SOURCE_LOCATION) 238a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao && isAirplaneModeOff() && mListener != null && isGeoCoderImplemented()) { 239a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Start finding location when the source is less reliable than the 240a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // location and the airplane mode is off (as geocoder will not 241a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // work). 242a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // TODO : Shall we give up starting the detector within a 243a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // period of time? 244a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao startLocationBasedDetector(mLocationBasedCountryDetectionListener); 245a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 246a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (detectedCountry == null 247a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao || detectedCountry.getSource() >= Country.COUNTRY_SOURCE_LOCATION) { 248a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Schedule the location refresh if the country source is 249a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // not more reliable than the location or no country is 250a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // found. 251a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // TODO: Listen to the preference change of GPS, Wifi etc, 252a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // and start detecting the country. 253a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao scheduleLocationRefresh(); 254a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } else { 255a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // Cancel the location refresh once the current source is 256a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // more reliable than the location. 257a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao cancelLocationRefresh(); 258a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao stopLocationBasedDetector(); 259a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 260a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 261a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 262a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 263a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Find the country from LocationProvider. 264a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 265a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private synchronized void startLocationBasedDetector(CountryListener listener) { 266a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLocationBasedCountryDetector != null) { 267a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return; 268a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 269a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector = createLocationBasedCountryDetector(); 270a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector.setCountryListener(listener); 271a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector.detectCountry(); 272a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 273a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 274a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private synchronized void stopLocationBasedDetector() { 275a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLocationBasedCountryDetector != null) { 276a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector.stop(); 277a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationBasedCountryDetector = null; 278a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 279a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 280a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 281a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected CountryDetectorBase createLocationBasedCountryDetector() { 282a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return new LocationBasedCountryDetector(mContext); 283a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 284a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 285a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected boolean isAirplaneModeOff() { 286a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return Settings.System.getInt( 287a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 0; 288a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 289a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 290a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 291a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Notify the country change. 292a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 293a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private void notifyIfCountryChanged(final Country country, final Country detectedCountry) { 294a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (detectedCountry != null && mListener != null 295a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao && (country == null || !country.equals(detectedCountry))) { 296a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Slog.d(TAG, 297a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao "The country was changed from " + country != null ? country.getCountryIso() : 298a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao country + " to " + detectedCountry.getCountryIso()); 299a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao notifyListener(detectedCountry); 300a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 301a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 302a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 303a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 304a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Schedule the next location refresh. We will do nothing if the scheduled task exists. 305a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 306a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private synchronized void scheduleLocationRefresh() { 307a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLocationRefreshTimer != null) return; 308a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer = new Timer(); 309a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer.schedule(new TimerTask() { 310a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 311a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void run() { 312a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer = null; 313a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao detectCountry(false, true); 314a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 315a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }, LOCATION_REFRESH_INTERVAL); 316a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 317a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 318a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 319a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Cancel the scheduled refresh task if it exists 320a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 321a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private synchronized void cancelLocationRefresh() { 322a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLocationRefreshTimer != null) { 323a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer.cancel(); 324a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLocationRefreshTimer = null; 325a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 326a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 327a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 328a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected synchronized void addPhoneStateListener() { 329a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mPhoneStateListener == null && mPhoneType == TelephonyManager.PHONE_TYPE_GSM) { 330a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLastState = null; 331a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mPhoneStateListener = new PhoneStateListener() { 332a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao @Override 333a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void onServiceStateChanged(ServiceState serviceState) { 334a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // TODO: Find out how often we will be notified, if this 335a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // method is called too 336a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // many times, let's consider querying the network. 337a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Slog.d(TAG, "onServiceStateChanged"); 338a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao // We only care the state change 339a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mLastState == null || mLastState.getState() != serviceState.getState()) { 340a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao detectCountry(true, true); 341a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mLastState = new ServiceState(serviceState); 342a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 343a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 344a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }; 345a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); 346a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 347a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 348a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 349a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected synchronized void removePhoneStateListener() { 350a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (mPhoneStateListener != null) { 351a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); 352a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mPhoneStateListener = null; 353a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 354a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 355a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 356a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao protected boolean isGeoCoderImplemented() { 357a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return Geocoder.isImplemented(); 358a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 359a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao} 360