• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ListenerTransport(CountryListener listener, Looper looper)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 
onCountryDetected(final Country country)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      */
CountryDetector(ICountryDetector service)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      */
detectCountry()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      */
addCountryListener(CountryListener listener, Looper looper)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      */
removeCountryListener(CountryListener listener)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