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