Android无线Wifi开发

来源:互联网 发布:物理补课软件 编辑:程序博客网 时间:2024/05/16 10:15

一.Wife的基础知识

      WIFI就是一种无线联网技术,常见的是使用无线路由器。那么在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网。如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为“热点”。
      在Android中对Wifi操作,android本身提供了一些有用的包,在android.net.wifi包下面。主要包括以下几个类和接口:

(一)ScanResult

      主要用来描述已经检测出的接入点,包括接入点的地址,接入点的名称,身份认证,频率,信号强度等信息。

(二)WifiConfiguration

      Wifi网络的配置,包括安全设置等。

(三)WifiInfo

      wifi无线连接的描述,包括接入点,网络连接状态,隐藏的接入点,IP地址,连接速度,MAC地址,网络ID,信号强度等信息。这里简单介绍一下这里的方法:

1. getBSSID() 获取BSSID

2. getDetailedStateOf() 获取客户端的连通性

3. getHiddenSSID() 获得SSID 是否被隐藏

4. getIpAddress() 获取IP 地址

5. getLinkSpeed() 获得连接的速度

6. getMacAddress() 获得Mac 地址

7. getRssi() 获得802.11n 网络的信号

8. getSSID() 获得SSID

9. getSupplicanState() 返回具体客户端状态的信息

(四)WifiManager

      管理我们的wifi 连接,这里已经定义好了一些类,可以供我们使用。

(五)获取WIFI网卡的状态

WIFI网卡的状态是由一系列的整形常量来表示的。
1. WIFI_STATE_DISABLED : WIFI网卡不可用(1)
2. WIFI_STATE_DISABLING : WIFI网卡正在关闭(0)
3. WIFI_STATE_ENABLED : WIFI网卡可用(3)
4. WIFI_STATE_ENABLING : WIFI网正在打开(2) (WIFI启动需要一段时间)
5. WIFI_STATE_UNKNOWN : 未知网卡状态

(六)Wifi权限,无非是网络和Wife

<uses-permissionandroid:name="android.permission.CHANGE_NETWORK_STATE"/><uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/><uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

(七)常用方法

1.开启WIFI

 public void WifiOpen(){     if(!localWifiManager.isWifiEnabled()){         localWifiManager.setWifiEnabled(true);        } }

2.扫描WIFI信号

public void WifiStartScan(){        localWifiManager.startScan();        }

3、得到扫描WIFI结果

public List<ScanResult> getScanResults(){    return localWifiManager.getScanResults();//得到扫描结果    }

4.得到WIFi的配置好的信息,包含配置好的密码

 //得到Wifi配置好的信息 public void getConfiguration(){     wifiConfigList = localWifiManager.getConfiguredNetworks();//得到配置好的网络信息      for(int i =0;i<wifiConfigList.size();i++){                     Log.i("getConfiguration",wifiConfigList.get(i).SSID); Log.i("getConfiguration",String.valueOf(wifiConfigList.get(i).networkId));     }  }

5、根据WIFI的名称SSID判定指定WIFI是否已经配置好,配置好则返回其networkId,用于连接。之前尝试了BSSID地址没成功,所以只能使用SSID

//判定指定WIFI是否已经配置好,依据WIFI的地址BSSID,返回NetId  public int IsConfiguration(String SSID){      Log.i("IsConfiguration",String.valueOf(wifiConfigList.size()));      for(int i = 0; i < wifiConfigList.size(); i++){    Log.i(wifiConfigList.get(i).SSID,String.valueOf( wifiConfigList.get(i).networkId));     if(wifiConfigList.get(i).SSID.equals(SSID)){//地址相同      return wifiConfigList.get(i).networkId;      }  }  return -1; }

6、如果需要连接的WIFI没有配置好,即没有保存密码。则为指定名称ssid的WIFI添加密码信息psw,添加成功后返回给其分配的networId,同于连接

 //添加指定WIFI的配置信息,原列表不存在此SSID  public int AddWifiConfig(List<ScanResult> wifiList,String ssid,Stringpwd){      int wifiId = -1;     for(int i = 0;i < wifiList.size(); i++){          ScanResult wifi = wifiList.get(i);         if(wifi.SSID.equals(ssid)){          Log.i("AddWifiConfig","equals");                      WifiConfiguration wifiCong = new WifiConfiguration();          wifiCong.SSID = "\""+wifi.SSID+"\"";//\"转义字符,代表"      wifiCong.preSharedKey = "\""+pwd+"\"";//WPA-PSK密码      wifiCong.hiddenSSID = false;      wifiCong.status = WifiConfiguration.Status.ENABLED;              wifiId = localWifiManager.addNetwork(wifiCong);//将配置好的特定WIFI密码信息添加,添加完成后默认是不激活状态,成功返回ID,否则为-1      if(wifiId != -1){          return wifiId;              }        }      }      return wifiId;  }

7、根据步骤6配置好需要连接的WIFI密码信息后,下面通过networkId连接指定WIFI。在连接经过步骤6刚添加配置信息的WIFI信号之前需要重新执行下步骤4,得到新的配置好信息的列表。

//连接指定Id的WIFI  public boolean ConnectWifi(int wifiId){      for(int i = 0; i < wifiConfigList.size(); i++){      WifiConfiguration wifi = wifiConfigList.get(i);      if(wifi.networkId == wifiId){      while(!(localWifiManager.enableNetwork(wifiId, true))){//激活该Id,建立连接      //status:0--已经连接,1--不可连接,2--可以连接      Log.i("ConnectWifi",String.valueOf(wifiConfigList.get(wifiId).status));      }      return true;      }     }  return false;  }

二.Wife的开发示例程序

      这个程序运行后可以扫描周边的Wife,并且做连接,还有历史记录。
      程序运行后的界面:
w1

      可以点击对应的按钮,显示周边的Wife信息,和连接的Wife历史记录。点击某个Wife条目,就是连接的操作,输入正确的密码就可以完成Wife的连接。
下面是程序的代码:

(一)添加权限

<!--设计Wife示例使用的权限,网络权限和wife权限--><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

(二)布局文件设计

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="open"        android:text="打开wifi" />    <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="close"        android:text="关闭wifi" />    <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="scan"        android:text="扫描wifi" />    <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="getGood"        android:text="获取连接过的wifi配置信息" />    <ListView        android:id="@+id/lv"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></LinearLayout>

(三)设计一个WifeUtil工具类

package fuxi.wifedemo;import android.content.Context;import android.net.ConnectivityManager;import android.net.NetworkInfo;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 java.util.List;/** * wife使用的工具类 */public class WifiUtil {    // WifiManager.WIFI_STATE_ENABLED WiFi已打开    // WifiManager.WIFI_STATE_ENABLING WiFi打开中    // WifiManager.WIFI_STATE_DISABLING WiFi关闭中    // WifiManager.WIFI_STATE_DISABLED WiFi已关闭    // WifiManager.WIFI_STATE_UNKNOWN 未知的WiFi状态    // 定义一个WifiManager对象    private WifiManager mWifiManager;    // 定义一个WifiInfo对象    private WifiInfo mWifiInfo;    // 扫描出的网络连接列表    private List<ScanResult> mWifiList;    // 网络连接列表    private List<WifiConfiguration> mWifiConfigurations;    WifiLock mWifiLock;    Context mContext;    //传入上下文    public WifiUtil(Context context) {        // 取得WifiManager对象        mContext = context;        mWifiManager = (WifiManager) context                .getSystemService(Context.WIFI_SERVICE);        // 取得WifiInfo对象        mWifiInfo = mWifiManager.getConnectionInfo();    }    // 打开wifi    public void openWifi() {        if (!mWifiManager.isWifiEnabled()) {            mWifiManager.setWifiEnabled(true);        }    }    //判断wife是否是连接状态    public boolean isConn() {        ConnectivityManager connManager = (ConnectivityManager) mContext                .getSystemService(mContext.CONNECTIVITY_SERVICE);        NetworkInfo mWifi = connManager                .getNetworkInfo(ConnectivityManager.TYPE_WIFI);        return mWifi.isConnected();    }    // 关闭wifi    public void closeWifi() {        if (mWifiManager.isWifiEnabled()) {            mWifiManager.setWifiEnabled(false);        }    }    // 检查当前wifi状态    public int checkState() {        return mWifiManager.getWifiState();    }    // 锁定wifiLock    public void acquireWifiLock() {        mWifiLock.acquire();    }    // 解锁wifiLock    public void releaseWifiLock() {        // 判断是否锁定        if (mWifiLock.isHeld()) {            mWifiLock.acquire();        }    }    // 创建一个wifiLock    public void createWifiLock() {        mWifiLock = mWifiManager.createWifiLock("test");    }    // 得到配置好的网络    public List<WifiConfiguration> getConfiguration() {        return mWifiConfigurations;    }    // 指定配置好的网络进行连接    public boolean connetionConfiguration(int index) {        if (index > mWifiConfigurations.size()) {            return false;        }        // 连接配置好指定ID的网络        return mWifiManager.enableNetwork(mWifiConfigurations.get(index).networkId, true);    }    public void startScan() {        mWifiManager.startScan();        // 得到扫描结果        mWifiList = mWifiManager.getScanResults();        // 得到配置好的网络连接        mWifiConfigurations = mWifiManager.getConfiguredNetworks();    }    // 得到网络列表    public List<ScanResult> getWifiList() {        return mWifiList;    }    // 查看扫描结果    public StringBuffer lookUpScan() {        StringBuffer sb = new StringBuffer();        for (int i = 0; i < mWifiList.size(); i++) {            sb.append("Index_" + new Integer(i + 1).toString() + ":");            // 将ScanResult信息转换成一个字符串包            // 其中把包括:BSSID、SSID、capabilities、frequency、level            sb.append((mWifiList.get(i)).toString()).append("\n");        }        return sb;    }    public String getMacAddress() {        return (mWifiInfo == null) ? "NULL" : mWifiInfo.getMacAddress();    }    public String getBSSID() {        return (mWifiInfo == null) ? "NULL" : mWifiInfo.getBSSID();    }    public int getIpAddress() {        return (mWifiInfo == null) ? 0 : mWifiInfo.getIpAddress();    } // 得到连接的ID    public String getSSID() {        return (mWifiInfo == null) ? "" : mWifiInfo.getSSID().replace("\"", "");    } // 得到连接的ID    public int getNetWordId() {        return (mWifiInfo == null) ? 0 : mWifiInfo.getNetworkId();    } // 得到wifiInfo的所有信息    public String getWifiInfo() {        return (mWifiInfo == null) ? "NULL" : mWifiInfo.toString();    }    public String getGateway() {        return mWifiInfo == null ? "NULL"                : intToIp(mWifiManager.getDhcpInfo().gateway);    }    private String intToIp(int paramInt) {        return (paramInt & 0xFF) + "." + (0xFF & paramInt >> 8) + "."                + (0xFF & paramInt >> 16) + "." + (0xFF & paramInt >> 24);    }    // 添加一个网络并连接    public boolean addNetWork(WifiConfiguration configuration) {        int wcgId = mWifiManager.addNetwork(configuration);        return mWifiManager.enableNetwork(wcgId, true);    }    // 断开指定ID的网络    public void disConnectionWifi(int netId) {        mWifiManager.disableNetwork(netId);        mWifiManager.disconnect();    }    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  WPA2        {            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;    }    //判断密码的类别    public int getType(String capabilities) //[wpa]    {        //[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]        // [WPA2-PSK-CCMP][ESS]        //[ESS]        if (capabilities.contains("WPA"))            return 3;        else if (capabilities.contains("WEP"))            return 2;        else            return 1;    }    //根据SSID判断这个WIFE设置对象是否存在    private WifiConfiguration IsExsits(String SSID) {        List<WifiConfiguration> existingConfigs = mWifiManager                .getConfiguredNetworks();        for (WifiConfiguration existingConfig : existingConfigs) {            if (existingConfig.SSID.equals("\"" + SSID + "\"")) {                return existingConfig;            }        }        return null;    }}

(四)主方法的类的设计

package fuxi.wifedemo;import android.content.DialogInterface;import android.net.wifi.ScanResult;import android.net.wifi.WifiConfiguration;import android.net.wifi.WifiManager;import android.os.Bundle;import android.support.v7.app.AlertDialog;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.EditText;import android.widget.ListView;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {    WifiUtil wifiUtil;//定义Wife工具类    ListView listView;//显示Wife的数据列表    ArrayAdapter<String> adapter;//列表的适配器    List<String> wifiSSIDs = new ArrayList<>();//列表的数据    WifiManager wifiManager;//Wife管理器    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        wifiUtil = new WifiUtil(this);        wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);//获取Wife管理器        listView = (ListView) findViewById(R.id.lv);        //创建适配器,并把适配器设置到ListView中        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, wifiSSIDs);        listView.setAdapter(adapter);        //给ListView设置点击事件,点击后连接Wife        listView.setOnItemClickListener(this);    }    /**     * 打开Wife     */    public void open(View view) {        wifiUtil.openWifi();    }    /**     * 关闭Wife     */    public void close(View view) {        wifiUtil.closeWifi();    }    /**     * 扫描Wife     */    List<ScanResult> wifiList = new ArrayList<>();    public void scan(View view) {        isClickHistory = false;//显示的列表不是历史记录        //扫描先清除数据        wifiSSIDs.clear();        wifiList.clear();        wifiUtil.startScan();//扫描Wife        wifiList = wifiUtil.getWifiList();        //获取列表中的SSID并显示出来        for (ScanResult scanResult : wifiList) {            wifiSSIDs.add(scanResult.SSID);        }        //刷新适配器        adapter.notifyDataSetChanged();    }    /**     * 获取连接过的Wife数据     */    List<WifiConfiguration> configuredNetworks = new ArrayList<>();    public void getGood(View view) {        isClickHistory = true;//显示的列表是历史记录        //扫描先清除数据        wifiSSIDs.clear();        if (configuredNetworks != null) {            configuredNetworks.clear();            //获取历史记录            configuredNetworks = wifiUtil.getConfiguration();            if (configuredNetworks == null)                return;            for (WifiConfiguration result : configuredNetworks) {                wifiSSIDs.add(result.SSID);            }            //刷新适配器            adapter.notifyDataSetChanged();        }        //获取列表中的SSID并显示出来    }    /**     * 点击Wife视图列表数据后的回调方法,这里是连接WIfe     */    boolean isClickHistory = false;    @Override    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {        //判断是否是点击的历史记录        if (isClickHistory) {            boolean connOk = wifiUtil.connetionConfiguration(position);            if (connOk) {                Toast.makeText(MainActivity.this, "Wife连接成功", Toast.LENGTH_SHORT).show();                finish();            } else {                Toast.makeText(MainActivity.this, "Wife连接失败", Toast.LENGTH_SHORT).show();            }        } else {            //连接wifi            ScanResult sr = wifiList.get(position);//获取点击的扫描信息            final String SSID = sr.SSID;//获取Wife的SSID            final int type = wifiUtil.getType(sr.capabilities);            if (type == 1) {//没有密码的Wife情况                WifiConfiguration config = wifiUtil.createWifiInfo(SSID, "", type);//第二个空就是密码                wifiUtil.addNetWork(config);            } else {                //有密码                final EditText et = new EditText(MainActivity.this);                et.setHint("输入wifi密码");                new AlertDialog.Builder(MainActivity.this)                        .setTitle("设置密码")                        .setView(et)                        .setNeutralButton("取消", null)                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {                            @Override                            public void onClick(DialogInterface dialog, int which) {                                WifiConfiguration config = wifiUtil.createWifiInfo(SSID, et.getText().toString(), type);                                boolean conn = wifiUtil.addNetWork(config);                                //判断密码是否连接成功                                if (conn) {                                    Toast.makeText(MainActivity.this, "Wife连接成功", Toast.LENGTH_SHORT).show();                                    finish();//关闭页面                                } else {                                    Toast.makeText(MainActivity.this, "Wife连接失败", Toast.LENGTH_SHORT).show();                                }                            }                        }).create().show();            }        }    }}

       其中上面很多过程的操作都是在工具类中做好实现了,在主方法类中只要实现逻辑调用就可以完成Wife的设计了。
       这里的WifeUtil可以直接拿去使用,也可以在里面多添加一些功能。
程序运行后,扫描蓝牙的显示界面:
w2
点击历史连接记录,显示的界面:

w3
点击某一个条目的Wife数据,就行连接的界面:
w4
       输入正确的密码就可以连上Wife了,如果输入错误,它会提示你连接失败。

       上面已经简单使用一个Wife程序的开发,就是功能不是很强大!

4 0