Android连接指定Wifi的方法实例代码
发布时间 - 2026-01-11 00:17:56 点击率:次本篇文章主要记录一下Android中打开Wifi、获取Wifi接入点信息及连接指接入点的方法。

自己写的demo主要用于测试接口的基本功能,因此界面及底层逻辑比较粗糙。
demo的整体界面如下所示:
上图中的OPEN按键负责开启Wifi;
GET按键负责获取扫描到的接入点信息。
当获取到接入点信息后,我选取了其中的名称及信号强度,以列表的形式显示在主界面下方,如下图:
当点击列表中的Item时,就会去连接对应的接入点。
自己的逻辑比较简单,测试时的代码,假定连接的是不许要密码或密码已知的接入点。
demo的布局文件就不介绍了,就是Button和RecyclerView。
主要记录一下,使用到的核心代码。
....................
//Open按键点击后的逻辑
mOpenWifiButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//WifiManager的isWifiEnabled接口,用于判断Wifi开关是否已经开启
if (!mWifiManager.isWifiEnabled()) {
//setWifiEnabled接口用于开启Wifi
mWifiManager.setWifiEnabled(true);
mMainHandler.post(mMainRunnable);
}
}
});
....................
mMainRunnable的代码如下,主要用于判断Wifi是否开启成功。
................
private Runnable mMainRunnable = new Runnable() {
@Override
public void run() {
if (mWifiManager.isWifiEnabled()) {
//开启成功后,使能Get按键
mGetWifiInfoButton.setEnabled(true);
} else {
mMainHandler.postDelayed(mMainRunnable, 1000);
}
}
};
..............
这部分代码,主要使用了WifiManager的公有接口,开启Wifi开关及判断开启状态。
这部分操作需要的权限是:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
Get按键被点击后,对应的代码如下:
.................
mGetWifiInfoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mWifiManager.isWifiEnabled()) {
//getScanResults接口将返回List<ScanResult>
//ScanResult中保留了每个接入点的基本信息
mScanResultList = mWifiManager.getScanResults();
//多个接入点可能携带相同的信息,形成一个整体的Wifi覆盖网络
//因此,筛除一些冗余信息
sortList(mScanResultList);
//我使用的是RecyclerView,得到数据后,刷新界面进行显示
mWifiInfoRecyclerView.getAdapter().notifyDataSetChanged();
}
}
});
.................
上面这部分代码也比较简单,主要利用WifiManager的getScanResults接口,获取终端探索到的接入点信息。
其中,sortList的代码如下:
..............
private void sortList(List<ScanResult> list) {
TreeMap<String, ScanResult> map = new TreeMap<>();
//demo中仅按照SSID进行筛选
//实际使用时,还可以参考信号强度等条件
for (ScanResult scanResult : list) {
map.put(scanResult.SSID, scanResult);
}
list.clear();
list.addAll(map.values());
}
.............
这部分代码唯一需要注意的地方是,需要申明权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
同时,在高版本中还需要主动获取运行时权限。
权限的要求,是由WifiServiceImpl的实现决定的,我们以Android 7.0为例,看看对应的代码:
public List<ScanResult> getScanResults(String callingPackage) {
//这里要求的是ACCESS_WIFI_STATE
enforceAccessPermission();
............
try {
...........
if (!canReadPeerMacAddresses && !isActiveNetworkScorer
//在checkCallerCanAccessScanResults中检查了ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION
//如果没有这两个权限,就会返回一个empty List
&& !checkCallerCanAccessScanResults(callingPackage, uid)) {
return new ArrayList<ScanResult>();
}
...........
} fianlly {
..........
}
}
获取到信息后,就可以显示和点击列表中的Item了。
由于自己使用的是RecyclerView,因此这部分工作全部交给了对应ViewHolder:
...............
private class ScanResultViewHolder extends RecyclerView.ViewHolder {
private View mView;
private TextView mWifiName;
private TextView mWifiLevel;
ScanResultViewHolder(View itemView) {
super(itemView);
mView = itemView;
mWifiName = (TextView) itemView.findViewById(R.id.ssid);
mWifiLevel = (TextView) itemView.findViewById(R.id.level);
}
void bindScanResult(final ScanResult scanResult) {
//将接入点的名称和强度显示到界面上
mWifiName.setText(
getString(R.string.scan_wifi_name, "" + scanResult.SSID));
mWifiLevel.setText(
getString(R.string.scan_wifi_level, "" + scanResult.level));
//点击Item后,就连接对应的接入点
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//createWifiConfig主要用于构建一个WifiConfiguration,代码中的例子主要用于连接不需要密码的Wifi
//WifiManager的addNetwork接口,传入WifiConfiguration后,得到对应的NetworkId
int netId = mWifiManager.addNetwork(createWifiConfig(scanResult.SSID, "", WIFICIPHER_NOPASS));
//WifiManager的enableNetwork接口,就可以连接到netId对应的wifi了
//其中boolean参数,主要用于指定是否需要断开其它Wifi网络
boolean enable = mWifiManager.enableNetwork(netId, true);
Log.d("ZJTest", "enable: " + enable);
//可选操作,让Wifi重新连接最近使用过的接入点
//如果上文的enableNetwork成功,那么reconnect同样连接netId对应的网络
//若失败,则连接之前成功过的网络
boolean reconnect = mWifiManager.reconnect();
Log.d("ZJTest", "reconnect: " + reconnect);
}
});
}
}
.................
以上就是连接指定Wifi的基本套路,从代码中容易看出,关键问题是如何创建出有效的WifiConfiguration。
自己测试时,初始创建WifiConfiguration失败,手机怎么都没法连接到热点上,后来修改后,基本功能终于能够实现:
....................
private static final int WIFICIPHER_NOPASS = 0;
private static final int WIFICIPHER_WEP = 1;
private static final int WIFICIPHER_WPA = 2;
private WifiConfiguration createWifiConfig(String ssid, String password, int type) {
//初始化WifiConfiguration
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
//指定对应的SSID
config.SSID = "\"" + ssid + "\"";
//如果之前有类似的配置
WifiConfiguration tempConfig = isExist(ssid);
if(tempConfig != null) {
//则清除旧有配置
mWifiManager.removeNetwork(tempConfig.networkId);
}
//不需要密码的场景
if(type == WIFICIPHER_NOPASS) {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
//以WEP加密的场景
} else if(type == WIFICIPHER_WEP) {
config.hiddenSSID = true;
config.wepKeys[0]= "\""+password+"\"";
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
//以WPA加密的场景,自己测试时,发现热点以WPA2建立时,同样可以用这种配置连接
} else if(type == 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.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.status = WifiConfiguration.Status.ENABLED;
}
return config;
}
.................
private WifiConfiguration isExist(String ssid) {
List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
for (WifiConfiguration config : configs) {
if (config.SSID.equals("\""+ssid+"\"")) {
return config;
}
}
return null;
}
.................
自己写完demo后,以一个手机建立热点,分别测试了有密码和无密码的场景(对应的,需要修改createWifiConfig的传入参数)。
发现demo运行的手机在两种场景下,均能够连接到指定热点。
Demo地址如下:
https://github.com/ZhangJianIsAStark/Demos/tree/master/wifitest
在本文的最后,补充一下终端作为热点时的接口。
public boolean isWifiApEnabled()
具有@SystemApi、@hide注解的公有接口,判断手机的热点是否开启。
在Android 5.1之前,这个接口没有@SystemApi注解,
于是有很多代码会利用Java发射机制,获取该方法并判断手机热点是否开启。
现在那些老代码已经没法使用了。
现在的做法(以5.1以上为例),应该利用广播接收器监听WifiManager中定义的WIFI_AP_STATE_CHANGED_ACTION。
注意到该Action也有@SystemApi注解,所以要直接监听对应的字符串,示例如下(上面链接中的demo也有涉及):
...................
private BroadcastReceiver mBroadcastReceiver;
private void registerBroadcastReceiver() {
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//收到广播后,利用"wifi_state"的字段,得到AP的状态
int state = intent.getIntExtra("wifi_state", 11);
Log.d("ZJTest", "AP state: " + state);
}
};
IntentFilter intentFilter = new IntentFilter();
//添加Action对应的字符信息
intentFilter.addAction("android.net.wifi.WIFI_AP_STATE_CHANGED");
this.registerReceiver(mBroadcastReceiver, intentFilter);
}
.........
private void unregisterBroadcastReceiver() {
this.unregisterReceiver(mBroadcastReceiver);
}
..........
我暂时没有深究Wifi模块开启AP的流程。
不过从自己的测试结果来看,Wifi开启或关闭AP时,推测发送的应该是Sticky类型的广播。
于是,只要APK注册了广播监听器,立马就会得到回复,明白当前AP的状态。
例如,我在开启AP后,再打开自己的测试Demo,立马会收到如下信息:
//对应WIFI_AP_STATE_ENABLED,定义于WifiManager中,@SystemApi 02-20 17:48:52.470 12773-12773/? D/ZJTest: AP state: 13
手动关闭AP后可以得到如下结果:
//WIFI_AP_STATE_DISABLING 02-20 17:49:35.803 12773-12773/stark.a.is.zhang.wifitest D/ZJTest: AP state: 10 //WIFI_AP_STATE_DISABLED 02-20 17:49:36.960 12773-12773/stark.a.is.zhang.wifitest D/ZJTest: AP state: 11
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) public WifiConfiguration getWifiApConfiguration()
@SystemApi,设置和获取Wifi-AP的配置信息。
可以看出不论手机作为AP还是STA,在Framework中均利用WifiConfiguration抽象对应的配置信息,包括鉴权算法、密码、SSID、协议等。
这种设计是符合802.11协议精神的,毕竟在物理设备的角度上,AP和STA是完全对等的。只不过在实际情况中,根据各自的需求,特质化了一些组件。
实际上从底层协议来看,仅在传输这个角度上,AP和STA的主要区别仅在于收到数据帧后的处理流程不同。AP收到数据帧后,发现目的地址不是自己,就会进入转发流程;而STA可能就直接丢弃该数据帧了。当然如果从控制的角度来看,即考虑通信信令,AP和STA还是主从的关系。
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)
@SystemApi,改变Wifi-AP的开关状态。开启的AP,将使用参数定义的WifiConfiguration信息。
可以看出,手机热点对应接口全部变成了SystemApi,因此在android的高版本上,应用基本上是无法再操作热点了。
以上所述是小编给大家介绍的Android连接指定Wifi的方法实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
# android
# 连接指定wifi
# 连接wifi
# Android 通过代码设置、打开wifi热点及热点连接的实现代码
# Android编程实现wifi扫描及连接的方法
# Android设备之间通过Wifi通信的示例代码
# 解决Android 6.0获取wifi Mac地址为02:00:00:00:00:00问题
# Android开发实现在Wifi下获取本地IP地址的方法
# Android通过命令连接wifi的方法(解决usb不能用问题)
# 接入点
# 的是
# 这部
# 自己的
# 主要用于
# 就会
# 连接到
# 也有
# 不需要
# 为例
# 可以看出
# 小编
# 就可以
# 使用了
# 我在
# 还可以
# 多个
# 在此
# 有很多
# 就不
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
微信小程序 canvas开发实例及注意事项
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
java ZXing生成二维码及条码实例分享
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】
5种Android数据存储方式汇总
如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)
如何生成腾讯云建站专用兑换码?
Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能
Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧
动图在线制作网站有哪些,滑动动图图集怎么做?
Laravel如何使用Vite进行前端资源打包?(配置示例)
Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南
如何选择PHP开源工具快速搭建网站?
Laravel事件和监听器如何实现_Laravel Events & Listeners解耦应用的实战教程
重庆市网站制作公司,重庆招聘网站哪个好?
成都网站制作公司哪家好,四川省职工服务网是做什么用?
,网页ppt怎么弄成自己的ppt?
Laravel安装步骤详细教程_Laravel环境搭建指南
HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】
Python图片处理进阶教程_Pillow滤镜与图像增强
香港服务器建站指南:免备案优势与SEO优化技巧全解析
Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】
如何制作一个表白网站视频,关于勇敢表白的小标题?
原生JS获取元素集合的子元素宽度实例
如何用花生壳三步快速搭建专属网站?
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
网站建设要注意的标准 促进网站用户好感度!
详解Oracle修改字段类型方法总结
Thinkphp 中 distinct 的用法解析
如何有效防御Web建站篡改攻击?
java获取注册ip实例
Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用
济南网站建设制作公司,室内设计网站一般都有哪些功能?
Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势
三星网站视频制作教程下载,三星w23网页如何全屏?
如何解决hover在ie6中的兼容性问题
iOS正则表达式验证手机号、邮箱、身份证号等
php8.4header发送头信息失败怎么办_php8.4header函数问题解决【解答】
javascript中对象的定义、使用以及对象和原型链操作小结
Laravel如何实现全文搜索功能?(Scout和Algolia示例)
网站制作软件免费下载安装,有哪些免费下载的软件网站?
Laravel如何使用Passport实现OAuth2?(完整配置步骤)
如何快速搭建个人网站并优化SEO?
高性价比服务器租赁——企业级配置与24小时运维服务
网站制作企业,网站的banner和导航栏是指什么?
如何快速查询网站的真实建站时间?
如何在IIS7上新建站点并设置安全权限?
如何在阿里云部署织梦网站?
Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID
python中快速进行多个字符替换的方法小结

