[Android WIFI开采]

来源:http://www.sh-fengwen.com 作者:鲜果干果 人气:89 发布时间:2019-09-07
摘要:在说WiFi之前,先来说说网络连接处理。 在Android开发过程中,对于一个需要连接网络的Android设备,对设备的网络状态检测是很有必要的!有很多的App都需要连接网络。判断设备是否已经

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

前言

在Android应用层的开发中,使用到wifi相关知识点的地方并不多,所以之前对wifi开发并不熟悉,最近接到的两个硬件项目都有用到wifi并且知识点越来越深入,所以有必要记一下笔记,做一些注释。

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

基本使用

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

1.权限

Android中要使用系统功能一般都要申请权限,在6.0上可能还要手动申请权限,这里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"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> // 需要系统权限 [定位权限]

其中在6.0以上设备,定位权限需要主动申请,并且如果要获取扫描wifi列表需要打开系统的定位开关。

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

2. WiFi相关API

图片 1

WIFI相关API

ScanResult类用于存放wifi扫描结果信息,包含ssid(wifi名称), bssid(网络接入点地址),capabilities(加密类型),frequency(传输频率),level(信号强度)等。这里的解释并不太标准,但是对应功能很形象,如果你要了解更多,可以去具体的查阅资料。

WifiConfiguration类用于存放wifi的配置信息。包括wifi的密码,加密类型,网络id(用于连接wifi)等。他的几个子类分别对应秘钥加密方式,安全协议等,这些在设置wifi配置的时候会被用到

wifiinfo类用来描述wifi属性和连接状态。暴露了一些方法给开发者调用。getBSSID(), getMacAddress(), getIpAddress(),getSSID()等

WifiManager类是framework层暴露的api,用来管理wifi。通过调用 Context.getSystemService(Context.WIFI_SERVICE)可以得到类的实例。通过他可以得到:1.已经配置的网络列表。2.当前连接的wifi。3.扫描到的wifi。4.以及一些常量表示广播的意图等

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

3. wifi状态及开关

/**
 * 判断wifi是否打开
 * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>}</p>
 *
 * @return {@code true}: 是<br>{@code false}: 否
 */
public static boolean getWifiEnabled() {
    @SuppressLint("WifiManagerLeak")
    WifiManager wifiManager = (WifiManager) Utils.getApp().getSystemService(Context.WIFI_SERVICE);
    return wifiManager.isWifiEnabled();
}

/**
 * 打开或关闭wifi
 * <p>需添加权限 {@code <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>}</p>
 *
 * @param enabled {@code true}: 打开<br>{@code false}: 关闭
 */
public static void setWifiEnabled(final boolean enabled) {
    @SuppressLint("WifiManagerLeak")
    WifiManager wifiManager = (WifiManager) Utils.getApp().getSystemService(Context.WIFI_SERVICE);
    if (enabled) {
        if (!wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(true);
        }
    } else {
        if (wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(false);
        }
    }
}

涉及的常用类

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

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

获取ConnectivityManager

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

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

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

主要方法:

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

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

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类主要提供了一系列用于访问与手机通讯相关的状态和信息的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网络,返回MEIDIMEI是International Mobile Equipment Identity 的简称IMEI由15位数字组成的”电子串号”,它与每台手机一一对应,而且该码是全世界唯一的,其组成为:
    1. 前6位数是”型号核准号码”,一般代表机型
    2. 接着的2位数是”最后装配号”,一般代表产地
    3. 之后的6位数是”串号”,一般代表生产顺序号
    4. 最后1位数通常是”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是国际移动用户识别码的简称(International Mobile Subscriber Identity)IMSI共有15位,其结构如下:MCC+MNC+MINMCC:Mobile Country Code,移动国家码,共3位,中国为460;MNC:Mobile NetworkCode,移动网络码,共2位在中国,移动的代码为电00和02,联通的代码为01,电信的代码为03合起来就是(也是Android手机中APN配置文件中的代码):中国移动:46000 46002中国联通:46001中国电信:46003举例,一个典型的IMSI号码为460030912121001
  • getNetworkOperatorName() 移动网络运营商的名字
  • getNetworkType() 移动网络类型int NETWORK_TYPE_CDMA 网络类型为CDMAint NETWORK_TYPE_EDGE 网络类型为EDGEint NETWORK_TYPE_EVDO_0 网络类型为EVDO0int NETWORK_TYPE_EVDO_A 网络类型为EVDOAint NETWORK_TYPE_GPRS 网络类型为GPRSint NETWORK_TYPE_HSDPA 网络类型为HSDPAint NETWORK_TYPE_HSPA 网络类型为HSPAint NETWORK_TYPE_HSUPA 网络类型为HSUPAint 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卡运营商国家代码和运营商网络代码)
  • getSimSerialNumber() SIM卡的序列号
  • getSubscriberId() 用户唯一标识,比如GSM网络的IMSI编号
  • getVoiceMailAlphaTag() 语音信箱号码关联的字母标识
  • getVoiceMailNumber() 语音邮件号码
  • isNetworkRoaming() 手机是否处于漫游状态

4. 扫描wifi

 /**
 *
 * 获取WIFI列表
 * <p>需要权限{@code <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>}</p>
 * <p>注意Android6.0上需要主动申请定位权限,并且打开定位开关</p>
 *
 * @param context 上下文
 * @return wifi列表
 */
public static List<ScanResult> getWifiList(Context context) {
    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    List<ScanResult> scanResults = wm.getScanResults();

    Collections.sort(scanResults, new Comparator<ScanResult>() {
        @Override
        public int compare(ScanResult scanResult1, ScanResult scanResult2) {
            return scanResult2.level - scanResult1.level;
        }
    });
    return scanResultsCopy;
}

 /**
 * 获取当前链接的WiFi信息
 *
 * @param context 上下文
 * @return 当前wifi数据
 */
public static WifiInfo getCurrentWifi (Context context) {
    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    return wm.getConnectionInfo();
}


public static String getWifiEncryptTypeStr (String capabilitie) {
    if (TextUtils.isEmpty(capabilitie)) return null;

    String encryptType;

    if (capabilitie.contains("WPA") && capabilitie.contains("WPA2")) {
        encryptType = "WPA/WPA2 PSK";
    } else if (capabilitie.contains("WPA2")) {
        encryptType = "WPA2 PSK";
    } else if (capabilitie.contains("WPA")) {
        encryptType = "WPA PSK";
    } else if (capabilitie.contains("WEP")) {
        encryptType = "WEP";
    } else {
        encryptType = "NONE";
    }

    return encryptType;
}

/**
 * wifi加密方式有5种
 * 0 - WPA/WPA2 PSK
 * 1 - WPA2 PSK
 * 2 - WPA PSK
 * 3 - WEP
 * 4 - NONE
 * @param capabilitie
 * @return
 */
public static int getWifiEncryptType (String capabilitie) {
    if (TextUtils.isEmpty(capabilitie)) return -1;

    int encryptType;

    if (capabilitie.contains("WPA") && capabilitie.contains("WPA2")) {
        encryptType = 0;
    } else if (capabilitie.contains("WPA2")) {
        encryptType = 1;
    } else if (capabilitie.contains("WPA")) {
        encryptType = 2;
    } else if (capabilitie.contains("WEP")) {
        encryptType = 3;
    } else {
        encryptType = 4;
    }

    return encryptType;
}

网络连接处理方式

贴代码:

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; 

不同Rom可能不同。

下面来说WiFi

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

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

图片 2

<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

5. 连接wifi

 /**
 * @des 连接已经保存过配置的wifi
 * @param context
 * @param ssid
 */
public static void connectWifi (Context context, String ssid) {

    Log.d(TAG, "connectWifi: 去连接wifi: " + ssid);

    if (!getWifiEnabled()) return;

    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    WifiConfiguration wc = new WifiConfiguration();

    wc.SSID = """ + ssid + """;

    WifiConfiguration configuration = getWifiConfig(context, ssid);
    if (configuration != null) {
        wm.enableNetwork(configuration.networkId, true);
    }

}

/**
 * @des 连接没有配置过的wifi
 * @param context
 * @param ssid
 * @param password
 * @param encryptType
 */
public static void connectWifi (Context context, String ssid, String password, int encryptType) {

    Log.d(TAG, "connectWifi: 去连接wifi: " + ssid);

    if (!getWifiEnabled()) return;

    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    WifiConfiguration wc = new WifiConfiguration();
    wc.allowedAuthAlgorithms.clear();
    wc.allowedGroupCiphers.clear();
    wc.allowedKeyManagement.clear();
    wc.allowedPairwiseCiphers.clear();
    wc.allowedProtocols.clear();

    wc.SSID = """ + ssid + """;

    WifiConfiguration configuration = getWifiConfig(context, ssid);
    if (configuration != null) {
        wm.removeNetwork(configuration.networkId);
    }

    switch (encryptType) {
        case 4://不加密
            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            break;

        case 3://wep加密
            wc.hiddenSSID = true;
            wc.wepKeys[0] = """ + password +""";
            wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);

            break;
        case 0: //wpa/wap2加密
        case 1: //wpa2加密
        case 2: //wpa加密

            wc.preSharedKey = """ + password + """;
            wc.hiddenSSID = true;
            wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            wc.status = WifiConfiguration.Status.ENABLED;
            break;
    }

    int network = wm.addNetwork(wc);
    wm.enableNetwork(network, true);
}

public static void disConnectWifi (Context context, int networkId) {
    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    wm.disableNetwork(networkId);
    wm.disconnect();
}

WifiManager用来管理我们的wifi连接

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

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

if(mWifiManager.isWifiEnabled{ mWifiManager.setWifiEnabled; } 

mWifiManager.getWifiState()

WIFI网卡状态

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

6. 获取和清除WIFI配置

/**
 * @des 清除wifi配置信息
 * @param context
 * @param ssid
 */
public static void clearWifiInfo(Context context, String ssid) {

    Log.d(TAG, "clearWifiInfo: 清除WIFI配置信息: " + ssid);

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

    String newSSID = """ + ssid + """;

    if (!(ssid.startsWith(""") && ssid.endsWith("""))) {
        newSSID = """ + ssid + """;
    } else {
        newSSID = ssid;
    }

    WifiConfiguration configuration = getWifiConfig(context, newSSID);
    configuration.allowedAuthAlgorithms.clear();
    configuration.allowedGroupCiphers.clear();
    configuration.allowedKeyManagement.clear();
    configuration.allowedPairwiseCiphers.clear();
    configuration.allowedProtocols.clear();

    if (configuration != null) {

        wm.removeNetwork(configuration.networkId);
        wm.saveConfiguration();
    }
}

public static WifiConfiguration getWifiConfig (Context context, String ssid) {

    Log.d(TAG, "getWifiConfig: 获取wifi配置信息: " + ssid);

    if (TextUtils.isEmpty(ssid)) return null;

    String newSSID;

    if (!(ssid.startsWith(""") && ssid.endsWith("""))) {
        newSSID = """ + ssid + """;
    } else {
        newSSID = ssid;
    }

    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    List<WifiConfiguration> configuredNetworks = wm.getConfiguredNetworks();

    for (WifiConfiguration configuration : configuredNetworks) {
        if (newSSID.equalsIgnoreCase(configuration.SSID)) {
            return configuration;
        }
    }

    return null;
}

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() 返回具体客户端状态的信息

高级用法

本文由美高梅游戏平台网站发布于鲜果干果,转载请注明出处:[Android WIFI开采]

关键词:

最火资讯