android Wifi开发相关内容
今天,簡單講講android里如何使用WifiManager。
之前,我看代碼時,看到了wifi相關的代碼,發現自己對于這個內容的使用還很不熟悉,所以在網上查找資料,最終解決了問題。這里記錄一下。
移動設備離不開網絡,android平臺中在包android.net.wifi下提供了一些類專門用于管理設備的Wifi功能。該包下主要存在如下幾個類:
ScanResult類
這個類主要是通過Wifi硬件的掃描來獲取一些周邊的wifi熱點(access point)的信息。該類主要有5個域,
| 返回類型 | 域名 | 解釋 |
| public String | BSSID | 接入點的地址 |
| public String | SSID | 網絡的名字 |
| public String | capabilities | 網絡性能,包括接入點支持的認證、密鑰管理、加密機制等 |
| public int | frequency | 以MHz為單位的接入頻率 |
| public int | level | 以dBm為單位的信號強度。 |
WifiConfiguration類
通過該類獲取一個wifi網絡的網絡配置,包括安全配置等。它包含6個子類,如下所示:
| 子類 | 解釋 |
| WifiConfiguration.AuthAlgorthm | 獲取IEEE 802.11的加密方法 |
| WifiConfiguration.GroupCipher | 獲取組密鑰 |
| WifiConfiguration.KeyMgmt | 獲取密碼管理體制 |
| WifiConfiguration.PairwiseCipher | 獲取WPA方式的成對密鑰 |
| WifiConfiguration.Protocol | 獲取加密協議 |
| WifiConfiguration.Status | 獲取當前網絡狀態 |
該類內容較多,不一一例舉,需要用到的時候可以查Android SDK。
WifiInfo類
該類可以獲得已經建立的或處于活動狀態的wifi網絡的狀態信息。常用方法如下:
代碼:
mWifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE); mWifiInfo = mWifiManager.getConnectionInfo(); if(null != mWifiInfo && null != mWifiInfo.getSSID()){String info = "getSSID()="+mWifiInfo.getSSID()+"\n"+"getBSSID()="+mWifiInfo.getBSSID()+"\n"+"getHiddenSSID()="+mWifiInfo.getHiddenSSID()+"\n"+"getLinkSpeed()="+mWifiInfo.getLinkSpeed()+"\n"+"getMacAddress()="+mWifiInfo.getMacAddress()+"\n"+"getNetworkId()="+mWifiInfo.getNetworkId()+"\n"+"getRssi()="+mWifiInfo.getRssi()+"\n"+"getSupplicantState()="+mWifiInfo.getSupplicantState()+"\n"+"getDetailedStateOf()="+mWifiInfo.getDetailedStateOf(mWifiInfo.getSupplicantState());mTVWifiInfo.setText(info); }else {mTVWifiInfo.setText("沒有連接到wifi"); }WifiManager類
該類用于管理Wifi連接,定義了許多常量和方法,這里就不一一說了。
常用方法。
需要指出的是getWifiState()方法是反悔wifi的狀態,有整型常量表示,
這些就是wifi相關的基本知識,接下來舉一個例子:
注意,訪問Wifi需要用到如下權限:
<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>
wifi相關操作所需要用到的類。
先說一下wifi的基本使用情況。
import java.util.List; import android.content.Context; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.WifiLock; import android.widget.Toast;public class WifiAdmin {// 定義WifiManager對象 private WifiManager mWifiManager; // 定義WifiInfo對象 private WifiInfo mWifiInfo; // 掃描出的網絡連接列表 private List<ScanResult> mWifiList; // 網絡連接列表 private List<WifiConfiguration> mWifiConfiguration; // 定義一個WifiLock WifiLock mWifiLock;// 構造器 public WifiAdmin(Context context) { // 取得WifiManager對象 mWifiManager = (WifiManager) context .getSystemService(Context.WIFI_SERVICE); // 取得WifiInfo對象 mWifiInfo = mWifiManager.getConnectionInfo(); } // 打開WIFI public void openWifi(Context context) { if (!mWifiManager.isWifiEnabled()) { mWifiManager.setWifiEnabled(true);}else if (mWifiManager.getWifiState() == 2) {Toast.makeText(context,"親,Wifi正在開啟,不用再開了", Toast.LENGTH_SHORT).show();}else{Toast.makeText(context,"親,Wifi已經開啟,不用再開了", Toast.LENGTH_SHORT).show();}} // 關閉WIFI public void closeWifi(Context context) { if (mWifiManager.isWifiEnabled()) { mWifiManager.setWifiEnabled(false); }else if(mWifiManager.getWifiState() == 1){Toast.makeText(context,"親,Wifi已經關閉,不用再關了", Toast.LENGTH_SHORT).show();}else if (mWifiManager.getWifiState() == 0) {Toast.makeText(context,"親,Wifi正在關閉,不用再關了", Toast.LENGTH_SHORT).show();}else{Toast.makeText(context,"請重新關閉", Toast.LENGTH_SHORT).show();}} // 檢查當前WIFI狀態 public void checkState(Context context) { if (mWifiManager.getWifiState() == 0) {Toast.makeText(context,"Wifi正在關閉", Toast.LENGTH_SHORT).show();} else if (mWifiManager.getWifiState() == 1) {Toast.makeText(context,"Wifi已經關閉", Toast.LENGTH_SHORT).show();} else if (mWifiManager.getWifiState() == 2) {Toast.makeText(context,"Wifi正在開啟", Toast.LENGTH_SHORT).show();} else if (mWifiManager.getWifiState() == 3) {Toast.makeText(context,"Wifi已經開啟", Toast.LENGTH_SHORT).show();} else {Toast.makeText(context,"沒有獲取到WiFi狀態", Toast.LENGTH_SHORT).show();} } // 鎖定WifiLock public void acquireWifiLock() { mWifiLock.acquire(); } // 解鎖WifiLock public void releaseWifiLock() { // 判斷時候鎖定 if (mWifiLock.isHeld()) { mWifiLock.acquire(); } } // 創建一個WifiLock public void creatWifiLock() { mWifiLock = mWifiManager.createWifiLock("Test"); } // 得到配置好的網絡 public List<WifiConfiguration> getConfiguration() { return mWifiConfiguration; } // 指定配置好的網絡進行連接 public void connectConfiguration(int index) { // 索引大于配置好的網絡索引返回 if (index > mWifiConfiguration.size()) { return; } // 連接配置好的指定ID的網絡 mWifiManager.enableNetwork(mWifiConfiguration.get(index).networkId, true); } public void startScan(Context context) { mWifiManager.startScan(); // 得到掃描結果 mWifiList = mWifiManager.getScanResults(); // 得到配置好的網絡連接 mWifiConfiguration = mWifiManager.getConfiguredNetworks(); if (mWifiList == null) {if(mWifiManager.getWifiState()==3){Toast.makeText(context,"當前區域沒有無線網絡", Toast.LENGTH_SHORT).show();}else if(mWifiManager.getWifiState()==2){Toast.makeText(context,"WiFi正在開啟,請稍后重新點擊掃描", Toast.LENGTH_SHORT).show();}else{Toast.makeText(context,"WiFi沒有開啟,無法掃描", Toast.LENGTH_SHORT).show();}}} // 得到網絡列表 public List<ScanResult> getWifiList() { return mWifiList; } // 查看掃描結果 public StringBuilder lookUpScan() { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < mWifiList.size(); i++) { stringBuilder .append("Index_" + new Integer(i + 1).toString() + ":"); // 將ScanResult信息轉換成一個字符串包 // 其中把包括:BSSID、SSID、capabilities、frequency、level stringBuilder.append((mWifiList.get(i)).toString()); stringBuilder.append("/n"); } return stringBuilder; } // 得到MAC地址 public String getMacAddress() { return (mWifiInfo == null) ? "NULL" : mWifiInfo.getMacAddress(); } // 得到接入點的BSSID public String getBSSID() { return (mWifiInfo == null) ? "NULL" : mWifiInfo.getBSSID(); } // 得到IP地址 public int getIPAddress() { return (mWifiInfo == null) ? 0 : mWifiInfo.getIpAddress(); } // 得到連接的ID public int getNetworkId() { return (mWifiInfo == null) ? 0 : mWifiInfo.getNetworkId(); } // 得到WifiInfo的所有信息包 public String getWifiInfo() { return (mWifiInfo == null) ? "NULL" : mWifiInfo.toString(); } // 添加一個網絡并連接 public void addNetwork(WifiConfiguration wcg) { int wcgID = mWifiManager.addNetwork(wcg); boolean b = mWifiManager.enableNetwork(wcgID, true); System.out.println("a--" + wcgID); System.out.println("b--" + b); } // 斷開指定ID的網絡 public void disconnectWifi(int netId) { mWifiManager.disableNetwork(netId); mWifiManager.disconnect(); }public void removeWifi(int netId) {disconnectWifi(netId);mWifiManager.removeNetwork(netId);}//然后是一個實際應用方法,只驗證過沒有密碼的情況: public WifiConfiguration CreateWifiInfo(String SSID, String Password, int Type) { WifiConfiguration config = new WifiConfiguration(); config.allowedAuthAlgorithms.clear(); config.allowedGroupCiphers.clear(); config.allowedKeyManagement.clear(); config.allowedPairwiseCiphers.clear(); config.allowedProtocols.clear(); config.SSID = "\"" + SSID + "\""; WifiConfiguration tempConfig = this.IsExsits(SSID); if(tempConfig != null) { mWifiManager.removeNetwork(tempConfig.networkId); } if(Type == 1) //WIFICIPHER_NOPASS { config.wepKeys[0] = ""; config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); config.wepTxKeyIndex = 0; } if(Type == 2) //WIFICIPHER_WEP { config.hiddenSSID = true; config.wepKeys[0]= "\""+Password+"\""; 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; } if(Type == 3) //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; } private WifiConfiguration IsExsits(String SSID) { List<WifiConfiguration> existingConfigs = mWifiManager.getConfiguredNetworks(); for (WifiConfiguration existingConfig : existingConfigs) { if (existingConfig.SSID.equals("\""+SSID+"\"")) { return existingConfig; } } return null; } }如圖所示:
? ? ? ??
倆bug
這些代碼看起來沒有什么問題,但是通過不同環境的測試,發現了一些問題。
1 ?測試到的wifi熱點,有的ssid為”“,也就是ssid != null,獲取不到said。
2 ?wifi列表中有許多同名的wifi熱點,也就是掃描的結果中有重合部分,并不是有多個同名的wifi熱點。
第一個問題ssid為“”,這個看設置中并沒有多余wifi,但這個熱點點其它信息可以獲取到,說明這個熱點是存在的,應該是該熱點隱藏了,所以獲取不到。這也就是手機設置中為什么會有添加網路的按鈕了。
第二個問題,當附近wifi熱點比較少時不會出現此問題,當附近wifi網絡比較多時會出現此問題。這就需要將同名的熱點進行刪除,但是如果真有兩個ssid名相同的wifi,那就可以通過capabilities去區分吧,如果capabilities也相同就沒辦法了,系統設置里面也不顯示同名的。
修改上面的方法 startScan()。
public void startScan(Context context) { mWifiManager.startScan();//得到掃描結果 List<ScanResult> results = mWifiManager.getScanResults(); // 得到配置好的網絡連接 mWifiConfiguration = mWifiManager.getConfiguredNetworks(); if (results == null) {if(mWifiManager.getWifiState()==3){Toast.makeText(context,"當前區域沒有無線網絡",Toast.LENGTH_SHORT).show();}else if(mWifiManager.getWifiState()==2){Toast.makeText(context,"wifi正在開啟,請稍后掃描", Toast.LENGTH_SHORT).show();}else{Toast.makeText(context,"WiFi沒有開啟", Toast.LENGTH_SHORT).show();}} else {mWifiList = new ArrayList();for(ScanResult result : results){ if (result.SSID == null || result.SSID.length() == 0 || result.capabilities.contains("[IBSS]")) {continue;}boolean found = false;for(ScanResult item:mWifiList){ if(item.SSID.equals(result.SSID)&&item.capabilities.equals(result.capabilities)){found = true;break; }} if(!found){mWifiList.add(result);} } } }這樣就可以避免出現上面的兩種情況了。
? ? ? ??
代碼?
public class MainActivity extends Activity implements OnClickListener {public static final String TAG = "MainActivity";private Button check_wifi,open_wifi,close_wifi,scan_wifi;private ListView mlistView;protected WifiAdmin mWifiAdmin;private List<ScanResult> mWifiList;public int level;protected String ssid;protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mWifiAdmin = new WifiAdmin(MainActivity.this);initViews();IntentFilter filter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);//="android.net.wifi.STATE_CHANGE" 監聽wifi狀態的變化registerReceiver(mReceiver, filter);mlistView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {AlertDialog.Builder alert=new AlertDialog.Builder(MainActivity.this);ssid=mWifiList.get(position).SSID;alert.setTitle(ssid);alert.setMessage("輸入密碼");final EditText et_password=new EditText(MainActivity.this);final SharedPreferences preferences=getSharedPreferences("wifi_password",Context.MODE_PRIVATE);et_password.setText(preferences.getString(ssid, ""));alert.setView(et_password);//alert.setView(view1);alert.setPositiveButton("連接", new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which) {String pw = et_password.getText().toString();if(null == pw || pw.length() < 8){Toast.makeText(MainActivity.this, "密碼至少8位", Toast.LENGTH_SHORT).show();return; }Editor editor=preferences.edit();editor.putString(ssid, pw); //保存密碼editor.commit(); mWifiAdmin.addNetwork(mWifiAdmin.CreateWifiInfo(ssid, et_password.getText().toString(), 3));}});alert.setNegativeButton("取消", new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which) {////mWifiAdmin.removeWifi(mWifiAdmin.getNetworkId());}});alert.create();alert.show();}});}/** 控件初始化* */private void initViews() {check_wifi=(Button) findViewById(R.id.check_wifi);open_wifi=(Button) findViewById(R.id.open_wifi);close_wifi=(Button) findViewById(R.id.close_wifi);scan_wifi=(Button) findViewById(R.id.scan_wifi);mlistView=(ListView) findViewById(R.id.wifi_list); check_wifi.setOnClickListener(MainActivity.this);open_wifi.setOnClickListener(MainActivity.this);close_wifi.setOnClickListener(MainActivity.this);scan_wifi.setOnClickListener(MainActivity.this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.check_wifi:mWifiAdmin.checkState(MainActivity.this);break;case R.id.open_wifi:mWifiAdmin.openWifi(MainActivity.this);break;case R.id.close_wifi:mWifiAdmin.closeWifi(MainActivity.this);break;case R.id.scan_wifi:mWifiAdmin.startScan(MainActivity.this);mWifiList=mWifiAdmin.getWifiList();if(mWifiList!=null){mlistView.setAdapter(new MyAdapter(this,mWifiList));new Utility().setListViewHeightBasedOnChildren(mlistView);}break;default:break;}}public class MyAdapter extends BaseAdapter{LayoutInflater inflater;List<ScanResult> list;public MyAdapter(Context context, List<ScanResult> list){this.inflater=LayoutInflater.from(context);this.list=list;}@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}@SuppressLint({ "ViewHolder", "InflateParams" })@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view=null;view=inflater.inflate(R.layout.wifi_listitem, null);ScanResult scanResult = list.get(position);TextView wifi_ssid=(TextView) view.findViewById(R.id.ssid);ImageView wifi_level=(ImageView) view.findViewById(R.id.wifi_level);wifi_ssid.setText(scanResult.SSID);Log.i(TAG, "scanResult.SSID="+scanResult);level=WifiManager.calculateSignalLevel(scanResult.level,5);if(scanResult.capabilities.contains("WEP")||scanResult.capabilities.contains("PSK")||scanResult.capabilities.contains("EAP")){wifi_level.setImageResource(R.drawable.wifi_signal_lock);}else{wifi_level.setImageResource(R.drawable.wifi_signal_open);}wifi_level.setImageLevel(level);//判斷信號強度,顯示對應的指示圖標 ?return view;}}/*設置listview的高度*/public class Utility { public void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); } }//監聽wifi狀態private BroadcastReceiver mReceiver = new BroadcastReceiver (){ @Override public void onReceive(Context context, Intent intent) { ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if(wifiInfo.isConnected()){WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);String wifiSSID = wifiManager.getConnectionInfo().getSSID();Toast.makeText(context, wifiSSID+"連接成功", 1).show();} } }; }簡單講講,其實wifi開發的內容很多。這個例子首先通過mWifiManager.startScan()??和ifiManager.getScanResults();?獲取到了wifi搜索到的列表信息,然后顯示在界面的list上。點擊list的item時,輸入密碼,調用工具類的CreateWifiInfo(String?SSID,?String?Password,?int?Type)??創建一個WifiConfiguration,然后調用int?wcgID?=?mWifiManager.addNetwork(wcg);??將wifi添加到wifi列表,調用mWifiManager.enableNetwork(wcgID,?true);進行連接。具體的代碼里比較清楚,我這邊也說不明白。
android Wifi開發相關內容就講完了。
就這么簡單。
總結
以上是生活随笔為你收集整理的android Wifi开发相关内容的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 使用浏览器打开指定页面
- 下一篇: android 解决password过时