Android WiFi开发

发布时间:2017-07-19
技术:Android4.4+jdk1.8

概述

介绍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的基本使用情况。

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()。

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

代码:

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

代码:

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关闭才可以。

用到的主要代码:

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

使用方法:

使用方法:

//初始化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销毁的时候

@Override  
protected void onDestroy() {  
    super.onDestroy();  
    WifiAPUtil.getInstance(this).unregitsterHandler();  
}

添加点击事件

//开启wifi热点  
WifiAPUtil.getInstance(WifiApActivity.this).turnOnWifiAp(ssid, password, mWifiType);
//关闭wifi热点  
WifiAPUtil.getInstance(WifiApActivity.this).closeWifiAp();

2、监听热点的状态

当wifi热点状态发送变化,系统会发送广播 Android.net.wifi.WIFI_AP_STATE_CHANGED,所以我们只要注册监听这个广播就可以了。

wifi ap状态值。

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 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

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

五、其他补充

没有



本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢