Android WiFi开发

概述

介绍Android WiFi的扫描、连接、信息、以及WiFi热点等等的实现,并用代码实现。

详细

一、准备工作

开发环境:

jdk1.8

Eclipse Luna Service Release 1 (4.4.1)

运行环境:

华为荣耀6(Android4.4)、华为p9(Android7.0)

实现功能:

  • Android WiFi开发 (一)扫描、连接、信息

  • Android WiFi开发 (二)Wifi热点

二、代码结构

代码包里面,有两个部分,一个是源码,一个是V7支持包。

image.png

(源码项目)

image.png

(V7包)

三、Android WiFi开发 (一)扫描、连接、信息

1、详细讲解

在平常开发中经常会涉及到wifi相关的内容,在此将之前所用到的整理一下,以免忘记。

操作wifi的相关类,主要放在Android.net.wifi包下面。使用wifi相关方法需要申请一些权限:

image.png

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相关操作所需要用到的类。

image.png

先说一下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;     
    }  
}

如图所示:

image.png

俩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); 
        }  
    }  
    }  
}

这样就可以避免出现上面的两种情况了。

image.png

代码:

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类

image.png

这个类主要是通过Wifi硬件的扫描来获取一些周边的wifi热点(access point)的信息。该类主要有5个域,

image.png

打印信息如下所示:

image.png

WifiConfiguration类

通过该类获取一个wifi网络的网络配置,包括安全配置等。它包含6个子类,如下所示:

image.png

该类内容较多,不一一例举,需要用到的时候可以查Android SDK。

WifiInfo类

image.png

该类可以获得已经建立的或处于活动状态的wifi网络的状态信息。常用方法如下:

image.png

image.png

代码:

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连接,定义了许多常量和方法,这里就不一一说了。

常用方法。

20160304133401314.jpg

需要指出的是getWifiState()方法是反悔wifi的状态,有整型常量表示,

image.png

四、Android WiFi开发 (二)Wifi热点

这个章节主要说一下手机开启Wifi热点。

demo的下载地址会在最下面贴出来。

image.png

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,添加上此权限就可以成功开启了。

五、其他补充

没有

 

 

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

posted on   demo例子集  阅读(22910)  评论(0编辑  收藏  举报

(评论功能已被禁用)
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示