问题
I have managed to scan for wireless networks and obtain scan results in my application. but is there a way i could possibly connect to them using my app itself? I was wondering whether I would have to specify the encryption type for the network i'm trying to connect? and my requirement would be to connect to any wireless network irrespective of it's encryption type?
Any ideas? Thanks
回答1:
TO connect to WiFi AP needed to implement followed steps:
Scan WiFi
To be sure that you have appropriate AP. Bear in mind that you must provide password to secured AP. Suppose you know witch AP you prefer and now we are going to other step:
Create new profile
We need must support information about:
What type AP should be: Open spot, WEP, WPA, (or WPA2), with shared-key authentication, WPA2-Enterprise (RADIUS Server authentication)
Priority - Priority determines the preference given to a network by wpa_supplicant when choosing an access point with which to associate (I set default 1000)
SSID - AP Name
Password - if it's secured AP.
Here is a snippets method demonstrating the technique:
I used single enum TEncMode encMode
for switch statement
....
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;
For now we configured new AP according to our requst. Now lets create it:
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 } }
if you skip this implementation, after turn WiFi off your created AP will dissapear
m_WifiManager.saveConfiguration();
So far so good, we can wait for android to connect to our new AP or we can do it by ourselves
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;
}
That's all. For sure you can listen on WiFi state changed to catch CONNECTED
event. Because we don't know how long it will take to device to connect to your AP. But we disabled all other APs and enabled new one. After we can get HTTP response for example from google to be sure that our AP has internet.
Asked me to add this method:
/**
* 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();
}
回答2:
The only thing I know of, is checking the IP address to determine where you are connected. I would imagine that choosing the SSID would require using the device's interface (i.e. issuing an intent to the WiFi service instead of doing your own chooser).
For what it's worth, to detect where I'm connected, I use something like this:
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);
}
}
来源:https://stackoverflow.com/questions/12973872/how-to-connect-to-a-wireless-network-in-android