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