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"); you may not 5a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * use this file except in compliance with the License. You may obtain a copy of 6a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 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, WITHOUT 12a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * License for the specific language governing permissions and limitations under 14a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * the License. 15a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 16a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 17a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taopackage android.location; 18a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 19a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport java.util.HashMap; 20a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 21a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.os.Handler; 22a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.os.Looper; 23a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.os.RemoteException; 24a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taoimport android.util.Log; 25a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 26a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao/** 27a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * This class provides access to the system country detector service. This 28a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * service allows applications to obtain the country that the user is in. 29a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 30a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * The country will be detected in order of reliability, like 31a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <ul> 32a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Mobile network</li> 33a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Location</li> 34a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>SIM's country</li> 35a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <li>Phone's locale</li> 36a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * </ul> 37a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 38a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Call the {@link #detectCountry()} to get the available country immediately. 39a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 40a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * To be notified of the future country change, use the 41a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * {@link #addCountryListener} 42a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 43a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 44a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * You do not instantiate this class directly; instead, retrieve it through 45a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * {@link android.content.Context#getSystemService 46a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Context.getSystemService(Context.COUNTRY_DETECTOR)}. 47a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * <p> 48a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions are needed. 49a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 50a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @hide 51a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 52a58a8751b4c2ce457f0082a0baaee61312d56195Bai Taopublic class CountryDetector { 53a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 54a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 55a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * The class to wrap the ICountryListener.Stub and CountryListener objects 56a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * together. The CountryListener will be notified through the specific 57a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * looper once the country changed and detected. 58a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 59a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final static class ListenerTransport extends ICountryListener.Stub { 60a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 61a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final CountryListener mListener; 62a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 63a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final Handler mHandler; 64a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 65a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public ListenerTransport(CountryListener listener, Looper looper) { 66a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListener = listener; 67a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (looper != null) { 68a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mHandler = new Handler(looper); 69a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } else { 70a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mHandler = new Handler(); 71a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 72a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 73a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 74a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void onCountryDetected(final Country country) { 75a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mHandler.post(new Runnable() { 76a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void run() { 77a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListener.onCountryDetected(country); 78a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 79a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao }); 80a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 81a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 82a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 83a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final static String TAG = "CountryDetector"; 84a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final ICountryDetector mService; 85a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao private final HashMap<CountryListener, ListenerTransport> mListeners; 86a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 87a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 88a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @hide - hide this constructor because it has a parameter of type 89a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * ICountryDetector, which is a system private class. The right way to 90a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * create an instance of this class is using the factory 91a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Context.getSystemService. 92a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 93a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public CountryDetector(ICountryDetector service) { 94a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mService = service; 95a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListeners = new HashMap<CountryListener, ListenerTransport>(); 96a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 97a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 98a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 99a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Start detecting the country that the user is in. 100a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 101a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @return the country if it is available immediately, otherwise null will 102a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * be returned. 103a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 104a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public Country detectCountry() { 105a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao try { 106a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return mService.detectCountry(); 107a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } catch (RemoteException e) { 108a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Log.e(TAG, "detectCountry: RemoteException", e); 109a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao return null; 110a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 111a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 112a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 113a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 114a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Add a listener to receive the notification when the country is detected 115a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * or changed. 116a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * 117a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @param listener will be called when the country is detected or changed. 118a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * @param looper a Looper object whose message queue will be used to 119a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * implement the callback mechanism. If looper is null then the 120a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * callbacks will be called on the main thread. 121a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 122a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void addCountryListener(CountryListener listener, Looper looper) { 123a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao synchronized (mListeners) { 124a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (!mListeners.containsKey(listener)) { 125a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao ListenerTransport transport = new ListenerTransport(listener, looper); 126a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao try { 127a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mService.addCountryListener(transport); 128a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListeners.put(listener, transport); 129a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } catch (RemoteException e) { 130a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Log.e(TAG, "addCountryListener: RemoteException", e); 131a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 132a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 133a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 134a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 135a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao 136a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao /** 137a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao * Remove the listener 138a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao */ 139a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao public void removeCountryListener(CountryListener listener) { 140a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao synchronized (mListeners) { 141a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao ListenerTransport transport = mListeners.get(listener); 142a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao if (transport != null) { 143a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao try { 144a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mListeners.remove(listener); 145a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao mService.removeCountryListener(transport); 146a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } catch (RemoteException e) { 147a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao Log.e(TAG, "removeCountryListener: RemoteException", e); 148a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 149a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 150a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 151a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao } 152a58a8751b4c2ce457f0082a0baaee61312d56195Bai Tao} 153