Android—WIFI开发流程

本文介绍了Android平台上进行WIFI开发的基本流程,包括添加权限、获取WiFiManager、手动扫描和监听WiFi列表、设置连接、状态监听,以及相关辅助方法如判断5G网络和热点状态。特别提到在Android 6.0后修改其他应用WiFi设置的限制,并探讨了可能的解决方案。

1.添加权限

    <!-- 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"/>

2.获取wifi列表

(1) 获取wifiManager

wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);

(2)注册wifi扫描广播

        myWifiScanReceiver=new MyWifiScanReceiver();
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        mContext.registerReceiver(myWifiScanReceiver,intentFilter);

    private class MyWifiScanReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            ArrayList<ScanResult> list;                   //存放周围wifi热点对象的列表
            list = (ArrayList<ScanResult>) wifiManager.getScanResults();
            ArrayList<ScanResult> list_new = new ArrayList<>();
            for(ScanResult result:list){
                list_new.add(result);
            }
            list_new=sortByLevel(list_new);
            wifiListInter.getWifiList(list_new);

            try {
                mContext.unregisterReceiver(myWifiScanReceiver);
            }catch (Exception e){

            }

        }
    }

此处的wifi列表,是自己手动扫描,然后监听扫描结果来获取的,比较最新的列表,当然,你也可以直接调用WifiManager的getScanResults()方法直接获取上次扫描到的wifi列表信息。


(3)通过wifiManager开启扫描

        wifiManager.startScan();

3.将获取到的wifi列表,按照强度由高到低排序

这里的等级可以根据自己的需求设置等级数

    private ArrayList<ScanResult> sortByLevel(ArrayList<ScanResult> list) {
        Collections.sort(list, new Comparator<ScanResult>() {
            @Override
            public int compare(ScanResult scanResult, ScanResult t1) {
                int i =  wifiManager.calculateSignalLevel(t1.level,4)- wifiManager.calculateSignalLevel(scanResult.level,4);
                return i;
            }
        });
        return list;
    }

4.获取wifi类别
     public static final int WIFICIPHER_NOPASS = 0;
    public static final int WIFICIPHER_WEP = 1;
    public static final int WIFICIPHER_PSK = 2;
    public static final int WIFICIPHER_EAP = 3;
    public static final int WIFICIPHER_WAPI_PSK = 4;
    public static final int WIFICIPHER_WAPI_CERT = 5;
   public static int getSecurityType(ScanResult result) {
        if (result.capabilities.contains("WAPI-PSK")) {
            /*  WAPI_PSK */
            return WIFICIPHER_WAPI_PSK;
        } else if (result.capabilities.contains("WAPI-CERT")) {
            /* WAPI_CERT */
            return WIFICIPHER_WAPI_CERT;
        } else if (result.capabilities.contains("WEP")) {
            return WIFICIPHER_WEP;
        } else if (result.capabilities.contains("PSK")) {
            return WIFICIPHER_PSK;
        } else if (result.capabilities.contains("EAP")) {
            return WIFICIPHER_EAP;
        }
        return WIFICIPHER_NOPASS;
    }

5.连接wifi

    public static void connectingWifi(Context context,String SSID, String password, int type){
        mWifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);        //获得系统wifi服务
        mWifiManager.setWifiEnabled(true);

        mWifiManager.disconnect();
        WifiList wifiList = new WifiList(context);
        ArrayList<ScanResult> wifi_list =  wifiList.getWifiList();
        for(ScanResult result:wifi_list){
            Log.e(TAG,"result:"+result.SSID+"");
            if(result.SSID.equals(SSID)){
                type = getSecurityType(result);
                Log.e(TAG,"result:"+type+"");
            }
        }

        //createWifiConfig主要用于构建一个WifiConfiguration,代码中的例子主要用于连接不需要密码的Wifi
        //WifiManager的addNetwork接口,传入WifiConfiguration后,得到对应的NetworkId
        Log.e(TAG, "SSID: " + SSID+"|||password:"+password+"|||type:"+type);
        final WifiConfiguration wifiConfig =getWifiConfiguration(mWifiManager,SSID,password, type);
        Log.e(TAG, "wifiConfig: " + wifiConfig);
        int netId = mWifiManager.addNetwork(wifiConfig);
        Log.e(TAG, "netId: " + netId);
        //WifiManager的enableNetwork接口,就可以连接到netId对应的wifi了
        //其中boolean参数,主要用于指定是否需要断开其它Wifi网络
        boolean enable = mWifiManager.enableNetwork(netId, true);
        Log.e(TAG, "enable: " + enable);
        is_Success = enable;
        //可选操作,让Wifi重新连接最近使用过的接入点
        //如果上文的enableNetwork成功,那么reconnect同样连接netId对应的网络
        //若失败,则连接之前成功过的网络
        if(!enable){
            boolean reconnect = mWifiManager.reconnect();
            Log.e(TAG, "reconnect: " + reconnect);
        }
    }



6.获取所连接wifi的链接信息wifiConfiguration

    public static WifiConfiguration getWifiConfiguration(WifiManager wifiManager, String ssid, String password, int type) {
        List<WifiConfiguration> wifiConfigList = wifiManager.getConfiguredNetworks();
        if (wifiConfigList != null) {
            for (WifiConfiguration wifiConfig : wifiConfigList) {
                String new_SSID = null;
                Log.e("new_SSID","SSID"+wifiConfig.SSID);
                if(wifiConfig.SSID!=null&&wifiConfig.SSID.length()>3){
                    new_SSID= wifiConfig.SSID.substring(1,wifiConfig.SSID.length()-1);
                }
                Log.e("new_SSID","new_SSID"+new_SSID);
                Log.e("new_SSID","ssid"+ssid);
                if (new_SSID!=null&&new_SSID.trim().equals(ssid.trim())) {
                    Log.e("removeNetwork","removeNetwork"+wifiConfig.SSID+":::"+wifiConfig.networkId);
                    boolean isSuccess = wifiManager.removeNetwork(wifiConfig.networkId);
                    Log.e("removeNetwork","isSuccess:"+isSuccess);
                    wifiManager.saveConfiguration();
                    break;
                }
            }
        }
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.SSID = "\"" + ssid + "\"";


        if(type == WIFICIPHER_NOPASS) {
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        } else if(type == WIFICIPHER_WEP) {
            config.hiddenSSID = true;
            config.wepKeys[0]= "\""+password+"\"";
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            config.wepTxKeyIndex = 0;
        } else if(type == WIFICIPHER_PSK) {
            config.preSharedKey = "\""+password+"\"";
            config.hiddenSSID = true;
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            config.status = WifiConfiguration.Status.ENABLED;
        } else if (type == WIFICIPHER_EAP) {

        }
        return config;
    }


7.监听wifi链接状态

    public void registerReceiver(Context context){
        if (!isRegisterReceiver){
            isRegisterReceiver = true;
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(EXIT_ACTION);
            intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
            intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
            intentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
            context.registerReceiver(WifiReceiver.this,intentFilter);
        }
    }
    public void unRegisterReceiver(Context context){
        if (isRegisterReceiver){
            isRegisterReceiver = false;
            context.unregisterReceiver(WifiReceiver.this);
        }
    }


这里的回调响应事件,在实际开发中,重新链接其他网络,监听NETWORK_STATE_CHANGED_ACTION事件时,直接判断为已连接,所以,此处我们增加了一个is_Success的判断值,这个值 是在第五步的wifiManager.addNetWork()方法的成功返回值。

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo mobileInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        NetworkInfo activeInfo = manager.getActiveNetworkInfo();
        if (mobileInfo != null && activeInfo != null && wifiInfo != null){
//            Toast.makeText(context, "mobile:"+mobileInfo.isConnected()+"\n"+"wifi:"+wifiInfo.isConnected()
//                    +"\n"+"active:"+activeInfo.getTypeName(), Toast.LENGTH_LONG).show();
        }
        switch (intent.getAction()){
            case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                LogUtils.e("WifiReceiver","网络状态改变");
                NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                if (null != info) {
                    NetworkInfo.State state = info.getState();
                    boolean isConnected = state == NetworkInfo.State.CONNECTED;
                    LogUtils.e("WifiReceiver", WifiUtil.is_Success+"isConnected:"+isConnected+"::"+wifiInfo.isConnected());
                    if (isConnected&&WifiUtil.is_Success) {
                        LogUtils.e("WifiReceiver", "connectWiFiSuccess");
                        if (mCallBack != null) {
                            mCallBack.connectWiFiSuccess();
                            WifiUtil.is_Success = false;
                        }
                    }
                }
                break;

            case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:
                int linkWifiResult = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 123);
                LogUtils.e("linkWifiResult",linkWifiResult+"");
                if (linkWifiResult == WifiManager.ERROR_AUTHENTICATING) {
                    LogUtils.e("WifiReceiver","密码错误");
                    if(mCallBack!=null){
                        mCallBack.connectWiFiFailed();
                    }
                }
                break;
            case WifiManager.WIFI_STATE_CHANGED_ACTION:
                WifiManager mWm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                //获取当前的wifi状态int类型数据
                int mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
                switch (mWifiState ) {
                    case WifiManager.WIFI_STATE_ENABLED:
                        //已打开
                        break;
                    case WifiManager.WIFI_STATE_DISABLED:
                        //已关闭
                        if(!mWm.isWifiEnabled()){
                            mWm.setWifiEnabled(true);
                        }
                        break;
                }
                break;

        }
    }

8.wifi相关的其他方法

(1)判断wifi是不是5G网络(部分手机不支持5G)

    /**
     * 判断wifi是否为5G
     * @param freq
     * @return
     */
    public static boolean is5GHz(int freq) {
        return freq > 4900 && freq < 5900;
    }

(2)判断手机是否开启了热点(如果开启了热点,则不让打开wifi)

    /**判断热点开启状态*/
    public boolean isWifiApEnabled() {
        return getWifiApState() == WIFI_AP_STATE.WIFI_AP_STATE_ENABLED;
    }
    public enum WIFI_AP_STATE {
        WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_ENABLING,  WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_FAILED
    }
    private WIFI_AP_STATE getWifiApState(){
        int tmp;
        try {
            Method method = wifiManager.getClass().getMethod("getWifiApState");
            tmp = ((Integer) method.invoke(wifiManager));
            // Fix for Android 4
            if (tmp > 10) {
                tmp = tmp - 10;
            }
            return WIFI_AP_STATE.class.getEnumConstants()[tmp];
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return WIFI_AP_STATE.WIFI_AP_STATE_FAILED;
        }
    }


(3)在Android6.0之后,不同应用间,不能够修改其他应用设置的wifi。即 removeNetWork()方法返回false  这个问题 普通应用开发 目前没有找到解决办法。  但是通过查看Settings源码发现,Settings是用过forgett()方法 来删除wifi信息的。 具体的 可以查看系统源码。但是调用forget方法,必须在系统编译下 才能够使用 所以 并不适用于普通的app开发

frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiServiceImpl  等相关代码


  wifiManager.forget(accessPoint.getConfig().networkId, null /* listener */);








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值