十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
用户手机当前网络可用:WIFI、2G/3G网络,用户打开与不打开网络,和是否可以用是两码事。可以使用指的是:用户打开网络了并且可以连上互联网进行上网。
成都创新互联服务项目包括猇亭网站建设、猇亭网站制作、猇亭网页制作以及猇亭网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,猇亭网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到猇亭省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
检测当前网络是否可用,代码如下:
/**
* 检测当的网络(WLAN、3G/2G)状态
* @param context Context
* @return true 表示网络可用
*/
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo info = connectivity.getActiveNetworkInfo();
if (info != null info.isConnected())
{
// 当前网络是连接的
if (info.getState() == NetworkInfo.State.CONNECTED)
{
// 当前所连接的网络可用
return true;
}
}
}
return false;
}
/**
* 检测当的网络(WLAN、3G/2G)状态
* @param context Context
* @return true 表示网络可用
*/
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo info = connectivity.getActiveNetworkInfo();
if (info != null info.isConnected())
{
// 当前网络是连接的
if (info.getState() == NetworkInfo.State.CONNECTED)
{
// 当前所连接的网络可用
return true;
}
}
}
return false;
}
在AndroidManifest.xml文件添加的权限:
uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/
uses-permission android:name="android.permission.INTERNET"/
uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/
uses-permission android:name="android.permission.INTERNET"/
我们做项目的时候,不可避免的要做网络状态的监听,一般我们都是抽取出一个工具类来实现,比如:
细致的你当然还会再写一个判断网络类型的方法,反手再来一个例:
然后就可以在相应的操作前进行判断网络的判断:
但是这样做也有些问题:
接下来就是本文的重点,如何通过 NetStatusBus 这个库来解决以上问题,让你的网络状态监听变得前所未有的简单粗暴。
到这里就已经结束了,你的所有网络操作已经都可以清晰优雅的在订阅方法中进行处理了,当然你也可以继续往下看。
订阅方法必须填写一个NetType参数,可以通过NetType的值来判断当前网络类型。
@NetSubscribe中 netType为可选值,可以设置订阅的类型,可选值类型如下:
NetType.AUTO
这是默认值,任何网络状态发生变化,该类型订阅者都会被回调。同时会传入NetType参数告知你当前的网络类型,示例如下:
只要当前是由 WIFI 改变引发的网络状态变化,该类型订阅者都会被回调。同时会传入NetType参数告知你当前的网络类型,示例如下:
只要当前是由移动网络改变引发的网络状态变化,该类型订阅者都会被回调。同时会传入NetType参数告知你当前的网络类型,示例如下:
NetType.NONE
只有当网络丢失时,该类型订阅者才会被回调。
有人会觉得,我用个库爽就行了管它的原理干什么?
你放心,我只是小小的描述一下实现方式。
原理简单来说,就是在全局初始化的时候就绑定对网络的变化监听。然后将进行注册的父类所有的订阅方法保存至集合中,这里涉及到一些方法的校验,最后在网络状态发生改变时利用 Java 反射机制遍历执行所有订阅方法。熟悉 EventBus 的小伙伴已经看出来了这里借鉴了一小部分 EventBus 的思想。
回到第一步,那么具体是如何绑定对网络状态变化的监听呢?
以前我们是通过注册广播来实现绑定网络变更的监听,在Android 7.0 以后,Google 基于性能和安全原因对广播进行了很多限制,比如监听网络变更的广播 android.net.conn.CONNECTIVITY_CHANGE 使用静态注册的方式则无法生效,而动态注册的方式虽然可以生效但毕竟不是最优解。
同样出于性能和安全,以及拥抱变化的角度,最终我们还是使用官方推荐的方式,利用 ConnectivityManager.NetworkCallback 来进行网络变化的监听,这是在Android 5.0即android api 21推出的API,目前Android 5.0以上的市场占有率在 85%以上,随着国内各大厂商正在积极的推进适配普及Android Q,这个比例还会进一步增大,所以个人人认为无需过于担心低版本适配。
使用的时候出现这个问题是由于少添加了权限。
Caused by: java.lang.SecurityException: ConnectivityService: Neither user 10513 nor current process has android.permission.ACCESS_NETWORK_STATE.
java.lang.RuntimeException: Unable to create application com.jiyun.wanandroid.WanApplication: java.lang.SecurityException: ConnectivityService: Neither user 10513 nor current process has android.permission.ACCESS_NETWORK_STATE.
加上这几个权限就好了:
附上原文地址:
在开发android应用时,涉及到要进行网络访问,时常需要进行网络状态的检查,以提供给用户必要的提醒。一般可以通过ConnectivityManager来完成该工作。
ConnectivityManager有四个主要任务:
1、监听手机网络状态(包括GPRS,WIFI, UMTS等)
2、手机状态发生改变时,发送广播
3、当一个网络连接失败时进行故障切换
4、为应用程序提供可以获取可用网络的高精度和粗糙的状态
当我们要在程序中监听网络状态时,只要一下几个步骤即可:
1、定义一个Receiver重载其中的onReceive函数,在其中完成所需要的功能,如根据WIFI和GPRS是否断开来改变空间的外观
复制代码 代码如下:
connectionReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectMgr = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo mobNetInfo = connectMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo wifiNetInfo = connectMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (!mobNetInfo.isConnected() !wifiNetInfo.isConnected()) {
Log.i(TAG, "unconnect");
// unconnect network
}else {
// connect network
}
}
};
2、在适当的地方注册Receiver,可以在程序中注册,在onCreate中调用如下函数即可:
复制代码 代码如下:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(connectionReceiver, intentFilter);
3、在适当时取消注册Receiver,可以在程序中取消,在onDestroye中调用如下函数即可:
复制代码 代码如下:
if (connectionReceiver != null) {
unregisterReceiver(connectionReceiver);
}
Scoket 判定是否连接网络不仅需要使用isClose方法进行判定,同时需要使用isConnected方法来判断Socket对象 是否连接成功。
1) isConnected方法所判断的并不是Socket对象的当前连接状态, 而是Socket对象是否曾经连接成功过,如果成功连接过,即使现在isClose返回true, isConnected仍然返回true。因此,要判断当前的Socket对象是否处于连接状态, 必须同时使用isClose和isConnected方法, 即只有当isClose返回false,isConnected返回true的时候Socket对象才处于连接状态。
1) 在大多数的时候可以直接使用Socket类或输入输出流的close方法关闭网络连接,但有时我们只希望关闭OutputStream或InputStream,而在关闭输入输出流的同时,并不关闭网络连接。这就需要用到Socket类的另外两个方法:shutdownInput和shutdownOutput,这两个方法只关闭相应的输入、输出流,而它们并没有同时关闭网络连接的功能。和isClosed、isConnected方法一样,Socket类也提供了两个方法来判断Socket对象的输入、输出流是否被关闭,这两个方法是isInputShutdown()和isOutputShutdown()。 shutdownInput和shutdownOutput并不影响Socket对象的状态。
获取android系统的连接服务可判断网络连接状态,代码如下
public class NetUtils{
public static boolean isNetworkConnected(Context context){
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] infos = cm.getAllNetworkInfo();
for(NetworkInfo info:infos){
if(info.isAvailable()info.isConnected()){
return true;
}
}
return false;
}
}
NetworkInfo的isAvailable()和isConnected()有以下5种状态:
在WLAN设置界面
1,显示连接已保存,但标题栏没有,即没有实质连接上:isConnected()==false,isAvailable()=true
2,显示连接已保存,标题栏也有已连接上的图标:isConnected()==true,isAvailable()=true
3,选择不保存后:isConnected()==false,isAvailable()=true
4,选择连接,在正在获取IP地址时:isConnected()==false,isAvailable()=false
5,连接上后:isConnected()==true,isAvailable()=true
实现步骤:
下面解决办法来自于android学习手册,android学习手册包含9个章节,108个例子,源码文档随便看,例子都是可交互,可运行,源码采用android studio目录结构,高亮显示代码,文档都采用文档结构图显示,可以快速定位。360手机助手中下载。排到第三个。
1、获取ConnectivityManager对象
Context context = activity.getApplicationContext();
// 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
2、获取NetworkInfo对象
// 获取NetworkInfo对象
NetworkInfo[] networkInfo = connectivityManager.getAllNetworkInfo();
3、判断当前网络状态是否为连接状态
if (networkInfo[i].getState() == NetworkInfo.State.CONNECTED)
{
return true;
}
4、在AndroidManifest.xml中添加访问当前网络状态权限
uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/uses-permission
代码如下:
public class ClassTestDemoActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (isNetworkAvailable(ClassTestDemoActivity.this))
{
Toast.makeText(getApplicationContext(), "当前有可用网络!", Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getApplicationContext(), "当前没有可用网络!", Toast.LENGTH_LONG).show();
}
}
/**
* 检查当前网络是否可用
*
* @param context
* @return
*/
public boolean isNetworkAvailable(Activity activity)
{
Context context = activity.getApplicationContext();
// 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null)
{
return false;
}
else
{
// 获取NetworkInfo对象
NetworkInfo[] networkInfo = connectivityManager.getAllNetworkInfo();
if (networkInfo != null networkInfo.length 0)
{
for (int i = 0; i networkInfo.length; i++)
{
System.out.println(i + "===状态===" + networkInfo[i].getState());
System.out.println(i + "===类型===" + networkInfo[i].getTypeName());
// 判断当前网络状态是否为连接状态
if (networkInfo[i].getState() == NetworkInfo.State.CONNECTED)
{
return true;
}
}
}
}
return false;
}
}