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 17package android.location; 18 19import java.util.HashMap; 20 21import android.os.Handler; 22import android.os.Looper; 23import android.os.RemoteException; 24import 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 * 48 * @hide 49 */ 50public class CountryDetector { 51 52 /** 53 * The class to wrap the ICountryListener.Stub and CountryListener objects 54 * together. The CountryListener will be notified through the specific 55 * looper once the country changed and detected. 56 */ 57 private final static class ListenerTransport extends ICountryListener.Stub { 58 59 private final CountryListener mListener; 60 61 private final Handler mHandler; 62 63 public ListenerTransport(CountryListener listener, Looper looper) { 64 mListener = listener; 65 if (looper != null) { 66 mHandler = new Handler(looper); 67 } else { 68 mHandler = new Handler(); 69 } 70 } 71 72 public void onCountryDetected(final Country country) { 73 mHandler.post(new Runnable() { 74 public void run() { 75 mListener.onCountryDetected(country); 76 } 77 }); 78 } 79 } 80 81 private final static String TAG = "CountryDetector"; 82 private final ICountryDetector mService; 83 private final HashMap<CountryListener, ListenerTransport> mListeners; 84 85 /** 86 * @hide - hide this constructor because it has a parameter of type 87 * ICountryDetector, which is a system private class. The right way to 88 * create an instance of this class is using the factory 89 * Context.getSystemService. 90 */ 91 public CountryDetector(ICountryDetector service) { 92 mService = service; 93 mListeners = new HashMap<CountryListener, ListenerTransport>(); 94 } 95 96 /** 97 * Start detecting the country that the user is in. 98 * 99 * @return the country if it is available immediately, otherwise null will 100 * be returned. 101 */ 102 public Country detectCountry() { 103 try { 104 return mService.detectCountry(); 105 } catch (RemoteException e) { 106 Log.e(TAG, "detectCountry: RemoteException", e); 107 return null; 108 } 109 } 110 111 /** 112 * Add a listener to receive the notification when the country is detected 113 * or changed. 114 * 115 * @param listener will be called when the country is detected or changed. 116 * @param looper a Looper object whose message queue will be used to 117 * implement the callback mechanism. If looper is null then the 118 * callbacks will be called on the main thread. 119 */ 120 public void addCountryListener(CountryListener listener, Looper looper) { 121 synchronized (mListeners) { 122 if (!mListeners.containsKey(listener)) { 123 ListenerTransport transport = new ListenerTransport(listener, looper); 124 try { 125 mService.addCountryListener(transport); 126 mListeners.put(listener, transport); 127 } catch (RemoteException e) { 128 Log.e(TAG, "addCountryListener: RemoteException", e); 129 } 130 } 131 } 132 } 133 134 /** 135 * Remove the listener 136 */ 137 public void removeCountryListener(CountryListener listener) { 138 synchronized (mListeners) { 139 ListenerTransport transport = mListeners.get(listener); 140 if (transport != null) { 141 try { 142 mListeners.remove(listener); 143 mService.removeCountryListener(transport); 144 } catch (RemoteException e) { 145 Log.e(TAG, "removeCountryListener: RemoteException", e); 146 } 147 } 148 } 149 } 150} 151