Android开发之WIFI与网络连接处理

网络连接处理

在说WiFi之前,先来说说网络连接处理。
在Android开发过程中,对于一个需要连接网络的Android设备,对设备的网络状态检测是很有必要的!有很多的App都需要连接网络。判断设备是否已经连接网络,并且在连接网络的状态下判断是wifi无线连接还是GPRS手机网络连接,这样就可以在不同的网络连接下去调用不同的方法,处理不同的事情。

现在app大多都需要从网络上获得数据。所以访问网络是在所难免。但是在访问网络之前,我们应该先做一下网络的状态判断。其实在访问网络之前我们要做一些状态判断,对应一些状态判断来做处理,并不是直接使用Http访问网络即可。很多人在开发就经常把网络这块直接跳过,直接访问网络,一旦断网,各种体验效果不好,不是说app没法用,只是体验效果差。还有,就是我们可能为用户考虑,因为现在一般连网是wifi和手机流量,都知道后者收费是比较高的。假如我们的app加载的图片或者有大的数据下载操作,可是用户的本意是要是在流量下的话就不要操作这些很费流量的的操作,这样就必须要我们做一些连网状态的判断。网络是否连接良好,连接的wifi还是流量,断网或者网络改变了的时候怎么做,这都是一些细节,但是要注意处理。

查看当前网络状态需要的权限:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

允许查看当前网络状态,比如是3G还是WIFI上网。

连接管理

涉及的常用类

ConnectivityManager

翻译成中文即:网络连接管理者
主要作用:

  • 监听手机网络状态(包括GPRS,WIFI, UMTS等)
  • 手机状态发生改变时,发送广播
  • 当一个网络连接失败时进行故障切换
  • 为应用程序提供可以获取可用网络的高精度和粗糙的状态

获取ConnectivityManager

ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 

NetworkInfo

翻译成中文即:网络的状态信息
获取NetworkInfo
通过ConnectivityManager获取

ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

主要方法:

  • getDetailedState():获取详细状态。
  • isAvailable():判断该网络是否可用,是否可以寻找到网络
  • isConnected():判断是否已经连接
  • isConnectedOrConnecting():判断是否已经连接或正在连接。
  • getState() 获取连接状态
  • getExtraInfo():获取附加信息。
  • getType():获取网络类型(一般为移动(0)或Wi-Fi(1))。
  • getTypeName():获取网络类型名称(一般取值“WIFI”或“MOBILE”)。
  • getReason():获取连接失败的原因。
  • isFailover():判断是否连接失败。
  • isRoaming():判断是否漫游

注意:
1.当用wifi上的时候
getType是WIFI
getExtraInfo是空的

2.当用手机上的时候
getType是MOBILE

3.用移动CMNET方式
getExtraInfo的值是cmnet

4.用移动CMWAP方式
getExtraInfo的值是cmwap,但是不在代理的情况下访问普通的网站访问不了

5.用联通3gwap方式
getExtraInfo的值是3gwap

6.用联通3gnet方式
getExtraInfo的值是3gnet

7.用联通uniwap方式
getExtraInfo的值是uniwap

8.用联通uninet方式
getExtraInfo的值是uninet

TelephonyManager

TelephonyManager类主要提供了一系列用于访问与手机通讯相关的状态和信息的get方法。其中包括手机SIM的状态和信息、电信网络的状态及手机用户的信息。在应用程序中可以使用这些get方法获取相关数据。
需要添加权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

第一步,也要像ConnectivityManager一样获取管理器:

TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

常用方法:

  • getCallState()
    CALL_STATE_IDLE 无任何状态时
    CALL_STATE_OFFHOOK 接起电话时
    CALL_STATE_RINGING 电话进来时
  • getDataActivity()
    DATA_ACTIVITY_IN 数据连接状态:活动,正在接受数据
    DATA_ACTIVITY_OUT 数据连接状态:活动,正在发送数据
    DATA_ACTIVITY_INOUT 数据连接状态:活动,正在接受和发送数据
    DATA_ACTIVITY_NONE 数据连接状态:活动,但无数据发送和接受
  • getDataState()
    DATA_CONNECTED 数据连接状态:已连接
    DATA_CONNECTING 数据连接状态:正在连接
    DATA_DISCONNECTED 数据连接状态:断开
    DATA_SUSPENDED 数据连接状态:暂停
  • getDeviceSoftwareVersion() 移动终端的软件版本,例如:GSM手机的IMEI/SV码
  • getLine1Number() 手机号码,对于GSM网络来说即MSISDN(不一定能拿到)
  • getNetworkCountryIso() ISO标准的国家码,即国际长途区号
  • getDeviceId() GSM网络,返回IMEI;如果是CDMA网络,返回MEID
    IMEI是International Mobile Equipment Identity (国际移动设备标识)的简称
    IMEI由15位数字组成的”电子串号”,它与每台手机一一对应,而且该码是全世界唯一的,其组成为:
    1. 前6位数(TAC)是”型号核准号码”,一般代表机型
    2. 接着的2位数(FAC)是”最后装配号”,一般代表产地
    3. 之后的6位数(SNR)是”串号”,一般代表生产顺序号
    4. 最后1位数(SP)通常是”0″,为检验码,目前暂备用
      MEID 移动设备识别码(Mobile Equipment Identifier)是CDMA手机的身份识别码,也是每台CDMA手机或通讯平板唯一的识别码。
      MEID由14个十六进制字符标识,第15位为校验位,不参与空中传输。
      RR:范围A0-FF,由官方分配
      XXXXXX:范围 000000-FFFFFF,由官方分配
      ZZZZZZ:范围 000000-FFFFFF,厂商分配给每台终端的流水号
      C/CD:0-F,校验码
  • getNetworkOperator() MCC+MNC代码 (SIM卡运营商国家代码和运营商网络代码)(IMSI)
    IMSI是国际移动用户识别码的简称(International Mobile Subscriber Identity)
    IMSI共有15位,其结构如下:
    MCC+MNC+MIN
    MCC:Mobile Country Code,移动国家码,共3位,中国为460;
    MNC:Mobile NetworkCode,移动网络码,共2位
    在中国,移动的代码为电00和02,联通的代码为01,电信的代码为03
    合起来就是(也是Android手机中APN配置文件中的代码):
    中国移动:46000 46002
    中国联通:46001
    中国电信:46003
    举例,一个典型的IMSI号码为460030912121001
  • getNetworkOperatorName() 移动网络运营商的名字(SPN)
  • getNetworkType() 移动网络类型
    int NETWORK_TYPE_CDMA 网络类型为CDMA
    int NETWORK_TYPE_EDGE 网络类型为EDGE
    int NETWORK_TYPE_EVDO_0 网络类型为EVDO0
    int NETWORK_TYPE_EVDO_A 网络类型为EVDOA
    int NETWORK_TYPE_GPRS 网络类型为GPRS
    int NETWORK_TYPE_HSDPA 网络类型为HSDPA
    int NETWORK_TYPE_HSPA 网络类型为HSPA
    int NETWORK_TYPE_HSUPA 网络类型为HSUPA
    int NETWORK_TYPE_UMTS 网络类型为UMTS
    在中国,联通的3G为UMTS或HSDPA,移动和联通的2G为GPRS或EGDE,电信的2G为CDMA,电信的3G为EVDO
  • getPhoneType() 手机制式类型
    int PHONE_TYPE_CDMA 手机制式为CDMA,电信
    int PHONE_TYPE_GSM 手机制式为GSM,移动和联通
    int PHONE_TYPE_NONE 手机制式未知
  • getSimState()
    int SIM_STATE_ABSENT SIM卡未找到
    int SIM_STATE_NETWORK_LOCKED SIM卡网络被锁定,需要Network PIN解锁
    int SIM_STATE_PIN_REQUIRED SIM卡PIN被锁定,需要User PIN解锁
    int SIM_STATE_PUK_REQUIRED SIM卡PUK被锁定,需要User PUK解锁
    int SIM_STATE_READY SIM卡可用
    int SIM_STATE_UNKNOWN SIM卡未知
  • getSimCountryIso() SIM卡提供商的国家代码
  • getSimOperator(),getSimOperatorName() MCC+MNC代码 (SIM卡运营商国家代码和运营商网络代码)(IMSI)
  • getSimSerialNumber() SIM卡的序列号(IMEI)
  • getSubscriberId() 用户唯一标识,比如GSM网络的IMSI编号
  • getVoiceMailAlphaTag() 语音信箱号码关联的字母标识
  • getVoiceMailNumber() 语音邮件号码
  • isNetworkRoaming() 手机是否处于漫游状态

网络连接处理方式

获取单个网络是否连接

贴代码:

ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
//WiFi是否连接
NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
boolean isWifiConn = networkInfo.isConnected();
//手机网络是否连接
networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
boolean isMobileConn = networkInfo.isConnected();

获取网络是否连接

ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

通过广播获取连接状态改变(常用方式)

  • 注册广播,监听ConnectivityManager.CONNECTIVITY_ACTION频道
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
context.registerReceiver(mReceiver, filter);
  • 网络状态广播
BroadcastReceiver mReceiver = new BroadcastReceiver() {  
          
    @Override  
    public void onReceive(Context context, Intent intent) {  
  
        if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {  
            Log.i(TAG, "netWork has lost");  
        }  
      
        NetworkInfo tmpInfo = (NetworkInfo) 
            intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);  
        Log.i(TAG, tmpInfo.toString() + " {isConnected = " + tmpInfo.isConnected() + "}");  
    }  
};  
  • 清单文件注册(Demo写内部类了)
<receiver android:name=".ConnectionReceiver" >  
    <intent-filter>  
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />  
    </intent-filter>  
</receiver> 

无网络连接处理

提示无网络,或跳转到网络设置界面:

/** 
* 判断手机系统的版本!如果API大于10 就是3.0+ 
* 因为3.0以上的版本的设置和3.0以下的设置不一样,调用的方法不同 
*/  
Intent intent ;  
if (Build.VERSION.SDK_INT > 10) {  
   intent = new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS);  
} else {  
   intent = new Intent();  
   ComponentName component = new ComponentName("com.android.settings","com.android.settings.WirelessSettings");  
   intent.setComponent(component);  
   intent.setAction("android.intent.action.VIEW");  
}  
startActivity(intent);  

不同Rom可能不同。

下面来说WiFi

WiFi

WIFI是一种无线联网技术,常见的是使用无线路由器,在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网。如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为“热点”。

首先,要操作WiFi,先要加入权限

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

Android中对于Wifi操作本身提供了一些有用的包android.net.wifi

WiFi常用相关类

WifiManager用来管理我们的wifi连接

取得WifiManager对象

WifiManager mWifiManager=(WifiManager) context.getSystemService(Context.WIFI_SERVICE);  

打开wifi

if(!mWifiManager.isWifiEnabled())
{  
     mWifiManager.setWifiEnabled(true);  
 }  

关闭wifi

if(mWifiManager.isWifiEnabled())
{  
   mWifiManager.setWifiEnabled(false);  
} 

检查当前wifi状态

mWifiManager.getWifiState()

WIFI网卡状态

  • WifiManager.WIFI_STATE_DISABLING : WIFI网卡正在关闭(0)
  • WifiManager.WIFI_STATE_DISABLED : WIFI网卡不可用(1)
  • WifiManager.WIFI_STATE_ENABLING : WIFI网正在打开(2) (WIFI启动需要一段时间)
  • WifiManager.WIFI_STATE_ENABLED : WIFI网卡可用(3)
  • WifiManager.WIFI_STATE_UNKNOWN : 未知网卡状态

WifiInfo

wifi无线连接的信息,包括接入点,网络连接状态,隐藏的接入点,IP地址,连接速度,MAC地址,网络ID,信号强度等信息

WifiInfo mWifiInfo=mWifiManager.getConnectionInfo();  
  • getBSSID() 获取BSSID,在手机WIFI中,就是MAC地址
  • getSSID() 获取SSID
  • getDetailedStateOf() 获取客户端的连通性
  • getHiddenSSID() 获得SSID是否被隐藏
  • getIpAddress() 获取IP地址
  • getLinkSpeed() 获得连接的速度
  • getMacAddress() 获得Mac地址
  • getRssi() 获得802.11n网络的信号
  • getSupplicanState() 返回具体客户端状态的信息

ScanResult

主要用来描述已经检测出的接入点,包括接入点的地址,接入点的名称,
身份认证,频率,信号强度等信息。

开始扫描

mWifiManager.startScan()

得到扫描结果

List<ScanResult> mWifiList=mWifiManager.getScanResults();

WifiConfiguration

Wifi网络的配置,包括安全设置等。

得到配置好的网络连接

List<WifiConfiguration> mWifiConfigurations=mWifiManager.getConfiguredNetworks()

连接配置好指定ID的网络

mWifiManager.enableNetwork(mWifiConfigurations.get(index).networkId, true)

处理网络

动态处理WiFi网络

//添加一个网络并连接  
public void addNetWork(WifiConfiguration configuration){  
    int wcgId=mWifiManager.addNetwork(configuration);  
    mWifiManager.enableNetwork(wcgId, true);  
}  
//断开指定ID的网络  
public void disConnectionWifi(int netId){  
    mWifiManager.disableNetwork(netId);  
    mWifiManager.disconnect();  
}  

连接到对应WiFi网络

创建WifiConfiguration配置对象

String ssid = "Rair";
String pwd = "88888888";
WifiConfiguration localWifiConfiguration = new WifiConfiguration();
//公认的IEEE 802.11验证算法。
localWifiConfiguration.allowedAuthAlgorithms.clear();
localWifiConfiguration.allowedAuthAlgorithms.set(0);
//公认的的公共组密码。
localWifiConfiguration.allowedGroupCiphers.clear();
localWifiConfiguration.allowedGroupCiphers.set(2);
//公认的密钥管理方案。
localWifiConfiguration.allowedKeyManagement.clear();
localWifiConfiguration.allowedKeyManagement.set(1);
//密码为WPA。
localWifiConfiguration.allowedPairwiseCiphers.clear();
localWifiConfiguration.allowedPairwiseCiphers.set(1);
localWifiConfiguration.allowedPairwiseCiphers.set(2);
//公认的安全协议。
localWifiConfiguration.allowedProtocols.clear();

localWifiConfiguration.SSID = ("\"" + ssid + "\"");
localWifiConfiguration.preSharedKey = ("\"" + pwd + "\"");
//不广播其SSID的网络
localWifiConfiguration.hiddenSSID = true;

WifiConfiguration对应的配置值可到文档中查看,不知道怎么翻译描述。O(∩_∩)O~

添加WIFI网络

wcnetworkid = mWifiManager.addNetwork(localWifiConfiguration);

使WIFI网络有效

mWifiManager.enableNetwork(wcnetworkid,true);

锁定网络

手机屏幕关闭之后,并且其他的应用程序没有在使用wifi的时候,系统大概在两分钟之后,会关闭wifi,使得wifi处于睡眠状态,有利于电源能量的节省和延长电池寿命。

android为wifi提供了一种叫WifiLock的锁,能够阻止wifi进入睡眠状态,使wifi一直处于活跃状态。这种锁,在下载一个较大的文件的时候,比较适合使用。

添加权限

<uses-permission android:name="android.permission.WAKE_LOCK"/>

创建wifiLock

方式1:

 // lockName为锁的名称
 WifiLock wifiLock = wifiManager.createWifiLock(lockName);  

方式2:

wifiLock = wifiManager.createWifiLock(lockType, lockName);  

lockType可以取以下值:

  • WIFI_MODE_FULL == 1 //扫描,自动的尝试去连接一个曾经配置过的热点
  • WIFI_MODE_SCAN_ONLY == 2 //只剩下扫描
  • WIFI_MODE_FULL_HIGH_PERF = 3 //在第一种模式的基础上,保持最佳性能

wifi添加锁

wifiLock.acquire();  

wifi释放锁

//判断wifi是否被lock锁持用
if (wifiLock.isHeld())  
{  
    // 释放锁
    wifiLock.release();  
}  

一般到了这个时候就该给个Demo了

ConnectivityManagerDemo:连接管理的Demo,里面带一个NetworkConnUtil(网络连接帮助类),Demo都是以log形式显示结果。懒得写界面啦 (*)4

WifiDemo: 里面带一个WifiUtil(Wifi连接帮助类)


Demo已上传:RairDemo
GitHub:https://github.com/Rairmmd/android-demo
Coding:https://coding.net/u/Rair/p/RairDemo/git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容