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