Home | History | Annotate | Download | only in location
      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