在实际开发中在我们的 app 中几乎都会用到网络,有时我们需要在网络改变时给用户一些体验上的友好提示,比如:我们在视频播放时,由wifi切换到4G网络时,要给用户提示,当前为 4G 网络状态,注意流量的使用等.
网络变化的监听
实现方法,我们通过添加广播的方式,监听网络变化.
1. 添加网络状态权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- 创建网络变化监听广播
public class NetStatusBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//当网络变化时,该广播中该方法会被回调.
}
}
- 在 AndroidManifest.xml 中添加广播的配置信息,如下:
<receiver android:name=".NetStatusBroadcast">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
实现这个功能很简单,就上面这个几行代码就可以实现.
在注册网络变化监听时,建议是使用动态注册方式.不要忘记当程序退出时记得你,取消注册.
IntentFilter filter = new IntentFilter();
filter.addAction(NetStatusBroadcast.NET_CHANGE_ACTION);
mBroadcast = new NetStatusBroadcast();
this.registerReceiver(mBroadcast,filter);
下面是我也的一个网络变化相应的工具,如果有什么地方些的不好或有错误请指出来,一起交流,进步.
工具下载地址:https://github.com/CNCFOX/NetStatus
思路:
先介绍几个类:
- NetType 是一个枚举,在这里存放这网络状态:
public enum NetType {
NO_NET, //没有网络
NET_WIFI, //wifi 网络
NET_3G_4G //移动网络 3G 4G
}
- NetTools 类,在该类中可以判断网络是否可用,获取当前网络状态.
先看一下代码(代码中有注释,不过多解释):要说明一下,在使用前,一定要在使用前调用init()方法设置Context.
public class NetTools {
/**
* 获取连接服务
* @param context :
* @return
*/
private static ConnectivityManager getConnectivityMannager(Context context){
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
private static Context sCtx;
/**
* 初始化 Context ,一般建议在 Application 中进行设置
* @param context
*/
public static void init(Context context){
if (sCtx != null) return;
if (context instanceof Activity){
sCtx = ((Activity) context).getApplication();
return;
}
if (context instanceof Service){
sCtx = ((Service) context).getApplication();
return;
}
sCtx = context.getApplicationContext();
}
/**
* 判断网络是否连接
* <br/> 在使用这个方法时,一定要先通过#NetTools init() 方法中进行Context 设置
* @return
*/
public static boolean isConnected(){
return isConnected(sCtx);
}
/**
* 判断网络是否连接
* @param context
* @return
*/
public static boolean isConnected(Context context){
if (context == null){
throw new RuntimeException(NetTools.class.getSimpleName() + " # Content is null");
}
init(context);
ConnectivityManager connectivityManager = getConnectivityMannager(sCtx);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
/**
* 获取网络状态
* <br/> 在使用这个方法时,一定要先通过#NetTools init() 方法中进行 Context 设置
* @return
* <br/> enum NetType
* <br/> #NO_NET : 没有网络
* <br/> NET_WIFI : wifi 网络
* <br/> NET_3G_4G : 移动网络 3G 4G
*/
public static NetType netType(){
return netType(sCtx);
}
/**
* 获取网络状态
* @return
* <br/> enum NetType
* <br/> #NO_NET : 没有网络
* <br/> NET_WIFI : wifi 网络
* <br/> NET_3G_4G : 移动网络 3G 4G
*/
public static NetType netType(Context context){
if (context == null){
throw new RuntimeException(NetTools.class.getSimpleName() + " # Content is null");
}
init(context);
ConnectivityManager connectivityManager = getConnectivityMannager(sCtx);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo == null) return NetType.NO_NET;
int type = networkInfo.getType();
if (type == ConnectivityManager.TYPE_MOBILE) return NetType.NET_3G_4G;
if (type == ConnectivityManager.TYPE_WIFI) return NetType.NET_WIFI;
return NetType.NO_NET;
}
}
- NetObserver 类,管理注册监听类.
public class NetObserver {
private static NetStatusReceiver sGlobalReceiver;
private static NetStatusReceiver sNetStatusReceiver;
/**
* 注册全局回调,全局网络状态改变时,每次都会回调,主要用于设置全局网络状态使用
* @param netStatusReceiver
*/
public static synchronized void registerlGlobalReceiver(NetStatusReceiver netStatusReceiver){
sGlobalReceiver = netStatusReceiver;
}
/**
* 获取全局回调
* @return
*/
public static NetStatusReceiver getGlobalReceiver(){
return sGlobalReceiver;
}
/**
* 取消注册的全局回调
*/
public static void unGlobalRegister(){
sGlobalReceiver = null;
}
/**
* 注册回调
* @param netStatusReceiver
*/
public static synchronized void register(NetStatusReceiver netStatusReceiver){
sNetStatusReceiver = netStatusReceiver;
}
/**
* 取消
*/
public static void unregister(){
sNetStatusReceiver = null;
}
public static NetStatusReceiver getNetStatusReceiver(){
return sNetStatusReceiver;
}
}
4.NetStatusReceiver 接口.
public interface NetStatusReceiver {
void netStatusChanged(NetType netType);
}
看完这几个类,可能已经知道大概的思路了,下面介绍一下我的思路.
在 AndroidManifest.xml 中添加注册网络状态改变监听广播:这里推荐使用动态注册方式,如果使用动态注册,在程序退出时不要忘记取消注册
- 静态注册
<receiver android:name=".netutils.NetStatusBroadcast">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
- 动态注册
IntentFilter filter = new IntentFilter();
filter.addAction(NetStatusBroadcast.NET_CHANGE_ACTION);
mBroadcast = new NetStatusBroadcast();
this.registerReceiver(mBroadcast,filter);
注意: 不要忘记添加权限:<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- ### 实现网络状态改变接收广播:
public class NetStatusBroadcast extends BroadcastReceiver {
private static final String TAG = "NetStatusBroadcast";
public static final String NET_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
/** 有些时候网络改变时会调用两次,使用这个变了记录上一次改变时的网络状态,如果和上一次相同,则不向下通知 */
private static NetType sNetTypeCache = null;
@Override
public void onReceive(Context context, Intent intent) {
NetTools.init(context);
Log.i(TAG,"Cache Net :" + sNetTypeCache );
if (NetTools.netType() == sNetTypeCache) return;
Log.i(TAG,"Changed net :" + NetTools.netType());
if (intent.getAction().equals(NET_CHANGE_ACTION)){
sNetTypeCache = NetTools.netType();
NetStatusReceiver receiver = NetObserver.getGlobalReceiver();
if (receiver != null) receiver.netStatusChanged(sNetTypeCache);
receiver = NetObserver.getNetStatusReceiver();
if (receiver != null) receiver.netStatusChanged(sNetTypeCache);
}
}
}
- ### 添加注册和取消注册:
建议在 onResume 中添加注册,在 onDestroy 中添加取消注册.
ublic class OtherActivity extends Activity {
private Button mBtnFinsh;
private NetStatusReceiver receiver = new NetStatusReceiver() {
@Override
public void netStatusChanged(NetType netType) {
Toast.makeText(OtherActivity.this,name + "OtherActivity page net type" + netType ,Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
mBtnFinsh = (Button) findViewById(R.id.btn_finsh);
}
@Override
protected void onResume() {
super.onResume();
NetObserver.register(receiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
NetObserver.unregister();
}
public void exitActivity(View view) {
finish();
}
}
详细内容请参考工程代码工具下载地址:https://github.com/CNCFOX/NetStatus