Android开发实践:WIFI连接功能的封装

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介:

与WIFI扫描类似,WIFI的连接同样是一个耗时的过程,所以需要放到线程中执行,通过回调来通知调用者连接结果。该回调接口的定义如下:

1
2
3
public  interface  WifiConnectListener {
     public  void  OnWifiConnectCompleted(  boolean  isConnected );
}


   从Android的WIFI Setting可以看出,一般添加一个新的WIFI连接,需要给出三个信息,一个是WIFI的SSID,一个是WIFI的密码,另一个是WIFI的加密类型,不同的加密方式,连接时程序中的配置是不同的,这里定义一个枚举,给出四种常见的加密类型:


1
2
3
public  enum  SecurityMode {
     OPEN, WEP, WPA, WPA2
}


   Android的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
package  com.example.testwifi;
                      
import  java.util.List;
import  java.util.concurrent.TimeUnit;
import  java.util.concurrent.locks.Condition;
import  java.util.concurrent.locks.Lock;
import  java.util.concurrent.locks.ReentrantLock;
import  android.content.BroadcastReceiver;
import  android.content.Context;
import  android.content.Intent;
import  android.content.IntentFilter;
import  android.net.wifi.SupplicantState;
import  android.net.wifi.WifiConfiguration;
import  android.net.wifi.WifiInfo;
import  android.net.wifi.WifiManager;
                                                                                                                   
public  class  WifiConnector {
                                                                                                         
     private  static  final  int  WIFI_CONNECT_TIMEOUT =  20 //连接WIFI的超时时间
                                                                                                         
     private  Context mContext;
     private  WifiManager mWifiManager;           
     private  Lock mLock;
     private  Condition mCondition;
     private  WiFiConncetReceiver mWifiConnectReceiver;
     private  WifiConnectListener mWifiConnectListener;
     private  boolean  mIsConnnected =  false ;
     private  int  mNetworkID = - 1 ;
               
     //网络加密模式
     public  enum  SecurityMode {
         OPEN, WEP, WPA, WPA2
     }
                       
    //通知连接结果的监听接口
     public  interface  WifiConnectListener {
         public  void  OnWifiConnectCompleted(  boolean  isConnected );
     }
                         
     public  WifiConnector( Context context , WifiConnectListener listener ) {
                                                                                                             
         mContext = context;   
                                                                                                             
         mLock =  new  ReentrantLock();
         mCondition = mLock.newCondition();
         mWifiManager=(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);   
                                                                                                             
         mWifiConnectReceiver =  new  WiFiConncetReceiver();  
                                                                                                             
         mWifiConnectListener = listener;
     }
                                                                                                                 
     public  void  connect(  final  String ssid,  final  String password,  final  SecurityMode mode ) {
                                                                                                             
         new  Thread( new  Runnable() {
                                                                                                                 
             @Override
             public  void  run() {
                                                                                                                     
                 //如果WIFI没有打开,则打开WIFI
                 if ( !mWifiManager.isWifiEnabled() ) {
                     mWifiManager.setWifiEnabled( true );
                 }
                                                                                                                             
                 //注册连接结果监听对象
                 mContext.registerReceiver(mWifiConnectReceiver,  new  IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
                                                                                                                     
                 //连接指定SSID
                 if ( !onConnect(ssid,password,mode) ) {
                     mWifiConnectListener.OnWifiConnectCompleted( false );
                 }
                 else  {
                     mWifiConnectListener.OnWifiConnectCompleted( true );
                 }
                                                                                                                     
                 //删除注册的监听类对象
                 mContext.unregisterReceiver(mWifiConnectReceiver);         
             }
         }).start();            
     }
                                                                                                         
     protected  boolean  onConnect( String ssid, String password, SecurityMode mode ) {
                                                                                                             
         //添加新的网络配置
         WifiConfiguration cfg =  new  WifiConfiguration();
         cfg.SSID =  "\""  + ssid +  "\"" ;
         if ( password != null  && ! "" .equals(password) ) {
             //这里比较关键,如果是WEP加密方式的网络,密码需要放到cfg.wepKeys[0]里面
             if ( mode == SecurityMode.WEP ) {
                 cfg.wepKeys[ 0 ]   =  "\""  + password +  "\"" ;
                 cfg.wepTxKeyIndex =  0 ;
             }
             else  {
                 cfg.preSharedKey =  "\""  + password +  "\"" ;
             }                  
         }
         cfg.status = WifiConfiguration.Status.ENABLED;
          
         //添加网络配置
         mNetworkID = mWifiManager.addNetwork(cfg);
                                                                                                             
         mLock.lock();
                                                                                  
         mIsConnnected =  false ;
             
         //连接该网络
         if ( !mWifiManager.enableNetwork(mNetworkID ,  true ) ) {
             mLock.unlock();
             return  false ;
         }
                                                                                                             
         try  {
             //等待连接结果
             mCondition.await(WIFI_CONNECT_TIMEOUT, TimeUnit.SECONDS);
         }
         catch  (InterruptedException e) {
             e.printStackTrace();       
         }
                                                                                                             
         mLock.unlock();
                                                                                                             
         return  mIsConnnected;
     }  
                                                                                                         
     //监听系统的WIFI连接消息
     protected  class  WiFiConncetReceiver  extends  BroadcastReceiver {
                                                                                                                     
         @Override
         public  void  onReceive(Context context, Intent intent) {
                                                                                                                 
             if  (!WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(intent.getAction())) {
                 return ;
             }          
                                                                                                                 
             mLock.lock();
                                                                                                                 
             WifiInfo info = mWifiManager.getConnectionInfo();
             if  ( info.getNetworkId()==mNetworkID && info.getSupplicantState() == SupplicantState.COMPLETED ) {
                 mIsConnnected =  true ;
                 mCondition.signalAll();    
             }
                                                                                                                 
             mLock.unlock();
         }
     }
}

   与WIFI扫描的封装代码类似,这里也用到了Lock和Condition,就是为了阻塞地等待WIFI连接的结果,保证正确的registerReceiver和unregisterReceiver网络连接状态监听对象,同时,设置了WIFI连接超时,防止由于WIFI模块的问题导致界面收不到回调而长时间“卡死”。


   另外,AndroidManifest.xml文件中记得添加权限支持哦:


1
2
3
<uses-permission android:name= "android.permission.CHANGE_WIFI_STATE" ></uses-permission>
<uses-permission android:name= "android.permission.ACCESS_WIFI_STATE" ></uses-permission>
<uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE" ></uses-permission>


本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1410080,如需转载请自行联系原作者

相关文章
|
3月前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的海洋中,自定义控件是那片璀璨的星辰。它不仅让应用界面设计变得丰富多彩,还提升了用户体验。本文将带你探索自定义控件的核心概念、实现过程以及优化技巧,让你的应用在众多竞争者中脱颖而出。
|
3月前
|
传感器 数据采集 移动开发
基于STM32的智能手环wifi连接手机APP(下)
基于STM32的智能手环wifi连接手机APP(下)
148 0
|
4月前
|
安全 Android开发 Kotlin
Android经典实战之SurfaceView原理和实践
本文介绍了 `SurfaceView` 这一强大的 UI 组件,尤其适合高性能绘制任务,如视频播放和游戏。文章详细讲解了 `SurfaceView` 的原理、与 `Surface` 类的关系及其实现示例,并强调了使用时需注意的线程安全、生命周期管理和性能优化等问题。
203 8
|
1月前
|
搜索推荐 Android开发 开发者
安卓应用开发中的自定义控件实践
在安卓应用开发的广阔天地中,自定义控件如同璀璨的星辰,点亮了用户界面设计的夜空。它们不仅丰富了交互体验,更赋予了应用独特的个性。本文将带你领略自定义控件的魅力,从基础概念到实际应用,一步步揭示其背后的原理与技术细节。我们将通过一个简单的例子——打造一个具有独特动画效果的按钮,来展现自定义控件的强大功能和灵活性。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇通往更高阶UI设计的大门。
|
3月前
|
Android开发
Android开发表情emoji功能开发
本文介绍了一种在Android应用中实现emoji表情功能的方法,通过将图片与表情字符对应,实现在`TextView`中的正常显示。示例代码展示了如何使用自定义适配器加载emoji表情,并在编辑框中输入或删除表情。项目包含完整的源码结构,可作为开发参考。视频演示和源码详情见文章内链接。
84 4
Android开发表情emoji功能开发
|
3月前
|
安全 Android开发 iOS开发
Android vs iOS:探索移动操作系统的设计与功能差异###
【10月更文挑战第20天】 本文深入分析了Android和iOS两个主流移动操作系统在设计哲学、用户体验、技术架构等方面的显著差异。通过对比,揭示了这两种系统各自的独特优势与局限性,并探讨了它们如何塑造了我们的数字生活方式。无论你是开发者还是普通用户,理解这些差异都有助于更好地选择和使用你的移动设备。 ###
66 3
|
2月前
|
前端开发 Android开发 UED
安卓应用开发中的自定义控件实践
【10月更文挑战第35天】在移动应用开发中,自定义控件是提升用户体验、增强界面表现力的重要手段。本文将通过一个安卓自定义控件的创建过程,展示如何从零开始构建一个具有交互功能的自定义视图。我们将探索关键概念和步骤,包括继承View类、处理测量与布局、绘制以及事件处理。最终,我们将实现一个简单的圆形进度条,并分析其性能优化。
|
3月前
|
前端开发 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的世界里,自定义控件如同画家的画笔,能够绘制出独一无二的界面。通过掌握自定义控件的绘制技巧,开发者可以突破系统提供的界面元素限制,创造出既符合品牌形象又提供卓越用户体验的应用。本文将引导你了解自定义控件的核心概念,并通过一个简单的例子展示如何实现一个基本的自定义控件,让你的安卓应用在视觉和交互上与众不同。
|
3月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
57 6
|
4月前
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
169 3