Android自動連接指定的wifi,免密碼或指定密碼

来源:http://www.cnblogs.com/best/archive/2016/07/02/5634724.html
-Advertisement-
Play Games

一、運行時的狀態 遇到一個這樣的要求:“不進行掃描操作,怎麼對指定的免密碼WIFI進行連接(之前沒有連接過)”,於是動手寫了一個Demo,如圖所示未連接成功時的狀態,第一個編輯框讓用戶輸入SSID,第二個編輯框輸入密碼,密碼可以根據實例情況輸入,也可以不輸入密碼,因為有些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()+"\n"+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、參考示例:

下載示例源碼

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、在實際工作中,都是一個團隊在做項目,不是一個人在工作。多人協作,就是每個團隊都有自己 的命名習慣。1、css選擇符命名,規範。2、都有命名規範文檔。 二、css選擇符作用:指定css樣式所作用對象(範圍)1、標簽選擇符:針對html標簽2、id選擇符:針對頁面中只出現一次的內容,id3、類選擇符 ...
  • 這系列文章主要是學習Html5相關的知識點,以學習API知識點為入口,由淺入深的引入實例,讓大家一步一步的體會"h5"能夠做什麼,以及在實際項目中如何去合理的運用達到使用自如,完美駕馭O(∩_∩)O~ 先出一道題目:以下不是HTML5新增的API是 http://hovertree.com/tiku ...
  • //標準化總價錢 s:總價錢,n:保留幾位小數 function fmoney(s, n) { n = n > 0 && n <= 20 ? n : 2; s = parseFloat((s + "").replace(/[^\d\.-]/g, "")).toFixed(n) + "";//更改這裡 ...
  • function ChangeDateFormat(cellval) { var date = new Date(parseInt(cellval.replace("/Date(", "").replace(")/", ""), 10)); var month = date.getMonth() + ...
  • 看完下麵大神的三篇文章就很清楚了 大白話講解promise(一) http://www.cnblogs.com/lvdabao/p/es6-promise-1.html 大白話講解promise(二) http://www.cnblogs.com/lvdabao/p/5320705.html 大白話 ...
  • 正所謂“一山不容二虎,一淵不藏兩蛟”,在某些“矯情”的需求中,數組中不能存在重覆的元素,於是就有了對數組去重方法的討論,關於數組去重的方法由來已久,我當然也想不出什麼原創的方法了,這裡只是簡單的總結一下以備忘。 不過,我們要先聲明一下,上面的這句強行組成的諺語還有下一句叫做“除非一公一母” ;也就是 ...
  • // 判斷substr字元串在str中出現的次數 isIgnore是否忽略大小寫! function countSubstr(str, substr, isIgnore) { var count; var reg = ""; if (isIgnore == true) { reg = "/" + s ...
  • 第1章 概 述 (作者小波QQ463431476) (來源http://blog.chinaaet.com/zhaocundang/p/5100017645博客) (來源 http://www.cnblogs.com/xiaobo-Linux/博客) 1.1 設計背景與意義 安卓物聯繫統的設計主要是 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...