zoukankan      html  css  js  c++  java
  • 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、参考示例:

    下载示例源码

  • 相关阅读:
    Asp.Net Web API 2第八课——Web API 2中的属性路由
    Asp.Net Web API 2第七课——Web API异常处理
    Asp.Net Web API 2第六课——Web API路由和动作选择
    Asp.Net Web API 2第五课——Web API路由
    开始学习python
    BMI 小程序 购物车
    深浅copy 文件操作
    字典 dict 集合set
    基本数据类型 (str,int,bool,tuple,)
    python 运算符
  • 原文地址:https://www.cnblogs.com/best/p/5634724.html
Copyright © 2011-2022 走看看