android,wifi连接功能开发,踩过的坑

前段时间做的一个小项目,是关于wifi连接功能的,在此做个小总结,借鉴了网上很多前辈的开发经验,所以这里分享一下,欢迎大家沟通交流。我们使用的google公开给第三方app使用的接口,基本全部连接功能都是使用WifiManager完成,更偏底层的WifiService等类未涉及,公司禁止上传源码,所以主要的叙述是踩坑记录和其中比较关键点的描述。

1)最关键的一个类:WifiManager
获取WifiManager时尽量使用Application,不要使用activity,有前辈叙述说这样可以避免内存泄漏。

2)获取扫描结果
isWifiEnabled()&&mWifimanager.startScan(),首先需要判断当前wifi是否开启,然后再开启扫描,注册广播,action:WifiManager.NETWORK_STATE_CHANGED_ACTION,2-3s后可以接收到wifi扫描结果,android6.0以上要求必须打开GPS才能获取扫描结果,所以没有扫描结果的基本上是因为你的GPS没有打开。

3)忘记密码
首先找到对应的ssid的WifiConfiguration(输入密码连接时代码创建),然后mWifiManager.removeNetwork(configuration.networkId) && mWifiManager.saveConfiguration(); 这里有个坑的,你只能忘记自己创建的WifiConfiguration,比如你通过手机设置中的wifi系统连接了热点iphone01,然后你想在自己的代码中去忘记热点iphone01,肯定是不可以的。
即使你想自己创建iphone01的配置文件去新建连接,也是无法连接成功的, mWifiManager.addNetwork(configuration)会返回-1,无法连接。

  1. 获取已连接wifi的ssid
    刚开始使用的方法 WifiInfo = mWifiManager.getConnectionInfo(),WifiInfo .getSSID(),可测试发现这种方式很不准确,经常wifi断开的还保留着上次的连接信息,所以这种方式无法准确的判断wifi是否已连接,我们使用了mConnectivityManager.getActiveNetworkInfo()判断当前网络是否已连接。

5)wifi扫描频率
系统wifi界面扫描频率基本是10s一次,所以在我们自己的app界面,可以设置扫描频率为10s左右一次,但注意不能过多,不然会出问题的。每次连接成功后,实际上会收到两次连接成功的广播,如果在连接成功后加入开启扫描的逻辑,要额外处理一下,不然一不小心就会出现扫描频率过多的情况。
这里一定要注意不要扫描太频繁,我刚开发时由于接收连接成功的广播有两三处,当时每次都开启扫描,导致短时间内大量调用mWifiManager,startScan方法的情况,然后把android系统 wifi 搞崩了的现象,导致系统wifi 也无法使用。虽然系统wifi崩溃是偶现,不能百分之百确认是扫描太频繁导致的,也有可能是我们的app连接和系统wifi连接冲突导致的,但关系肯定是很大的。

6)关于连接失败
通过监听网络状态变化的广播WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)来确认是否连接成功,这里网上很多,比较简单。
但连接失败就比较难确认了,可能是密码错误,也可能是热点限制连接数量,也有可能就是单纯的这此次连接没成功,密码正确连接失败的现象也会遇到呀,wifi这块本身就比较坑。
密码错误,监听广播

if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
                int res = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 123);
                SupplicantState state = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
                Log.i(TAG, "onReceive: SupplicantState--state = "+state.toString());
                if (res == WifiManager.ERROR_AUTHENTICATING && mCurrentWifiConfiguration != null) {
                    Log.i(TAG, " 密码错误 ");
                    mCurrentWifiConfiguration = null;
                    if (mWifiConnectTimeOutTimer != null && mWifiConnectTimeOutTimer.isRunning()) {
                        mWifiConnectTimeOutTimer.stop();
                    }
                    mWifiEvent.onErrorAuthenticating();
                } else if (state == SupplicantState.DISCONNECTED && mCurrentWifiConfiguration != null) {
                    Log.i(TAG, "count_disconnected = : " + count_disconnected);
                    count_disconnected++;
                    if (count_disconnected > 5) {
                        Log.i(TAG, " 网络连接失败 --count_disconnected>5");
                        mCurrentWifiConfiguration = null;
                        if (mWifiConnectTimeOutTimer != null && mWifiConnectTimeOutTimer.isRunning()) {
                            mWifiConnectTimeOutTimer.stop();
                        }
                        mWifiEvent.onConnectFail();
                    }
                }
            }

这块不插代码讲不清楚呀,代码和注释比较清晰,判断密码错误的方法是个过时的方法,不准确,经常出现密码错了但是没判断出来的情况,这里暂未找到其他更好的方法,知道的网友可以交流分享一下,万分感谢。如果判断不出来失败原因就直接归类为连接失败了,木办法,就是这么蠢。
代码中可以看到加了连接超时mWifiConnectTimeOutTimer,这个很必要的,因为会出现开始连接后,没有成功或失败的广播的现象,不能一直处于连接中吧,所以超时一定要加。
*
遗留问题:
int netId = mWifiManager.addNetwork(configuration);
偶现netId 为-1的情况,此时是无法连接热点的,只能再次输入密码连接。热点系统wifi未保存,非与系统wifi的冲突导致,一般重新打开就能解决问题,可以连接成功。网上搜到有说是WifiConfiguration构建有问题,但试了下他的还是不行,有兴趣的可以交流下。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在 Android Studio 中开发基于最新 SDK 的 Wi-Fi 连接功能,可以按照以下步骤进行: 1. 在 Android Studio 中创建一个新的项目。 2. 在 `AndroidManifest.xml` 文件中添加以下权限: ``` <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ``` 3. 在 `build.gradle` 文件中添加以下依赖项: ``` dependencies { implementation 'com.android.support:appcompat-v7:28.0.0' } ``` 4. 在 `MainActivity.java` 文件中添加以下代码: ``` public class MainActivity extends AppCompatActivity { private WifiManager wifiManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); Button connectButton = findViewById(R.id.connect_button); connectButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { connectToWifi(); } }); } private void connectToWifi() { WifiConfiguration wifiConfig = new WifiConfiguration(); wifiConfig.SSID = "\"SSID\""; wifiConfig.preSharedKey = "\"password\""; int netId = wifiManager.addNetwork(wifiConfig); wifiManager.disconnect(); wifiManager.enableNetwork(netId, true); wifiManager.reconnect(); } } ``` 5. 在 `activity_main.xml` 文件中添加一个按钮: ``` <Button android:id="@+id/connect_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Connect to Wi-Fi" /> ``` 6. 运行应用程序,击按钮连接到 Wi-Fi 网络。 在 `connectToWifi()` 方法中,我们首先创建一个新的 `WifiConfiguration` 对象,并设置 SSID 和密码。然后,我们使用 `WifiManager` 的 `addNetwork()` 方法将该配置添加到系统中。接着,我们断开当前连接并启用新的 Wi-Fi 网络。最后,我们使用 `reconnect()` 方法重新连接到新的 Wi-Fi 网络。 请注意,由于 Android 6.0 (API 级别 23)引入了运行时权限,因此您需要在运行时请求 `ACCESS_WIFI_STATE`、`CHANGE_WIFI_STATE` 和 `ACCESS_NETWORK_STATE` 权限。您可以使用以下代码示例来请求这些权限: ``` private static final int PERMISSIONS_REQUEST_CODE = 123; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_WIFI_STATE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_WIFI_STATE, Manifest.permission.CHANGE_WIFI_STATE, Manifest.permission.ACCESS_NETWORK_STATE}, PERMISSIONS_REQUEST_CODE); } else { // Permissions already granted } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSIONS_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permissions granted } } } ``` 在 `onCreate()` 方法中,我们检查是否已授予权限。如果没有授予,我们使用 `requestPermissions()` 方法请求这些权限。在 `onRequestPermissionsResult()` 方法中,我们检查请求是否成功,并在成功时执行必要的操作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值