最近搞了个无线wifi模块,兴趣爱好写了个android wifi密码连接,先将成果分享出来,谢谢大家指出不足,欢迎点赞。
功能点:连接wifi模块,包括无密码和加密方式。异步连接,不会导致ANR。
自动保存wifi密码。
先上图:刷新wifi站点信息
连接我的wifi模块,没密码是ok的,有密码的我也先试了一把,所有密码自动保存了(代码中体现)
连接成功(通过获取到ip地址来判断是否连接成功)ip地址有打印输出
直接上代码,MainActivity直接继承至ListActivity,wifi连接模块主要用到android的WifiManager,WifiInfo和输出结果集ScanResult.
public class MainActivity extends ListActivity {
private static final String TAG = "MainActivity";
private static final boolean D = true;
private WifiManager wifiManager;
private WifiInfo current_wifiInfo;// 当前连接的wifi
// 扫描结果列表
private List<ScanResult> list_scan;// wifi列表
private ScanResult scanResult;
private int current_wifi_index;//当前点击的wifi索引
// 添加有图片的ListActivity
private ArrayList<HashMap<String, Object>> hashmap_wifi_items = new ArrayList<HashMap<String, Object>>();;
private SimpleAdapter simpleAdapter;
private ProgressDialog progressDialog;
private EditText edt_wifi_password = null;
private AlertDialog connect_wifi_alertdialog;
private boolean is_connect_wifi_thread = false;
private ConnectWifiThread connect_wifi_thread = null;
private final String PREFERENCES_NAME = "userinfo";
private String wifi_password = "";
创建activity是打开wifi刷新列表得到wifi结果集,加载到listView里面。我们会看到图1的效果
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wifi_list);
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
openWifi();
current_wifiInfo = wifiManager.getConnectionInfo();
getAllNetWorkList();
simpleAdapter = new SimpleAdapter(this, hashmap_wifi_items,
R.layout.item_wifi_list, new String[] { "ItemTitle",
"ItemImage" }, new int[] { R.id.wifiTextView,
R.id.wifiImageView });
this.setListAdapter(simpleAdapter);
}
Handler handler = new Handler() {
public void handleMessage(Message msg) {
if(D) Log.v(TAG, "msg.what = " + msg.what);
SharedPreferences vPreferences = getSharedPreferences(
PREFERENCES_NAME, Activity.MODE_PRIVATE);
Editor vEditor = vPreferences.edit();
switch (msg.what) {
case 0:
new RefreshSsidThread().start();
break;
case 1:
new AlertDialog.Builder(MainActivity.this)
.setMessage("连接失败,请重新连接!")
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
}
}).show();
break;
case 3:
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.access_point_dialog,
(ViewGroup) findViewById(R.id.dialog));
edt_wifi_password = (EditText) layout
.findViewById(R.id.edtTextWifiPassword);
edt_wifi_password.setText(vPreferences.getString(
"\"" + list_scan.get(current_wifi_index).SSID + "\"", ""));
connect_wifi_alertdialog = new AlertDialog.Builder(MainActivity.this)
.setView(layout)
.setTitle(list_scan.get(current_wifi_index).SSID)
.setNegativeButton("取消", null)
.setPositiveButton("连接",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
// TODO Auto-generated method stub
wifi_password = edt_wifi_password.getText()
.toString();
connectionConfiguration(current_wifi_index,
edt_wifi_password.getText().toString());
}
}).show();
break;
case 4:
vEditor.putString("\"" + list_scan.get(current_wifi_index).SSID + "\"", wifi_password);
vEditor.commit();
Toast.makeText(MainActivity.this, "连接成功 ip地址为:"+Formatter.formatIpAddress(current_wifiInfo.getIpAddress()), Toast.LENGTH_SHORT).show();
break;
default:
break;
}
super.handleMessage(msg);
}
};
public void openWifi() {
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
}
public void getAllNetWorkList() {
// 每次点击扫描之前清空上一次的扫描结果
// int vIntSecurity = -1;
String vStr = "";
hashmap_wifi_items.clear();
wifiManager.startScan();
// 开始扫描网络
list_scan = wifiManager.getScanResults();
if (list_scan != null) {
for (int i = 0; i < list_scan.size(); i++) {
if(D) Log.d(TAG, "listSize = " + list_scan.size());
// 得到扫描结果
HashMap<String, Object> vMap = new HashMap<String, Object>();
scanResult = list_scan.get(i);
if (0 == getSecurity(scanResult)) {
vStr = "NO-PASSWORD";
} else if (1 == getSecurity(scanResult)) {
vStr = "WEP";
}else if (2 == getSecurity(scanResult)) {
vStr = "WPA-PSK";
}
if (Math.abs(scanResult.level) > 100) {
vMap.put("ItemTitle", scanResult.SSID + "(" + vStr + ")");
vMap.put("ItemImage", R.drawable.wifi_full);
} else if (Math.abs(scanResult.level) > 70) {
vMap.put("ItemTitle", scanResult.SSID + "(" + vStr + ")");
vMap.put("ItemImage", R.drawable.wifi_mid);
} else if (Math.abs(scanResult.level) > 50) {
vMap.put("ItemTitle", scanResult.SSID + "(" + vStr + ")");
vMap.put("ItemImage", R.drawable.wifi_low);
} else {
vMap.put("ItemTitle", scanResult.SSID + "(" + vStr + ")");
vMap.put("ItemImage", R.drawable.wifi_low);
}
hashmap_wifi_items.add(vMap);
}
}
}
public int getSecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return 1;
} else if (result.capabilities.contains("PSK")) {
return 2;
} else if (result.capabilities.contains("EAP")) {
return 3;
}
return 0;
}
public void refreshWifiList(View view) {
getAllNetWorkList();
simpleAdapter.notifyDataSetChanged();
}
//这里就是点击事件了,点击之后取消上一次连接,以前我没有用哪个progressdialog导致可以点击很多个wifi SSID 这样前面的没有取消,后面有接着连接,理论上不通。
//CreateWifi这个函数就是根据不通的wifi加密类型创建一个wifiInfo然后去试着打开wifi。使用AsyncTask主要是放在ui产生Android ANR应用程序无响应。
protected void onListItemClick(ListView l, View v, int position, long id) {
if (connect_wifi_thread != null) {
connect_wifi_thread.cancel(true);
is_connect_wifi_thread = false;
if(D) Log.d(TAG, "cancel the wifi thread");
}
current_wifi_index = position;
handler.sendEmptyMessage(3);
}
class ConnectWifiThread extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
int index = Integer.parseInt(params[0]);
if (index > list_scan.size()) {
return null;
}
if(D) Log.d(TAG, "ssid = " + list_scan.get(index).SSID);
if(D) Log.d(TAG, "sucure type = " + getSecurity(list_scan.get(index)));
WifiConfiguration config = CreateWifiInfo(list_scan.get(index).SSID,
params[1], getSecurity(list_scan.get(index)));
int netId = wifiManager.addNetwork(config);
if (null != config) {
wifiManager.enableNetwork(netId, true);
return list_scan.get(index).SSID;
}
return null;
}
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
if(D) Log.d(TAG, "onPostExecute");
if(D) Log.d(TAG, result + "***" + list_scan.get(current_wifi_index));
if (list_scan.get(current_wifi_index).SSID.equals(result)) {
handler.sendEmptyMessage(0);
} else {
handler.sendEmptyMessage(1);
}
super.onPostExecute(result);
}
public WifiConfiguration CreateWifiInfo(String SSID, String Password,
int Type) {
if(D) Log.d(TAG, "SSID = " + SSID + "password " + Password + "type ="
+ Type);
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";
if (Type == 0) {
config.wepKeys[0] = "\"" + "\"";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
} else if (Type == 1) {
config.preSharedKey = "\"" + Password + "\"";
config.hiddenSSID = true;
config.allowedAuthAlgorithms
.set(WifiConfiguration.AuthAlgorithm.SHARED);
config.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.WEP40);
config.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.WEP104);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
} else if (Type == 2) {
if(D) Log.d(TAG, "into type 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;
} else {
return null;
}
return config;
}
}
public void connectionConfiguration(int index, String passwrod) {
progressDialog = ProgressDialog.show(MainActivity.this, "正在连接...",
"请稍候...",true);
connect_wifi_thread = new ConnectWifiThread();
connect_wifi_thread.execute(index + "", passwrod);
}
class RefreshSsidThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
is_connect_wifi_thread = true;
int i = 0;
while (is_connect_wifi_thread) {
if (wifiManager == null) {
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
}
current_wifiInfo = wifiManager.getConnectionInfo();
if(D) Log.d(TAG, "++++" + current_wifiInfo.getSSID());
if(D) Log.d(TAG, "++++" + (list_scan.get(current_wifi_index).SSID).toString());
if(D) Log.d(TAG, "++++" + current_wifiInfo.getIpAddress());
<span style="white-space:pre"> </span>//这个是以前没有加progressdialog的时候防止很多时间内点击不同的SSID导致连接到前面的WIFI了。
if (("\"" + list_scan.get(current_wifi_index).SSID + "\"")
.equals(current_wifiInfo.getSSID())
&& 0 != current_wifiInfo.getIpAddress()) {
if (null != progressDialog) {
progressDialog.dismiss();
}
handler.sendEmptyMessage(4);
is_connect_wifi_thread = false;
} else if (6 == (i++)) {
if (null != progressDialog) {
progressDialog.dismiss();
}
is_connect_wifi_thread = false;
handler.sendEmptyMessage(1);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
is_connect_wifi_thread = false;
e.printStackTrace();
}
}
super.run();
}
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
if (connect_wifi_alertdialog != null) {
connect_wifi_alertdialog.dismiss();
}
super.onDestroy();
}
access_point_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/dialog" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码" />
<EditText
android:id="@+id/edtTextWifiPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword" >
<requestFocus />
</EditText>
</LinearLayout>
activity_wifi_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<!-- 除了ListView和id为@id/android:empty的view之外,我们还可以任意添加view -->
<TextView
android:id="@+id/android:title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/wifi_list_name"/>
<!-- id为@id/android:list的ListView为客户化的list布局,如果没有,则系统会调用默认的布局 -->
<ListView
android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1.63"
android:background="#0099cc"
android:drawSelectorOnTop="false" >
</ListView>
<!-- 当ListView中没有数据时,id为@id/android:empty的view就会显示出来 -->
<TextView
android:id="@id/android:empty"
android:layout_width="match_parent"
android:layout_height="384dp"
android:layout_weight="9.40"
android:gravity="center_vertical|center_horizontal"
android:text="@string/wifi_list_empty"
android:textColor="#FF0000" />
<Button
android:id="@+id/refresh_wifilist_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="refreshWifiList"
android:layout_gravity="center_vertical"
android:text="@string/refresh_wifilist" />
</LinearLayout>
item_wifi_list.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/wifiImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/wifiTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/wifiImageView"
android:layout_marginBottom="14dp"
android:layout_toRightOf="@+id/wifiImageView"
android:text="TextView" />
</RelativeLayout>
strings.xml和在AndroidManifest.xml加入权限
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WifiTest</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="wifi_list_name">搜索到的WIFI站点列表</string>
<string name="wifi_list_empty">未搜索到可用的WIFI站点</string>
<string name="empty"></string>
<string name="refresh_wifilist">刷新WIFI列表</string>
</resources>
<span style="font-family: Arial, Helvetica, sans-serif;"> </span><!-- wifi 模块需要的权限 --></span></span>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />