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