如何在安卓设备中连接到无线网络?

3
我已经在我的应用程序中成功扫描到了无线网络并获得了扫描结果。但是,我是否有可能使用我的应用程序连接到这些网络呢?我想知道是否需要指定我正在尝试连接的网络的加密类型?而且,我的要求是可以连接任何无线网络,无论其加密类型如何?有什么想法吗? 谢谢。

你能够扫描一台打印机(wifi)如果你知道它的IP地址吗?如果可以的话,请帮帮我。我是一个新手。 - MGDroid
2个回答

3

连接WiFi AP需要实现以下步骤:

  1. 扫描WiFi

    确保您拥有适当的AP。请注意,您必须提供受保护的AP密码。假设您知道您喜欢的AP,现在我们转到下一步:

  2. 创建新配置文件

    我们必须支持以下信息:

应该是什么类型的AP: 开放式网络, WEP, WPA, (或WPA2),采用共享密钥身份验证, WPA2-企业级(RADIUS服务器身份验证)

优先级-优先级确定wpa_supplicant选择与之关联的接入点时给出的首选项(我设置默认值为1000)。

SSID - AP Name

密码 - 如果它是安全的AP。

这里是演示技术的代码片段:

我使用单个enum TEncMode encMode进行开关语句。

....
WifiConfiguration wc = new WifiConfiguration();
    wc.allowedAuthAlgorithms.clear();
    wc.allowedGroupCiphers.clear();
    wc.allowedKeyManagement.clear();
    wc.allowedPairwiseCiphers.clear();
    wc.allowedProtocols.clear();

    switch (encMode) {
    case ENC_WEP:
        // If password is empty, it should be left untouched
        if (!TextUtils.isEmpty(pswd)) {

            wc.wepKeys[0] = TextUtil.convertToQuotedString(pswd);

        }

        wc.wepTxKeyIndex = 0;

        wc.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
        wc.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);

        wc.allowedKeyManagement.set(KeyMgmt.NONE);

        wc.allowedGroupCiphers.set(GroupCipher.WEP40);
        wc.allowedGroupCiphers.set(GroupCipher.WEP104);
        break;

    case ENC_WPA:
    case ENC_WPA2:
        wc.allowedGroupCiphers.set(GroupCipher.TKIP);
        wc.allowedGroupCiphers.set(GroupCipher.CCMP);

        wc.allowedKeyManagement.set(KeyMgmt.WPA_PSK);

        wc.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
        wc.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);

        wc.allowedProtocols.set(Protocol.RSN);
        wc.allowedProtocols.set(Protocol.WPA);

        // If password is empty, it should be left untouched
        if (!TextUtils.isEmpty(pswd)) {
            if (pswd.length() == 64) {
                // Goes unquoted as hex
                wc.preSharedKey = pswd;
            } else {
                // Goes quoted as ASCII
                wc.preSharedKey = TextUtil.convertToQuotedString(pswd);
            }
        }
        break;

        //      case ENC_WPA2_ENTERPRISE:
        ....
        //          break;

    default:
        wc.allowedKeyManagement.set(KeyMgmt.NONE);
        break;
    }

    // This is must be quoted according to the documentation 
    // http://developer.android.com/reference/android/net/wifi/WifiConfiguration.html#SSID
    wc.SSID = TextUtil.convertToQuotedString(ssid.toString());

    wc.hiddenSSID = false;
    wc.priority = prior;
    wc.BSSID = null;


    wc.status = WifiConfiguration.Status.ENABLED; 

现在我们已经根据我们的要求配置了新的AP。现在让我们创建它:

  1. Create new AP only

     ....
     int res = -1;
     WifiManager m_WifiManager = (WifiManager)m_context.getSystemService(Context.WIFI_SERVICE); 
    ....
            /** If profile exists, do nothing  */
        if(ifConnectionProfileExists(ssid) == true){
    
            Log.i(Constants.TAG, "createConnectionProfile :: " + "CREATE_PROFILE ssid=" + ssid  + " exists");
        }
        else{
            res = m_WifiManager.addNetwork(wc);
    
            Log.i(Constants.TAG, "createConnectionProfile :: " + " CREATE_PROFILE ssid=" + ssid  + " dosn't exist, addNetwork ... res = " + res);
    
            // Don't make to AP high priority to connect
            //m_WifiManager.enableNetwork(res, false);  
    
            m_WifiManager.saveConfiguration();
    
            if(res != -1){
                             // profile created                 
            }
            else{           
             // failed to add profile   
            }
        }
    

如果您跳过此实现,关闭WiFi后您创建的AP将会消失。m_WifiManager.saveConfiguration();

到目前为止还不错,我们可以等待Android连接到我们的新AP,或者自己连接。

  1. Create and connect to AP

     int res = -1;
    
        /** If profile exists, do nothing  */
        if(ifConnectionProfileExists(ssid) == true){
    
            res = getNetIdBySSID(ssid);
        }
        else{
            res = m_WifiManager.addNetwork(wc);             
        }
    
    
        // Don't make to AP high priority to connect
        boolean b = m_WifiManager.enableNetwork(res, true);      
    
        if(b == true){
    
            fixSupplicant();
    
            m_WifiManager.saveConfiguration();
    
            // start connect to AP
        }
        else{           
            // failed
        }
    
            ....
    
    private void fixSupplicant() {
        final SupplicantState state = m_WifiManager.getConnectionInfo().getSupplicantState();
        boolean isReconnectDone = false;
    
    if ((state == SupplicantState.SCANNING)
            || (state == SupplicantState.DISCONNECTED) 
            || (state == SupplicantState.DORMANT)) {
        isReconnectDone = m_WifiManager.reconnect();;
    
    }       
     }
    
    
       private boolean ifConnectionProfileExists(String ssid){
    
    List<WifiConfiguration> apProfiles = m_WifiManager.getConfiguredNetworks();
    
    // remove profile if exists:
    for (int i = 0; i < apProfiles.size(); i++) {
    
        final WifiConfiguration ap = apProfiles.get(i);
    
        if ((ap.SSID != null)) {        
            // try to find by SSID
            if (TextUtils.equals(ap.SSID), ssid) {                  
                return true;
            }
        }               
    }
    
    return false;
     }
    

Enum TEncMode

/**
* Represents encryption types modes of access points
*/
public enum TEncMode {

/**
 * No encryption (open spot)
 */
ENC_NONE(0),

/*
 * General encryption
 */
ENC_UNKNOWN(1),

/**
 * WEP
 */
ENC_WEP(2),

/**
 * WPA
 */
ENC_WPA(3),

/**
 * WPA (or WPA2), with shared-key authentication
 */
ENC_WPA2(4),

/**
 * WPA2-Enterprise (RADIUS Server authentication).
 */
ENC_WPA2_ENTERPRISE(5)
;

public static TEncMode
FromIntToEnum(
    int value ) throws Exception
{
    for ( TEncMode c : TEncMode.values() ) {
        if ( c.mId == value ) {
            return c;
        }
    }

    throw new AgException( new StringBuilder("Illegal TEncMode: ").append(value).toString() );
}

public int
FromEnumToInt() {
    return mId;
}

private TEncMode( int id ){
    mId = id;
}

private int mId;
}

以上就是全部内容。当然你可以监听WiFi状态的改变并捕获 CONNECTED 事件,因为我们不知道设备连接到您的AP需要多长时间。但是我们已经禁用了所有其他AP并启用了新的AP。在此之后,我们可以从Google获取HTTP响应,以确保我们的AP具有Internet连接。

要求我添加此方法:

    /**
 * Surround the given string in quotes.
 * 
 * @param string The text to surround in quotes.
 * @return string wrapped with quotes.
 */
static public String convertToQuotedString(String string){

    if (string==null) {
        string = "";
    }
    empty(workBuffer);
    workBuffer.append("\"");
    workBuffer.append(string);
    workBuffer.append("\"");

    return workBuffer.toString();
}

它是用于实际加密类型AP的单个“枚举”。我编辑了我的示例,请参见上面的帖子末尾。 - Maxim Shoustin
嘿,Fess,我遇到了这个编译错误,它说:“TextUtils 类型未定义 convertToQuotedString(String) 方法。” - Mr.Noob
1
好的,这很简单,只需在输入字符串中加上引号,例如将 name 转换为 "name"。 - Maxim Shoustin
还是有点困惑,似乎还没有连接成功!:( - Mr.Noob
@MaximShoustin,如果您知道打印机(wifi)的IP地址,您能扫描它吗?如果可以,请帮帮我。我是新手。 - MGDroid
显示剩余4条评论

1
我所知道的唯一方法是检查IP地址以确定您连接的位置。我想选择SSID需要使用设备的接口(即向WiFi服务发出意图而不是自己进行选择器)。
值得一提的是,为了检测我连接到哪里,我使用类似于以下代码的东西:
package com.nifty.android.initialization;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.nifty.android.R;
import com.nifty.android.preferences.Preferences;

public class NetworkDetector {
    Context mContext = null;
    Preferences mPrefs = null;

    public static final String NONE                =        "none";
    public static final String HI_SPEED            =        "hiSpeed";
    public static final String MED_SPEED           =        "medSpeed";
    public static final String LOW_SPEED           =        "lowSpeed";

    public NetworkDetector(Context aContext) {
            mContext = aContext;
            mPrefs = new Preferences(aContext);

            WifiManager lWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
            TelephonyManager lTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

            String netSpeed = null;

            if( (lWifiManager.isWifiEnabled() && lWifiManager.getConnectionInfo() != null && lWifiManager.getConnectionInfo().getIpAddress() != 0)) {
                    netSpeed = HI_SPEED;
            } else {
                    if(lTelephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS  && lTelephonyManager.getDataState() == TelephonyManager.DATA_CONNECTED) {
                            netSpeed = MED_SPEED;
                    } else {
                            if( (   lTelephonyManager != null && lTelephonyManager.getDataState() == TelephonyManager.DATA_CONNECTED) ){
                                    netSpeed = LOW_SPEED;
                            } else {
                                    netSpeed = NONE;
                            }
                    }
            }

            mPrefs.networkSpeed(netSpeed);
            }
    }

我认为如果您可以使用设备接口进行扫描,那么从应用程序连接必须是可能的。需要进一步了解它。 - Mr.Noob
@Ted Collins,如果您知道打印机的IP地址,能否扫描一下它的WiFi连接?如果可以的话,请帮帮我。我是个新手。 - MGDroid
这是一个非常好的问题。你应该考虑将其作为一个单独的问题发布,而不是作为评论(这样其他人就可以找到它)。同时,我会看看是否能够弄清楚如何做到这一点。 - Ted Collins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接