zoukankan      html  css  js  c++  java
  • 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的基本使用情况。

    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()+"
    "  
                    +"getBSSID()="+mWifiInfo.getBSSID()+"
    "  
                    +"getHiddenSSID()="+mWifiInfo.getHiddenSSID()+"
    "  
                    +"getLinkSpeed()="+mWifiInfo.getLinkSpeed()+"
    "  
                    +"getMacAddress()="+mWifiInfo.getMacAddress()+"
    "  
                    +"getNetworkId()="+mWifiInfo.getNetworkId()+"
    "  
                    +"getRssi()="+mWifiInfo.getRssi()+"
    "  
                    +"getSupplicantState()="+mWifiInfo.getSupplicantState()+"
    "  
                    +"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热点开启成功"+"
    "  
                            +"SSID = "+ssid+"
    "  
                            +"Password = "+pw +"
    "  
                            +"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,添加上此权限就可以成功开启了。

    五、其他补充

    没有

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

  • 相关阅读:
    CSRF攻击与防御
    nmap报错: Failed to open device ethxxx
    谷歌黑客语法(google hacking)让你的搜索更精准有效
    查看CPU相关信息
    使用fiddler抓取jmeter发送的请求
    20191129字符串对齐方法
    20191126拼接字符串
    robotframework 模拟滚动鼠标到底部
    SQL中的左连接与右连接,内连接有什么区别
    robotframework 获取坐标
  • 原文地址:https://www.cnblogs.com/demodashi/p/8481645.html
Copyright © 2011-2022 走看看