• Android自动连接指定的wifi,免密码或指定密码


    一、运行时的状态

    遇到一个这样的要求:“不进行扫描操作,怎么对指定的免密码WIFI进行连接(之前没有连接过)”,于是动手写了一个Demo,如图所示未连接成功时的状态,第一个编辑框让用户输入SSID,第二个编辑框输入密码,密码可以根据实例情况输入,也可以不输入密码,因为有些Wifi免密码。这里的免密码不是指可以破解wifi密码。注意图片中手机顶部的wifi图标,是没有的,说明此时并没有打开手机的wifi。在手机上运行状态如下所示:

    输入SSID,点击连接后的状态,当手机的wifi没有打开时,程序将自动打开wifi,打开后再连接指定的wifi。

    测试的手机信息如下:

    二、功能实现

    2.1、项目结构如下所示:

    2.2、页面布局activity_main.xml文件如下所示:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <TextView
            android:id="@+id/txtSSID"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="SSID:"
            android:textSize="@dimen/activity_horizontal_margin" />
    
        <EditText
            android:id="@+id/editSSID"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:text="FBI" >
    
            <requestFocus />
        </EditText>
    
        <TextView
            android:id="@+id/TextView01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Password:"
            android:textSize="@dimen/activity_horizontal_margin" />
    
        <EditText
            android:id="@+id/editPwd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:text="" />
    
        <Button
            android:id="@+id/btnConnect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Connect" />
    
        <TextView
            android:id="@+id/txtMessage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="" />
    
    </LinearLayout>

     

    2.3、清单文件AndroidManifest.xml内容如下,中间添加了对wifi访问的用户权限部分非常重要

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.wifigo"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="14"
            android:targetSdkVersion="19" />
    
        <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" >
        </uses-permission>
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
        </uses-permission>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
        </uses-permission>
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
        </uses-permission>
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

     2.4、Wifi连接管理类WifiConnector.java,有不少是参考热心网友的博客,谢谢了!

    package com.example.wifigo;
    
    import java.util.List;
    
    import android.net.wifi.*;
    import android.net.wifi.WifiConfiguration.AuthAlgorithm;
    import android.net.wifi.WifiConfiguration.KeyMgmt;
    import android.os.Handler;
    import android.os.Message;
    import android.text.TextUtils;
    import android.util.Log;
    
    public class WifiConnector {
        Handler mHandler;
        WifiManager wifiManager;
        
        /**
         * 向UI发送消息
         * @param info 消息
         */
        public void sendMsg(String info) {
            if (mHandler != null) {
                Message msg = new Message();
                msg.obj = info;
                mHandler.sendMessage(msg);// 向Handler发送消息
            } else {
                Log.e("wifi", info);
            }
        }
    
        //WIFICIPHER_WEP是WEP ,WIFICIPHER_WPA是WPA,WIFICIPHER_NOPASS没有密码
        public enum WifiCipherType {
            WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
        }
    
        // 构造函数
        public WifiConnector(WifiManager wifiManager) {
            this.wifiManager = wifiManager;
        }
    
        // 提供一个外部接口,传入要连接的无线网
        public void connect(String ssid, String password, WifiCipherType type) {
            Thread thread = new Thread(new ConnectRunnable(ssid, password, type));
            thread.start();
        }
    
        // 查看以前是否也配置过这个网络
        private WifiConfiguration isExsits(String SSID) {
            List<WifiConfiguration> existingConfigs = wifiManager
                    .getConfiguredNetworks();
            for (WifiConfiguration existingConfig : existingConfigs) {
                if (existingConfig.SSID.equals(""" + SSID + """)) {
                    return existingConfig;
                }
            }
            return null;
        }
    
        private WifiConfiguration createWifiInfo(String SSID, String Password,
                WifiCipherType Type) {
            WifiConfiguration config = new WifiConfiguration();
            config.allowedAuthAlgorithms.clear();
            config.allowedGroupCiphers.clear();
            config.allowedKeyManagement.clear();
            config.allowedPairwiseCiphers.clear();
            config.allowedProtocols.clear();
            config.SSID = """ + SSID + """;
            // nopass
            if (Type == WifiCipherType.WIFICIPHER_NOPASS) {
                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            }
            // wep
            if (Type == WifiCipherType.WIFICIPHER_WEP) {
                if (!TextUtils.isEmpty(Password)) {
                    if (isHexWepKey(Password)) {
                        config.wepKeys[0] = Password;
                    } else {
                        config.wepKeys[0] = """ + Password + """;
                    }
                }
                config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
                config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
                config.allowedKeyManagement.set(KeyMgmt.NONE);
                config.wepTxKeyIndex = 0;
            }
            // wpa
            if (Type == WifiCipherType.WIFICIPHER_WPA) {
                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.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                config.allowedPairwiseCiphers
                        .set(WifiConfiguration.PairwiseCipher.CCMP);
                config.status = WifiConfiguration.Status.ENABLED;
            }
            return config;
        }
    
        // 打开wifi功能
        private boolean openWifi() {
            boolean bRet = true;
            if (!wifiManager.isWifiEnabled()) {
                bRet = wifiManager.setWifiEnabled(true);
            }
            return bRet;
        }
    
        class ConnectRunnable implements Runnable {
            private String ssid;
    
            private String password;
    
            private WifiCipherType type;
    
            public ConnectRunnable(String ssid, String password, WifiCipherType type) {
                this.ssid = ssid;
                this.password = password;
                this.type = type;
            }
    
            @Override
            public void run() {
                try {
                    // 打开wifi
                    openWifi();
                    sendMsg("opened");
                    Thread.sleep(200);
                    // 开启wifi功能需要一段时间(我在手机上测试一般需要1-3秒左右),所以要等到wifi
                    // 状态变成WIFI_STATE_ENABLED的时候才能执行下面的语句
                    while (wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING) {
                        try {
                            // 为了避免程序一直while循环,让它睡个100毫秒检测……
                            Thread.sleep(100);
                        } catch (InterruptedException ie) {
                        }
                    }
    
                    WifiConfiguration wifiConfig = createWifiInfo(ssid, password,
                            type);
                    //
                    if (wifiConfig == null) {
                        sendMsg("wifiConfig is null!");
                        return;
                    }
    
                    WifiConfiguration tempConfig = isExsits(ssid);
    
                    if (tempConfig != null) {
                        wifiManager.removeNetwork(tempConfig.networkId);
                    }
    
                    int netID = wifiManager.addNetwork(wifiConfig);
                    boolean enabled = wifiManager.enableNetwork(netID, true);
                    sendMsg("enableNetwork status enable=" + enabled);
                    boolean connected = wifiManager.reconnect();
                    sendMsg("enableNetwork connected=" + connected);
                    sendMsg("连接成功!");
                } catch (Exception e) {
                    // TODO: handle exception
                    sendMsg(e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    
        private static boolean isHexWepKey(String wepKey) {
            final int len = wepKey.length();
    
            // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
            if (len != 10 && len != 26 && len != 58) {
                return false;
            }
    
            return isHex(wepKey);
        }
    
        private static boolean isHex(String key) {
            for (int i = key.length() - 1; i >= 0; i--) {
                final char c = key.charAt(i);
                if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a'
                        && c <= 'f')) {
                    return false;
                }
            }
    
            return true;
        }
    }

    2.5、MainActivity.java代码,完成接收用户的输入与调用wifi连接功能,如下所示:

    package com.example.wifigo;
    
    import com.example.wifigo.WifiConnector.WifiCipherType;
    
    import android.app.Activity;
    import android.content.Context;
    import android.net.wifi.WifiManager;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        Button btnConnect;
        WifiManager wifiManager;
        WifiConnector wac;
        TextView textView1;
        EditText editPwd;
        EditText editSSID;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btnConnect = (Button) findViewById(R.id.btnConnect);
            textView1 = (TextView) findViewById(R.id.txtMessage);
            wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
            wac = new WifiConnector(wifiManager);
            
             editPwd=(EditText) findViewById(R.id.editPwd);
             editSSID=(EditText) findViewById(R.id.editSSID);
            
            wac.mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    // 操作界面
                    textView1.setText(textView1.getText()+"
    "+msg.obj+"");
                    super.handleMessage(msg);
                }
            };
            btnConnect.setOnClickListener(new Button.OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    try {
                        wac.connect(editSSID.getText().toString(), editPwd.getText().toString(),
                                editPwd.getText().toString().equals("")?WifiCipherType.WIFICIPHER_NOPASS:WifiCipherType.WIFICIPHER_WPA);
                    } catch (Exception e) {
                        textView1.setText(e.getMessage());
                    }
    
                }
            });
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }

    2.6、小结

    时间比较紧,代码比较粗糙,这毕竟只是一个demo,如果您需要使用在商业项目中这可能只具有抛砖引玉的作用了;另外测试时发现如果手机的wifi没有打开,依靠程序打开时程序会崩溃,后面发现有可能是打开wifi时需要一段时间,所以代码中增加了一些人为的延时操作,尽量用更加优雅的办法替代;我使用一台Android 4.x.x的meizu note 1手机和一个DLink DIR-600N的老路由器测试没有问题,使用自己的笔记本电脑作热点,带密码连接没有问题,这不代表在其它环境下就正常了。 

     2.7、参考示例:

    下载示例源码

  • 相关阅读:
    HOWTO re
    数据类型
    字符串
    最大公约数
    this
    tip 2:找最小公倍数之Boost
    tip 1:一个简单的将int型转换成char的方法
    Item47
    成员函数模板
    item44:将与参数无关的代码抽离template
  • 原文地址:https://www.cnblogs.com/best/p/5634724.html
Copyright © 2020-2023  润新知