Android WiFi开发

技术:Android4.4+jdk1.8

运行环境:Android4.4、Android7.0 

概述

介绍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(00);   

                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.classboolean.class);  

            method1.invoke(mWifiManager, nullfalse);  

           

                Thread.sleep(200);  

            catch (Exception e) {  

                Log.e(TAG, e.getMessage());  

                    return false;  

            }  

        }  

           

        //开启wifi热点  

        try {  

        Method method1 = mWifiManager.getClass().getMethod("setWifiApEnabled",  

                       WifiConfiguration.classboolean.class);  

        method1.invoke(mWifiManager, nulltrue);         

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

五、其他补充

没有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>