ConnectivityManagerCompat.java revision c725e0cfeb10019175b9a7e1eba80081848f7484
1/* 2 * Copyright (C) 2012 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 17package android.support.v4.net; 18 19import android.content.Intent; 20import android.net.ConnectivityManager; 21import android.net.NetworkInfo; 22import android.os.Build; 23import android.support.annotation.IntDef; 24 25import java.lang.annotation.Retention; 26import java.lang.annotation.RetentionPolicy; 27 28import static android.net.ConnectivityManager.TYPE_MOBILE; 29import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; 30import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; 31import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; 32import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; 33import static android.net.ConnectivityManager.TYPE_WIFI; 34import static android.net.ConnectivityManager.TYPE_WIMAX; 35 36/** 37 * Helper for accessing features in {@link ConnectivityManager} introduced after 38 * API level 16 in a backwards compatible fashion. 39 */ 40public final class ConnectivityManagerCompat { 41 42 interface ConnectivityManagerCompatImpl { 43 boolean isActiveNetworkMetered(ConnectivityManager cm); 44 45 @RestrictBackgroundStatus 46 int getRestrictBackgroundStatus(ConnectivityManager cm); 47 } 48 49 /** @hide */ 50 @Retention(RetentionPolicy.SOURCE) 51 @IntDef(flag = false, value = { 52 RESTRICT_BACKGROUND_STATUS_DISABLED, 53 RESTRICT_BACKGROUND_STATUS_WHITELISTED, 54 RESTRICT_BACKGROUND_STATUS_ENABLED, 55 }) 56 public @interface RestrictBackgroundStatus { 57 } 58 59 /** 60 * Device is not restricting metered network activity while application is running on 61 * background. 62 */ 63 public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; 64 65 /** 66 * Device is restricting metered network activity while application is running on background, 67 * but application is allowed to bypass it. 68 * <p> 69 * In this state, application should take action to mitigate metered network access. 70 * For example, a music streaming application should switch to a low-bandwidth bitrate. 71 */ 72 public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; 73 74 /** 75 * Device is restricting metered network activity while application is running on background. 76 * <p> 77 * In this state, application should not try to use the network while running on background, 78 * because it would be denied. 79 */ 80 public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; 81 82 static class BaseConnectivityManagerCompatImpl implements ConnectivityManagerCompatImpl { 83 @Override 84 public boolean isActiveNetworkMetered(ConnectivityManager cm) { 85 final NetworkInfo info = cm.getActiveNetworkInfo(); 86 if (info == null) { 87 // err on side of caution 88 return true; 89 } 90 91 final int type = info.getType(); 92 switch (type) { 93 case TYPE_MOBILE: 94 case TYPE_MOBILE_DUN: 95 case TYPE_MOBILE_HIPRI: 96 case TYPE_MOBILE_MMS: 97 case TYPE_MOBILE_SUPL: 98 case TYPE_WIMAX: 99 return true; 100 case TYPE_WIFI: 101 return false; 102 default: 103 // err on side of caution 104 return true; 105 } 106 } 107 108 @Override 109 public int getRestrictBackgroundStatus(ConnectivityManager cm) { 110 return RESTRICT_BACKGROUND_STATUS_ENABLED; 111 } 112 } 113 114 static class HoneycombMR2ConnectivityManagerCompatImpl 115 extends BaseConnectivityManagerCompatImpl { 116 @Override 117 public boolean isActiveNetworkMetered(ConnectivityManager cm) { 118 return ConnectivityManagerCompatHoneycombMR2.isActiveNetworkMetered(cm); 119 } 120 } 121 122 static class JellyBeanConnectivityManagerCompatImpl 123 extends HoneycombMR2ConnectivityManagerCompatImpl { 124 @Override 125 public boolean isActiveNetworkMetered(ConnectivityManager cm) { 126 return ConnectivityManagerCompatJellyBean.isActiveNetworkMetered(cm); 127 } 128 } 129 130 static class Api24ConnectivityManagerCompatImpl 131 extends JellyBeanConnectivityManagerCompatImpl { 132 @Override 133 public int getRestrictBackgroundStatus(ConnectivityManager cm) { 134 //noinspection ResourceType 135 return ConnectivityManagerCompatApi24.getRestrictBackgroundStatus(cm); 136 } 137 } 138 139 private static final ConnectivityManagerCompatImpl IMPL; 140 141 static { 142 if (Build.VERSION.SDK_INT >= 24) { 143 IMPL = new Api24ConnectivityManagerCompatImpl(); 144 } else if (Build.VERSION.SDK_INT >= 16) { 145 IMPL = new JellyBeanConnectivityManagerCompatImpl(); 146 } else if (Build.VERSION.SDK_INT >= 13) { 147 IMPL = new HoneycombMR2ConnectivityManagerCompatImpl(); 148 } else { 149 IMPL = new BaseConnectivityManagerCompatImpl(); 150 } 151 } 152 153 /** 154 * Returns if the currently active data network is metered. A network is 155 * classified as metered when the user is sensitive to heavy data usage on 156 * that connection due to monetary costs, data limitations or 157 * battery/performance issues. You should check this before doing large 158 * data transfers, and warn the user or delay the operation until another 159 * network is available. 160 * <p>This method requires the caller to hold the permission 161 * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. 162 * 163 * @return {@code true} if large transfers should be avoided, otherwise 164 * {@code false}. 165 */ 166 public static boolean isActiveNetworkMetered(ConnectivityManager cm) { 167 return IMPL.isActiveNetworkMetered(cm); 168 } 169 170 /** 171 * Return the {@link NetworkInfo} that caused the given 172 * {@link ConnectivityManager#CONNECTIVITY_ACTION} broadcast. This obtains 173 * the current state from {@link ConnectivityManager} instead of using the 174 * potentially-stale value from 175 * {@link ConnectivityManager#EXTRA_NETWORK_INFO}. May be {@code null}. 176 */ 177 public static NetworkInfo getNetworkInfoFromBroadcast(ConnectivityManager cm, Intent intent) { 178 final NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); 179 if (info != null) { 180 return cm.getNetworkInfo(info.getType()); 181 } else { 182 return null; 183 } 184 } 185 186 /** 187 * Determines if the calling application is subject to metered network restrictions while 188 * running on background. 189 * 190 * @return {@link #RESTRICT_BACKGROUND_STATUS_DISABLED}, 191 * {@link #RESTRICT_BACKGROUND_STATUS_ENABLED}, 192 * or {@link #RESTRICT_BACKGROUND_STATUS_WHITELISTED} 193 */ 194 @RestrictBackgroundStatus 195 public static int getRestrictBackgroundStatus(ConnectivityManager cm) { 196 return IMPL.getRestrictBackgroundStatus(cm); 197 } 198 199 private ConnectivityManagerCompat() {} 200} 201