你的位置:首页 > 操作系统

[操作系统]Android自动连接指定的wifi,免密码或指定密码


一、运行时的状态

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

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

测试的手机信息如下:

二、功能实现

2.1、项目结构如下所示:

2.2、页面布局activity_main.

<LinearLayout ="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.

<??><manifest ="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.    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、参考示例:

下载示例源码