Android WiFi开发
概述
详细
一、准备工作
开发环境:
jdk1.8
Eclipse Luna Service Release 1 (4.4.1)
运行环境:
华为荣耀6(Android4.4)、华为p9(Android7.0)
实现功能:
-
Android WiFi开发 (一)扫描、连接、信息
-
Android WiFi开发 (二)Wifi热点
二、代码结构
代码包里面,有两个部分,一个是源码,一个是V7支持包。
(源码项目)
(V7包)
三、Android WiFi开发 (一)扫描、连接、信息
1、详细讲解
在平常开发中经常会涉及到wifi相关的内容,在此将之前所用到的整理一下,以免忘记。
操作wifi的相关类,主要放在Android.net.wifi包下面。使用wifi相关方法需要申请一些权限:
ACCESS_WIFI_STATE 获取WiFi状态。
CHANGE_WIFI_STATE 改变WiFi状态。
CHANGE_WIFI_MULTICAST_STATE 改变WiFi多播状态
申请权限方式:在AndroidManifest.xml文件中填写
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
wifi相关操作所需要用到的类。
先说一下wifi的基本使用情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | 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()。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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); } } } } |
这样就可以避免出现上面的两种情况了。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | 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() { @Override public 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(){ @Override public 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(){ @Override public 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 ); } @Override public 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; } @Override public int getCount() { return list.size(); } @Override public Object getItem( int position) { return position; } @Override public long getItemId( int position) { return position; } @SuppressLint ({ "ViewHolder" , "InflateParams" }) @Override public 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(); } } }; } |
2、相关类说明补充
ScanResult类
这个类主要是通过Wifi硬件的扫描来获取一些周边的wifi热点(access point)的信息。该类主要有5个域,
打印信息如下所示:
WifiConfiguration类
通过该类获取一个wifi网络的网络配置,包括安全配置等。它包含6个子类,如下所示:
该类内容较多,不一一例举,需要用到的时候可以查Android SDK。
WifiInfo类
该类可以获得已经建立的或处于活动状态的wifi网络的状态信息。常用方法如下:
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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的状态,有整型常量表示,
四、Android WiFi开发 (二)Wifi热点
这个章节主要说一下手机开启Wifi热点。
demo的下载地址会在最下面贴出来。
1、创建WiFi热点
经测试开启wifi热点(无秘密,wpa安全类型,wpa2安全类型)都可以正常开启并使用。
需要注意的是wifi和wifi热点不能同时打开,也就是连接wifi的时候,开启热点需要先将wifi关闭才可以。
用到的主要代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | package com.vn.wifitest.utils; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiManager; import android.os.Handler; import android.util.Log; public class WifiAPUtil { private static final String TAG = "WifiAPUtil" ; public final static boolean DEBUG = true ; public static final int MESSAGE_AP_STATE_ENABLED = 1 ; public static final int MESSAGE_AP_STATE_FAILED = 2 ; //默认wifi秘密 private static final String DEFAULT_AP_PASSWORD = "12345678" ; private static WifiAPUtil sInstance; private static Handler mHandler; private static Context mContext; private WifiManager mWifiManager; //监听wifi热点的状态变化 public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED" ; public static final String EXTRA_WIFI_AP_STATE = "wifi_state" ; public static int WIFI_AP_STATE_DISABLING = 10 ; public static int WIFI_AP_STATE_DISABLED = 11 ; public static int WIFI_AP_STATE_ENABLING = 12 ; public static int WIFI_AP_STATE_ENABLED = 13 ; public static int WIFI_AP_STATE_FAILED = 14 ; public enum WifiSecurityType { WIFICIPHER_NOPASS, WIFICIPHER_WPA, WIFICIPHER_WEP, WIFICIPHER_INVALID, WIFICIPHER_WPA2 } private WifiAPUtil(Context context) { if (DEBUG) Log.d(TAG, "WifiAPUtils construct" ); mContext = context; mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); IntentFilter filter = new IntentFilter(); filter.addAction(WIFI_AP_STATE_CHANGED_ACTION); context.registerReceiver(mWifiStateBroadcastReceiver, filter); } protected void finalize() { if (DEBUG) Log.d(TAG, "finalize" ); mContext.unregisterReceiver(mWifiStateBroadcastReceiver); } public static WifiAPUtil getInstance(Context c) { if ( null == sInstance) sInstance = new WifiAPUtil(c); return sInstance; } public boolean turnOnWifiAp(String str, String password,WifiSecurityType Type) { String ssid = str; //配置热点信息。 WifiConfiguration wcfg = new WifiConfiguration(); wcfg.SSID = new String(ssid); wcfg.networkId = 1 ; wcfg.allowedAuthAlgorithms.clear(); wcfg.allowedGroupCiphers.clear(); wcfg.allowedKeyManagement.clear(); wcfg.allowedPairwiseCiphers.clear(); wcfg.allowedProtocols.clear(); if (Type == WifiSecurityType.WIFICIPHER_NOPASS) { if (DEBUG)Log.d(TAG, "wifi ap----no password" ); wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN, true ); wcfg.wepKeys[ 0 ] = "" ; wcfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); wcfg.wepTxKeyIndex = 0 ; } else if (Type == WifiSecurityType.WIFICIPHER_WPA) { if (DEBUG)Log.d(TAG, "wifi ap----wpa" ); //密码至少8位,否则使用默认密码 if ( null != password && password.length() >= 8 ){ wcfg.preSharedKey = password; } else { wcfg.preSharedKey = DEFAULT_AP_PASSWORD; } wcfg.hiddenSSID = false ; wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); wcfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); //wcfg.allowedKeyManagement.set(4); wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); wcfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA); wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); } else if (Type == WifiSecurityType.WIFICIPHER_WPA2) { if (DEBUG)Log.d(TAG, "wifi ap---- wpa2" ); //密码至少8位,否则使用默认密码 if ( null != password && password.length() >= 8 ){ wcfg.preSharedKey = password; } else { wcfg.preSharedKey = DEFAULT_AP_PASSWORD; } wcfg.hiddenSSID = true ; wcfg.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); wcfg.allowedKeyManagement.set( 4 ); //wcfg.allowedKeyManagement.set(4); wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); wcfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA); wcfg.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); wcfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); } try { Method method = mWifiManager.getClass().getMethod( "setWifiApConfiguration" , wcfg.getClass()); Boolean rt = (Boolean)method.invoke(mWifiManager, wcfg); if (DEBUG) Log.d(TAG, " rt = " + rt); } catch (NoSuchMethodException e) { Log.e(TAG, e.getMessage()); } catch (IllegalArgumentException e) { Log.e(TAG, e.getMessage()); } catch (IllegalAccessException e) { Log.e(TAG, e.getMessage()); } catch (InvocationTargetException e) { Log.e(TAG, e.getMessage()); } return setWifiApEnabled(); } //获取热点状态 public int getWifiAPState() { int state = - 1 ; try { Method method2 = mWifiManager.getClass().getMethod( "getWifiApState" ); state = (Integer) method2.invoke(mWifiManager); } catch (Exception e) { Log.e(TAG, e.getMessage()); } if (DEBUG)Log.i( "WifiAP" , "getWifiAPState.state " + state); return state; } private boolean setWifiApEnabled() { //开启wifi热点需要关闭wifi while (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_DISABLED){ mWifiManager.setWifiEnabled( false ); try { Thread.sleep( 200 ); } catch (Exception e) { Log.e(TAG, e.getMessage()); return false ; } } // 确保wifi 热点关闭。 while (getWifiAPState() != WIFI_AP_STATE_DISABLED){ try { Method method1 = mWifiManager.getClass().getMethod( "setWifiApEnabled" , WifiConfiguration. class , boolean . class ); method1.invoke(mWifiManager, null , false ); Thread.sleep( 200 ); } catch (Exception e) { Log.e(TAG, e.getMessage()); return false ; } } //开启wifi热点 try { Method method1 = mWifiManager.getClass().getMethod( "setWifiApEnabled" , WifiConfiguration. class , boolean . class ); method1.invoke(mWifiManager, null , true ); Thread.sleep( 200 ); } catch (Exception e) { Log.e(TAG, e.getMessage()); return false ; } return true ; } //关闭WiFi热点 public void closeWifiAp() { if (getWifiAPState() != WIFI_AP_STATE_DISABLED) { try { Method method = mWifiManager.getClass().getMethod( "getWifiApConfiguration" ); method.setAccessible( true ); WifiConfiguration config = (WifiConfiguration) method.invoke(mWifiManager); Method method2 = mWifiManager.getClass().getMethod( "setWifiApEnabled" , WifiConfiguration. class , boolean . class ); method2.invoke(mWifiManager, config, false ); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } public void regitsterHandler(Handler handler){ mHandler = handler; } public void unregitsterHandler(){ mHandler = null ; } //监听wifi热点状态变化 private BroadcastReceiver mWifiStateBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG)Log.i(TAG, "WifiAPUtils onReceive: " +intent.getAction()); if (WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) { int cstate = intent.getIntExtra(EXTRA_WIFI_AP_STATE, - 1 ); if (cstate == WIFI_AP_STATE_ENABLED) { if (mHandler != null ){ mHandler.sendEmptyMessage(MESSAGE_AP_STATE_ENABLED); } } if (cstate == WIFI_AP_STATE_DISABLED || cstate == WIFI_AP_STATE_FAILED) { if (mHandler != null ) mHandler.sendEmptyMessage(MESSAGE_AP_STATE_FAILED); } } } }; //获取热点ssid public String getValidApSsid() { try { Method method = mWifiManager.getClass().getMethod( "getWifiApConfiguration" ); WifiConfiguration configuration = (WifiConfiguration)method.invoke(mWifiManager); return configuration.SSID; } catch (Exception e) { Log.e(TAG, e.getMessage()); return null ; } } //获取热点密码 public String getValidPassword(){ try { Method method = mWifiManager.getClass().getMethod( "getWifiApConfiguration" ); WifiConfiguration configuration = (WifiConfiguration)method.invoke(mWifiManager); return configuration.preSharedKey; } catch (Exception e) { Log.e(TAG, e.getMessage()); return null ; } } //获取热点安全类型 public int getValidSecurity(){ WifiConfiguration configuration; try { Method method = mWifiManager.getClass().getMethod( "getWifiApConfiguration" ); configuration = (WifiConfiguration)method.invoke(mWifiManager); } catch (Exception e) { Log.e(TAG, e.getMessage()); return WifiSecurityType.WIFICIPHER_INVALID.ordinal(); } if (DEBUG)Log.i(TAG, "getSecurity security=" +configuration.allowedKeyManagement); if (configuration.allowedKeyManagement.get(KeyMgmt.NONE)) { return WifiSecurityType.WIFICIPHER_NOPASS.ordinal(); } else if (configuration.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { return WifiSecurityType.WIFICIPHER_WPA.ordinal(); } else if (configuration.allowedKeyManagement.get( 4 )) { //4 means WPA2_PSK return WifiSecurityType.WIFICIPHER_WPA2.ordinal(); } return WifiSecurityType.WIFICIPHER_INVALID.ordinal(); } } |
使用方法:
使用方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //初始化WifiAPUtil类 WifiAPUtil.getInstance(getApplicationContext()) //注册handler WifiAPUtil.getInstance( this ).regitsterHandler(mHandler); //接收message,做处理 private Handler mHandler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what) { case WifiAPUtil.MESSAGE_AP_STATE_ENABLED: String ssid = WifiAPUtil.getInstance(WifiApActivity. this ).getValidApSsid(); String pw = WifiAPUtil.getInstance(WifiApActivity. this ).getValidPassword(); int security = WifiAPUtil.getInstance(WifiApActivity. this ).getValidSecurity(); mWifiApState.setText( "wifi热点开启成功" + "\n" + "SSID = " +ssid+ "\n" + "Password = " +pw + "\n" + "Security = " +security); break ; case WifiAPUtil.MESSAGE_AP_STATE_FAILED: mWifiApState.setText( "wifi热点关闭" ); break ; default : break ; } } }; |
在activity销毁的时候
1 2 3 4 5 | @Override protected void onDestroy() { super .onDestroy(); WifiAPUtil.getInstance( this ).unregitsterHandler(); } |
添加点击事件
1 2 | //开启wifi热点 WifiAPUtil.getInstance(WifiApActivity. this ).turnOnWifiAp(ssid, password, mWifiType); |
1 2 | //关闭wifi热点 WifiAPUtil.getInstance(WifiApActivity. this ).closeWifiAp(); |
2、监听热点的状态
当wifi热点状态发送变化,系统会发送广播 Android.net.wifi.WIFI_AP_STATE_CHANGED,所以我们只要注册监听这个广播就可以了。
wifi ap状态值。
1 2 3 4 5 6 | public static final String EXTRA_WIFI_AP_STATE = "wifi_state" ; public static int WIFI_AP_STATE_DISABLING = 10 ; public static int WIFI_AP_STATE_DISABLED = 11 ; public static int WIFI_AP_STATE_ENABLING = 12 ; public static int WIFI_AP_STATE_ENABLED = 13 ; public static int WIFI_AP_STATE_FAILED = 14 ; |
动态注册
1 2 3 4 5 | public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED" ; //注册广播接收者 IntentFilter filter = new IntentFilter(); filter.addAction(WIFI_AP_STATE_CHANGED_ACTION); context.registerReceiver(mWifiStateBroadcastReceiver, filter); |
广播接收者
通过监听wifiap状态的变化,发送消息给相关activity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //监听wifi热点状态变化 private BroadcastReceiver mWifiStateBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG)Log.i(TAG, "WifiAPUtils onReceive: " +intent.getAction()); if (WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) { int cstate = intent.getIntExtra(EXTRA_WIFI_AP_STATE, - 1 ); if (cstate == WIFI_AP_STATE_ENABLED) { if (mHandler != null ){ mHandler.sendEmptyMessage(MESSAGE_AP_STATE_ENABLED); } } if (cstate == WIFI_AP_STATE_DISABLED || cstate == WIFI_AP_STATE_FAILED) { if (mHandler != null ) mHandler.sendEmptyMessage(MESSAGE_AP_STATE_FAILED); } } } }; |
3、遗留问题
在配置wificonfiguration的时候有过属性是hiddenSSID,这个是设置wifi热点AP是否隐藏的,
但是设置wcfg.hiddenSSID = true或false并没有发现有什么不同,按理说设置为true,ssid隐藏应该搜索不到这个热点,
但是都可以搜索到。还请知道的可以留言指教,十分感谢。
之前有朋友说5.0系统的开启热点有问题,我这里没有5.0的手机,使用华为p9Android6.0手机测试确实开启不了热点,需要添加write_settings,添加上此权限就可以成功开启了。
五、其他补充
没有
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?