Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of 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,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.common;
     18 
     19 import android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.net.ConnectivityManager;
     24 import android.net.NetworkInfo;
     25 import android.os.Handler;
     26 import android.os.Message;
     27 import android.util.Log;
     28 
     29 import java.util.HashMap;
     30 import java.util.Iterator;
     31 
     32 /**
     33  * A wrapper for a broadcast receiver that provides network connectivity
     34  * state information, independent of network type (mobile, Wi-Fi, etc.).
     35  * @deprecated Code tempted to use this class should simply listen for connectivity intents
     36  * (or poll ConnectivityManager) directly.
     37  * {@hide}
     38  */
     39 public class NetworkConnectivityListener {
     40     private static final String TAG = "NetworkConnectivityListener";
     41     private static final boolean DBG = false;
     42 
     43     private Context mContext;
     44     private HashMap<Handler, Integer> mHandlers = new HashMap<Handler, Integer>();
     45     private State mState;
     46     private boolean mListening;
     47     private String mReason;
     48     private boolean mIsFailover;
     49 
     50     /** Network connectivity information */
     51     private NetworkInfo mNetworkInfo;
     52 
     53     /**
     54      * In case of a Disconnect, the connectivity manager may have
     55      * already established, or may be attempting to establish, connectivity
     56      * with another network. If so, {@code mOtherNetworkInfo} will be non-null.
     57      */
     58     private NetworkInfo mOtherNetworkInfo;
     59 
     60     private ConnectivityBroadcastReceiver mReceiver;
     61 
     62     private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
     63         @Override
     64         public void onReceive(Context context, Intent intent) {
     65             String action = intent.getAction();
     66 
     67             if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
     68                 mListening == false) {
     69                 Log.w(TAG, "onReceived() called with " + mState.toString() + " and " + intent);
     70                 return;
     71             }
     72 
     73             boolean noConnectivity =
     74                 intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
     75 
     76             if (noConnectivity) {
     77                 mState = State.NOT_CONNECTED;
     78             } else {
     79                 mState = State.CONNECTED;
     80             }
     81 
     82             mNetworkInfo = (NetworkInfo)
     83                 intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
     84             mOtherNetworkInfo = (NetworkInfo)
     85                 intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
     86 
     87             mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
     88             mIsFailover =
     89                 intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
     90 
     91             if (DBG) {
     92                 Log.d(TAG, "onReceive(): mNetworkInfo=" + mNetworkInfo +  " mOtherNetworkInfo = "
     93                         + (mOtherNetworkInfo == null ? "[none]" : mOtherNetworkInfo +
     94                         " noConn=" + noConnectivity) + " mState=" + mState.toString());
     95             }
     96 
     97             // Notifiy any handlers.
     98             Iterator<Handler> it = mHandlers.keySet().iterator();
     99             while (it.hasNext()) {
    100                 Handler target = it.next();
    101                 Message message = Message.obtain(target, mHandlers.get(target));
    102                 target.sendMessage(message);
    103             }
    104         }
    105     };
    106 
    107     public enum State {
    108         UNKNOWN,
    109 
    110         /** This state is returned if there is connectivity to any network **/
    111         CONNECTED,
    112         /**
    113          * This state is returned if there is no connectivity to any network. This is set
    114          * to true under two circumstances:
    115          * <ul>
    116          * <li>When connectivity is lost to one network, and there is no other available
    117          * network to attempt to switch to.</li>
    118          * <li>When connectivity is lost to one network, and the attempt to switch to
    119          * another network fails.</li>
    120          */
    121         NOT_CONNECTED
    122     }
    123 
    124     /**
    125      * Create a new NetworkConnectivityListener.
    126      */
    127     public NetworkConnectivityListener() {
    128         mState = State.UNKNOWN;
    129         mReceiver = new ConnectivityBroadcastReceiver();
    130     }
    131 
    132     /**
    133      * This method starts listening for network connectivity state changes.
    134      * @param context
    135      */
    136     public synchronized void startListening(Context context) {
    137         if (!mListening) {
    138             mContext = context;
    139 
    140             IntentFilter filter = new IntentFilter();
    141             filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    142             context.registerReceiver(mReceiver, filter);
    143             mListening = true;
    144         }
    145     }
    146 
    147     /**
    148      * This method stops this class from listening for network changes.
    149      */
    150     public synchronized void stopListening() {
    151         if (mListening) {
    152             mContext.unregisterReceiver(mReceiver);
    153             mContext = null;
    154             mNetworkInfo = null;
    155             mOtherNetworkInfo = null;
    156             mIsFailover = false;
    157             mReason = null;
    158             mListening = false;
    159         }
    160     }
    161 
    162     /**
    163      * This methods registers a Handler to be called back onto with the specified what code when
    164      * the network connectivity state changes.
    165      *
    166      * @param target The target handler.
    167      * @param what The what code to be used when posting a message to the handler.
    168      */
    169     public void registerHandler(Handler target, int what) {
    170         mHandlers.put(target, what);
    171     }
    172 
    173     /**
    174      * This methods unregisters the specified Handler.
    175      * @param target
    176      */
    177     public void unregisterHandler(Handler target) {
    178         mHandlers.remove(target);
    179     }
    180 
    181     public State getState() {
    182         return mState;
    183     }
    184 
    185     /**
    186      * Return the NetworkInfo associated with the most recent connectivity event.
    187      * @return {@code NetworkInfo} for the network that had the most recent connectivity event.
    188      */
    189     public NetworkInfo getNetworkInfo() {
    190         return mNetworkInfo;
    191     }
    192 
    193     /**
    194      * If the most recent connectivity event was a DISCONNECT, return
    195      * any information supplied in the broadcast about an alternate
    196      * network that might be available. If this returns a non-null
    197      * value, then another broadcast should follow shortly indicating
    198      * whether connection to the other network succeeded.
    199      *
    200      * @return NetworkInfo
    201      */
    202     public NetworkInfo getOtherNetworkInfo() {
    203         return mOtherNetworkInfo;
    204     }
    205 
    206     /**
    207      * Returns true if the most recent event was for an attempt to switch over to
    208      * a new network following loss of connectivity on another network.
    209      * @return {@code true} if this was a failover attempt, {@code false} otherwise.
    210      */
    211     public boolean isFailover() {
    212         return mIsFailover;
    213     }
    214 
    215     /**
    216      * An optional reason for the connectivity state change may have been supplied.
    217      * This returns it.
    218      * @return the reason for the state change, if available, or {@code null}
    219      * otherwise.
    220      */
    221     public String getReason() {
    222         return mReason;
    223     }
    224 }
    225