1. 网络状态改变使用静态注册还是动态注册
回答: 动态注册。因为当App关闭后,我们的应用将不再关心网络状态的改变了。
2. 添加必须的权限
<uses-permission android:name="android.permission.INTERNET"/>
<!--允许读取网络状态-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--允许读取wifi网络状态-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
3. 静态注册
<!--静态注册-->
<receiver
android:name=".NetReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
4. 动态注册
public class MainActivity extends AppCompatActivity {
private NetReceiver mReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mReceiver = new NetReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
5. NetReceiver代码
/**
* 网络状态监听广播
* 监听网络的改变状态,只有在用户操作网络连接开关(wifi, mobile)的时候接收广播,
* 然后再对应的界面进行相应的操作,并将状态保存在我们的app里面
* @author mazaiting
*/
public class NetReceiver extends BroadcastReceiver {
private static final String TAG = "NetReceiver";
public NetReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
/**
* 这个监听wifi的打开与关闭,与wifi的连接无关
*/
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
// 获取Wifi状态
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
Log.e(TAG, "onReceive: " + wifiState);
switch (wifiState) {
case WifiManager.WIFI_STATE_ENABLING:
// Wifi开启中
Log.e(TAG, "onReceive: Wifi开启中");
break;
case WifiManager.WIFI_STATE_ENABLED:
// Wifi可用
Log.e(TAG, "onReceive: Wifi可用");
break;
case WifiManager.WIFI_STATE_DISABLING:
// Wifi关闭中
Log.e(TAG, "onReceive: Wifi关闭中");
break;
case WifiManager.WIFI_STATE_DISABLED:
// Wifi已关闭
Log.e(TAG, "onReceive: Wifi已关闭");
break;
case WifiManager.WIFI_STATE_UNKNOWN:
// Wifi状态未知
Log.e(TAG, "onReceive: Wifi未知");
break;
default:
break;
}
}
/**
* 监听Wifi的连接状态,即是否连上了一个有效无线路由,当上变广播的状态时WifiManager.WIFI_STATE_DISABLING,
* 和WIFI_STATE_DISABLED的时候,根本不会解到这个广播在上边广播接到是WifiManager.WIFI_STATE_ENABLED状态
* 的同时也会接到这个广播,当然刚打开wifi肯定还没有连接到有效的无线
*/
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) {
// 获取网络信息
Parcelable parcelableExtra = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (null != parcelableExtra) {
// 强转为NetworkInfo对象
NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
// 获取网络状态
NetworkInfo.State state = networkInfo.getState();
// 判断状态
boolean isConnection = state == NetworkInfo.State.CONNECTED;
Log.e(TAG, "onReceive: " + isConnection);
Toast.makeText(context, "当前状态: " + isConnection , Toast.LENGTH_SHORT).show();
}
}
/**
* 这个监听网络连接的设置,包括Wifi和移动数据的打开和关闭
* 最好还是用这个监听,Wifi如果打开,关闭以及链接上可用的连接都会接到监听
* 这个广播的最大的弊端势必上边两个广播的反应都要慢
*/
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
// 获取连接管理者
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
// 获取网络状态信息
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
// 判断网络信息是否为空并且已连接
if (null != networkInfo && networkInfo.isConnected()) {
if (ConnectivityManager.TYPE_WIFI == networkInfo.getType()) {
// 判断是否为Wifi
Log.e(TAG, "onReceive: 当前Wifi可用");
Toast.makeText(context, "当前Wifi可用", Toast.LENGTH_SHORT).show();
} else if (ConnectivityManager.TYPE_MOBILE == networkInfo.getType()) {
// 判断是否为移动网络
Log.e(TAG, "onReceive: 当前移动网络可用");
Toast.makeText(context, "当前移动网络可用", Toast.LENGTH_SHORT).show();
}
Log.e(TAG, "onReceive: info.getTypeName--" + networkInfo.getTypeName());
Log.e(TAG, "onReceive: getSubtypeName--" + networkInfo.getSubtypeName());
Log.e(TAG, "onReceive: getState--" + networkInfo.getState());
Log.e(TAG, "onReceive: getDetailedState().name--" + networkInfo.getDetailedState().name());
Log.e(TAG, "onReceive: getExtraInfo--" + networkInfo.getExtraInfo());
Log.e(TAG, "onReceive: getType--" + networkInfo.getType());
} else {
Log.e(TAG, "onReceive: 当前没有网络连接,请确保你已经打开网络!");
Toast.makeText(context, "当前没有网络连接,请确保你已经打开网络!", Toast.LENGTH_SHORT).show();
}
}
}
}
6. 网络工具类NetUtil
/**
* 网络工具类
* @author mazaiting
* @date 2018/3/29
*/
public class NetUtil {
/**
* 判断当前网络是否是移动网络
*
* @param context 上下文
* @return boolean 3G
*/
public static boolean is3G(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
return activeNetInfo != null
&& activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE;
}
/**
* 判断当前网络是否是wifi网络
*
* @param context 上下文
* @return true: wifi; false: 非wifi
*/
public static boolean isWifi(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
return activeNetInfo != null
&& activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI;
}
/**
* 判断当前网络是否是2G网络
*
* @param context 上下文
* @return true: 2G; false: 不是2G
*/
public static boolean is2G(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (null != activeNetInfo && (activeNetInfo.getSubtype() == TelephonyManager.NETWORK_TYPE_EDGE
|| activeNetInfo.getSubtype() == TelephonyManager.NETWORK_TYPE_GPRS || activeNetInfo
.getSubtype() == TelephonyManager.NETWORK_TYPE_CDMA)) {
return true;
}
return false;
}
/**
* wifi是否打开
* @param context 上下文
* @return true: 打开; false: 未打开
*/
public static boolean isWifiEnabled(Context context) {
ConnectivityManager mgrConn = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
TelephonyManager mgrTel = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
return ((mgrConn.getActiveNetworkInfo() != null && mgrConn
.getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) || mgrTel
.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS);
}
/**
* 判断是否有网络连接
*
* @param context 上下文
* @return 网络连接
*/
public static boolean isNetworkConnected(Context context) {
if (null != context) {
// 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
.CONNECTIVITY_SERVICE);
// 获取NetworkInfo对象
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
//判断NetworkInfo对象是否为空
if (null != networkInfo) {
return networkInfo.isAvailable();
}
}
return false;
}
/**
* 判断MOBILE网络是否可用
*
* @param context 上下文
* @return true, 可用; false,不可用
*/
public static boolean isMobileConnected(Context context) {
if (context != null) {
//获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
.CONNECTIVITY_SERVICE);
//获取NetworkInfo对象
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
//判断NetworkInfo对象是否为空 并且类型是否为MOBILE
if (null != networkInfo && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
return networkInfo.isAvailable();
}
}
return false;
}
/**
* 获取当前网络连接的类型信息
* 原生
*
* @param context 上下文
* @return 网络类型
*/
public static int getConnectedType(Context context) {
if (null != context) {
//获取手机所有连接管理对象
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
.CONNECTIVITY_SERVICE);
//获取NetworkInfo对象
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (null != networkInfo && networkInfo.isAvailable()) {
//返回NetworkInfo的类型
return networkInfo.getType();
}
}
return -1;
}
/**
* 获取当前的网络状态 :没有网络-0:WIFI网络1:4G网络-4:3G网络-3:2G网络-2
* 自定义
*
* @param context 上下文
* @return 网络类型
*/
public static int getApnType(Context context) {
//结果返回值
int netType = 0;
//获取手机所有连接管理对象
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
.CONNECTIVITY_SERVICE);
//获取NetworkInfo对象
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
//NetworkInfo对象为空 则代表没有网络
if (networkInfo == null) {
return netType;
}
//否则 NetworkInfo对象不为空 则获取该networkInfo的类型
int nType = networkInfo.getType();
if (nType == ConnectivityManager.TYPE_WIFI) {
//WIFI
netType = 1;
} else if (nType == ConnectivityManager.TYPE_MOBILE) {
// 获取子类型
int nSubType = networkInfo.getSubtype();
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService
(Context.TELEPHONY_SERVICE);
if (nSubType == TelephonyManager.NETWORK_TYPE_LTE
&& !telephonyManager.isNetworkRoaming()) {
// 4G
netType = 4;
} else if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
|| nSubType == TelephonyManager.NETWORK_TYPE_HSDPA
|| nSubType == TelephonyManager.NETWORK_TYPE_EVDO_0
&& !telephonyManager.isNetworkRoaming()) {
//3G 联通的3G为UMTS或HSDPA 电信的3G为EVDO
netType = 3;
} else if (nSubType == TelephonyManager.NETWORK_TYPE_GPRS
|| nSubType == TelephonyManager.NETWORK_TYPE_EDGE
|| nSubType == TelephonyManager.NETWORK_TYPE_CDMA
&& !telephonyManager.isNetworkRoaming()) {
//2G 移动和联通的2G为GPRS或EGDE,电信的2G为CDMA
netType = 2;
} else {
netType = 2;
}
}
return netType;
}
/**
* 获得本机ip地址
*
* @return ip地址
*/
public static String getHostIp() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface
.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface networkInterface = en.nextElement();
for (Enumeration<InetAddress> ipAdd = networkInterface.getInetAddresses(); ipAdd
.hasMoreElements(); ) {
InetAddress inetAddress = ipAdd.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress.getHostAddress();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}