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