精华内容
下载资源
问答
  • 2021-11-17 14:58:06

    boolean isUpdated = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false);

    Log.i(TAG, "onReceive: WIFI扫描 " + (isUpdated ? “完成” : “未完成”));

    } else {

    Log.i(TAG, “onReceive: WIFI扫描完成”);

    }

    Message scanResultsMessage = Message.obtain();

    scanResultsMessage.what = SCAN_RESULTS_UPDATED;

    scanResultsMessage.obj = wifiManager.getScanResults();

    mCallBackHandler.sendMessage(scanResultsMessage);

    break;

    //WIFI网络状态变化通知

    case WifiManager.NETWORK_STATE_CHANGED_ACTION:

    WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);

    if (null != wifiInfo && wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {

    String ssid = wifiInfo.getSSID();

    Log.i(TAG, "onReceive: 网络连接成功 ssid = " + ssid);

    }

    break;

    //WIFI连接状态变化的时候

    case WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION:

    boolean isConnected = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false);

    Log.i(TAG, "onReceive: SUPPLICANT_CONNECTION_CHANGE_ACTION isConnected = " + isConnected);

    break;

    //wifi连接结果通知 WIFI连接请求状态发生改变

    case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:

    // 获取连接状态

    SupplicantState supplicantState = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);

    Message logMessage = Message.obtain();

    logMessage.what = WIFI_CONNECT_LOG;

    logMessage.obj = supplicantState.toString();

    logMessage.obj = supplicantState.toString();

    mCallBackHandler.sendMessage(logMessage);

    switch (supplicantState) {

    case INTERFACE_DISABLED: // 接口禁用

    Log.i(TAG, “onReceive: INTERFACE_DISABLED 接口禁用”);

    break;

    case DISCONNECTED:// 断开连接

    // Log.i(TAG, “onReceive: DISCONNECTED:// 断开连接”);

    // break;

    case INACTIVE: // 不活跃的

    WifiInfo connectFailureInfo = wifiManager.getConnectionInfo();

    Log.i(TAG, "onReceive: INACTIVE 不活跃的 connectFailureInfo = " + connectFailureInfo);

    if (null != connectFailureInfo) {

    Message wifiConnectFailureMessage = Message.obtain();

    wifiConnectFailureMessage.what = WIFI_CONNECT_FAILURE;

    wifiConnectFailureMessage.obj = connectFailureInfo.getSSID();

    mCallBackHandler.sendMessage(wifiConnectFailureMessage);

    // 断开连接

    int networkId = connectFailureInfo.getNetworkId();

    boolean isDisable = wifiManager.disableNetwork(networkId);

    boolean isDisconnect = wifiManager.disconnect();

    Log.i(TAG, "onReceive: 断开连接 = " + (isDisable && isDisconnect));

    }

    break;

    case SCANNING: // 正在扫描

    Log.i(TAG, “onReceive: SCANNING 正在扫描”);

    break;

    case AUTHENTICATING: // 正在验证

    Log.i(TAG, “onReceive: AUTHENTICATING: // 正在验证”);

    break;

    case ASSOCIATING: // 正在关联

    Log.i(TAG, “onReceive: ASSOCIATING: // 正在关联”);

    break;

    case ASSOCIATED: // 已经关联

    Log.i(TAG, “onReceive: ASSOCIATED: // 已经关联”);

    break;

    case FOUR_WAY_HANDSHAKE: // 四次握手

    Log.i(TAG, “onReceive: FOUR_WAY_HANDSHAKE:”);

    break;

    case GROUP_HANDSHAKE: // 组握手

    Log.i(TAG, “onReceive: GROUP_HANDSHAKE:”);

    break;

    case COMPLETED: // 完成

    Log.i(TAG, “onReceive: WIFI_CONNECT_SUCCESS: // 完成”);

    WifiInfo connectSuccessInfo = wifiManager.getConnectionInfo();

    if (null != connectSuccessInfo) {

    Message wifiConnectSuccessMessage = Message.obtain();

    wifiConnectSuccessMessage.what = WIFI_CONNECT_SUCCESS;

    wifiConnectSuccessMessage.obj = connectSuccessInfo.getSSID();

    mCallBackHandler.sendMessage(wifiConnectSuccessMessage);

    }

    break;

    case DORMANT: // 休眠

    Log.i(TAG, “onReceive: DORMANT:”);

    break;

    case UNINITIALIZED: // 未初始化

    Log.i(TAG, “onReceive: UNINITIALIZED: // 未初始化”);

    break;

    case INVALID: // 无效的

    Log.i(TAG, “onReceive: INVALID: // 无效的”);

    break;

    default:

    break;

    }

    break;

    default:

    break;

    }

    }

    }

    相关API请参阅:官网WifiManagerAPI


    六,权限



    七,打开WIFI


    /**

    • 打开Wifi

    */

    public void openWiFi() {

    if (!isWifiEnabled() && null != mWifiManager) {

    mWifiManager.setWifiEnabled(true);

    }

    }


    八,关闭WIFI


    /**

    • 关闭Wifi

    */

    public void closeWiFi() {

    if (isWifiEnabled() && null != mWifiManager) {

    mWifiManager.setWifiEnabled(false);

    }

    }


    九,扫描附近的WIFI


    /**

    • 扫描附近的WIFI

    */

    public void startScan() {

    if (null != mWifiManager) {

    mWifiManager.startScan();

    }

    }


    十,获取WIFI列表


    /**

    • 获取最近扫描的WIFI热点

    • @return WIFI热点列表

    */

    public List getScanResults() {

    // 得到扫描结果

    if (null != mWifiManager) {

    return mWifiManager.getScanResults();

    }

    return null;

    }


    十一,通过密码连接到WIFI


    /**

    • 连接到开放网络

    • @param ssid 热点名

    • @return 配置是否成功

    */

    public boolean connectOpenNetwork(@NonNull String ssid) {

    // 获取networkId

    int networkId = setOpenNetwork(ssid);

    if (-1 != networkId) {

    // 保存配置

    boolean isSave = saveConfiguration();

    // 连接网络

    boolean isEnable = enableNetwork(networkId);

    return isSave && isEnable;

    }

    return false;

    }

    /**

    • 连接到WEP网络

    • @param ssid 热点名

    • @param password 密码

    • @return 配置是否成功

    */

    public boolean connectWEPNetwork(@NonNull String ssid, @NonNull String password) {

    // 获取networkId

    int networkId = setWEPNetwork(ssid, password);

    if (-1 != networkId) {

    // 保存配置

    boolean isSave = saveConfiguration();

    // 连接网络

    boolean isEnable = enableNetwork(networkId);

    return isSave && isEnable;

    }

    return false;

    }

    /**

    • 连接到WPA2网络

    • @param ssid 热点名

    • @param password 密码

    • @return 配置是否成功

    */

    public boolean connectWPA2Network(@NonNull String ssid, @NonNull String password) {

    // 获取networkId

    int networkId = setWPA2Network(ssid, password);

    if (-1 != networkId) {

    // 保存配置

    boolean isSave = saveConfiguration();

    // 连接网络

    boolean isEnable = enableNetwork(networkId);

    return isSave && isEnable;

    }

    return false;

    }

    这里就写了三种加密方式的连接,其中ssid是扫描到的,password是单击ListView列表弹出EditText框输入的。


    十二,直接连接配置过的WIFI


    这里的思路是通过NetworkId连接到WIFI (配置过的网络可以直接获取到NetworkID,从而不用再输入密码)。代码中采用回调方式来实现,这个具体请看项目代码。


    十三,断开指定WIFI


    /**

    • 断开指定 WIFI

    • @param netId netId

    • @return 是否断开

    */

    public boolean disconnectWifi(int netId) {

    if (null != mWifiManager) {

    boolean isDisable = mWifiManager.disableNetwork(netId)

    《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

    开源分享完整内容戳这里

    ;

    boolean isDisconnect = mWifiManager.disconnect();

    return isDisable && isDisconnect;

    }

    return false;

    }


    十四,删除配置


    /**

    • 删除配置

    • @param netId netId

    • @return 是否删除成功

    */

    public boolean deleteConfig(int netId) {

    if (null != mWifiManager) {

    boolean isDisable = mWifiManager.disableNetwork(netId);

    boolean isRemove = mWifiManager.removeNetwork(netId);

    boolean isSave = mWifiManager.saveConfiguration();

    return (isDisable && isRemove && isSave);

    }

    return false;

    }

    这个功能是在ListView长按监听那里的


    十五,开启热点


    Android7.0及7.0之前的方法:

    /**

    • 创建热点,这里只能是7.0或7.0之前的版本

    • 手动设置热点名和密码

    */

    public void createWifiHotspot7() {

    WifiConfiguration config = new WifiConfiguration();

    config.SSID = “性感荷官在线发脾气”;

    config.preSharedKey = “123456789”;

    config.hiddenSSID = true;

    config.allowedAuthAlgorithms

    .set(WifiConfiguration.AuthAlgorithm.OPEN);//开放系统认证

    config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

    //设置加密的方式,这个对应小米手机MIUI

    int indexOfWPA2_PSK = 4;

    //从WifiConfiguration.KeyMgmt数组中查找WPA2_PSK的值

    for (int i = 0; i < WifiConfiguration.KeyMgmt.strings.length; i++) {

    if (WifiConfiguration.KeyMgmt.strings[i].equals(“WPA2_PSK”)) {

    indexOfWPA2_PSK = i;

    break;

    }

    }

    config.allowedKeyManagement.set(indexOfWPA2_PSK);

    config.allowedPairwiseCiphers

    .set(WifiConfiguration.PairwiseCipher.TKIP);

    config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);

    config.allowedPairwiseCiphers

    .set(WifiConfiguration.PairwiseCipher.CCMP);

    config.status = WifiConfiguration.Status.ENABLED;

    //通过反射调用设置热点

    try {

    更多相关内容
  • Android WiFi开发教程

    万次阅读 2018-10-11 09:27:12
    Android WiFi开发教程(一)——WiFi热点的创建与关闭   相对于BlueTooth,WiFi是当今使用最广的一种无线网络传输技术, 几乎所有智能手机、平板电脑和笔记本电脑都支持Wi-Fi上网。因此,掌握基本的WiFI开发技术是...

     

    Android WiFi开发教程(一)——WiFi热点的创建与关闭

     

    相对于BlueTooth,WiFi是当今使用最广的一种无线网络传输技术, 几乎所有智能手机、平板电脑和笔记本电脑都支持Wi-Fi上网。因此,掌握基本的WiFI开发技术是非常必要的。本教程将围绕一个小Demo初步与大家一同探讨WiFi开发。

    先上效果图

    这里写图片描述
    这里写图片描述 
    这里写图片描述

    Demo功能比较简单,四个按钮、两个文本和一个列表。功能主要有创建WiFi热点,关闭WiFi热点,搜索WiFi,连接WiFi,数据通讯。源码会在教程结尾提供。

    本章节主要介绍WiFi热点的创建和关闭

    需要用到的权限

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

    WiFi热点的创建

    /**
         * 创建Wifi热点
         */
        private void createWifiHotspot() {
            if (wifiManager.isWifiEnabled()) {
                //如果wifi处于打开状态,则关闭wifi,
                wifiManager.setWifiEnabled(false);
            }
            WifiConfiguration config = new WifiConfiguration();
            config.SSID = WIFI_HOTSPOT_SSID;
            config.preSharedKey = "123456789";
            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.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedPairwiseCiphers
                    .set(WifiConfiguration.PairwiseCipher.CCMP);
            config.status = WifiConfiguration.Status.ENABLED;
            //通过反射调用设置热点
            try {
                Method method = wifiManager.getClass().getMethod(
                        "setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
                boolean enable = (Boolean) method.invoke(wifiManager, config, true);
                if (enable) {
                    textview.setText("热点已开启 SSID:" + WIFI_HOTSPOT_SSID + " password:123456789");
                } else {
                    textview.setText("创建热点失败");
                }
            } catch (Exception e) {
                e.printStackTrace();
                textview.setText("创建热点失败");
            }
        }

    这里我们需要用到一个很重要的API——WifiManager。源码中是有这么一段介绍:

    This class provides the primary API for managing all aspects of Wi-Fi
    connectivity. Get an instance of this class by calling
    {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}.

    可以了解到,我们能够通过WifiManager来管理WiFi的连接。而通过Context.getSystemService(Context.WIFI_SERVICE)就能获取到它的实例。

    wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

    在开启热点的时候,我们需要确保WiFi是关闭状态,因为大部分手机都是不支持热点和WiFi是同时开启的。接着就需要创建WifiConfiguration这个类,由于配置我们所要创建的热点的属性。这里我们所需注意的主要是SSID、preSharedKey和KeyMgmt。 分别对应热点的名称、密码和加密方式。

    配置完属性后,我们就可以通过Java的反射机制去创建热点。

    WiFi热点的关闭

    /**
         * 关闭WiFi热点
         */
        public void closeWifiHotspot() {
            try {
                Method method = wifiManager.getClass().getMethod("getWifiApConfiguration");
                method.setAccessible(true);
                WifiConfiguration config = (WifiConfiguration) method.invoke(wifiManager);
                Method method2 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
                method2.invoke(wifiManager, config, false);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

    跟创建WiFI热点一样,关闭的时候同样需要用到Java的反射机制。在调用Method的invoke方法时,将最后一个参数改成false就可以了。

    Android WiFi开发教程(二)——WiFi的搜索和连接

    WiFi的搜索

      /* 搜索wifi热点
         */
        private void search() {
            if (!wifiManager.isWifiEnabled()) {
                //开启wifi
                wifiManager.setWifiEnabled(true);
            }
            wifiManager.startScan();
        }

    我们在开始搜索WiFi之前确保当前WiFi功能是处于开启状态。如果未开启,通过调用WifiManager的setWifiEnabled(boolean enable)去开启。之后调用startScan()就开始扫描附近的WiFi了。而获取扫描的结果我们就需要创建一个广播接收者来处理。

    private BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                    // wifi已成功扫描到可用wifi。
                    List<ScanResult> scanResults = wifiManager.getScanResults();
                    wifiListAdapter.clear();
                    wifiListAdapter.addAll(scanResults);
                } 
        };

    系统在扫描结束后,会发出WifiManager.SCAN_RESULTS_AVAILABLE_ACTION的广播,当我们的接收者接收到这个广播的时候,通过WifiManager的getScanResults()就能获取到扫描结果的集合了。ScanResult保存着每一个WiFi的信息。这里我将这个集合设置到Adapter中,并在列表中展示出来。下面是Apater中主要的代码:

     @Override
        public View getView(int position, View convertView, ViewGroup parent) {
    
            if (convertView == null) {
                convertView = mInflater.inflate(mResource, parent, false);
            }
    
            TextView name = (TextView) convertView.findViewById(R.id.wifi_name);
            TextView signl = (TextView) convertView.findViewById(R.id.wifi_signal);
    
            ScanResult scanResult = getItem(position);
            name.setText(scanResult.SSID);
    
            int level = scanResult.level;
            if (level <= 0 && level >= -50) {
                signl.setText("信号很好");
            } else if (level < -50 && level >= -70) {
                signl.setText("信号较好");
            } else if (level < -70 && level >= -80) {
                signl.setText("信号一般");
            } else if (level < -80 && level >= -100) {
                signl.setText("信号较差");
            } else {
                signl.setText("信号很差");
            }
    
            return convertView;
        }

    可以看出列表展示的数据也是比较简单,只有WiFi的名称和信号强度,这两个数据也是平时用得比较多的。获取到扫描结果后,我们就可以处理连接的逻辑了。

    WiFi的连接

    WiFi的连接相当于搜索就要复杂一些。首先给列表项设置点击事件,获取对应的ScanResult。

       listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    wifiManager.disconnect();
                    final ScanResult scanResult = wifiListAdapter.getItem(position);
                     String capabilities = scanResult.capabilities;
                    int type = WIFICIPHER_WPA;
                    if (!TextUtils.isEmpty(capabilities)) {
                        if (capabilities.contains("WPA") || capabilities.contains("wpa")) {
                            type = WIFICIPHER_WPA;
                        } else if (capabilities.contains("WEP") || capabilities.contains("wep")) {
                            type = WIFICIPHER_WEP;
                        } else {
                            type = WIFICIPHER_NOPASS;
                        }
                    }
                    config = isExsits(scanResult.SSID);
            });

    取到ScanResult后我们通过他的capabilities属性判断WiFi的加密方式。接着通过isExsits(String SSID)方法判断系统是否保存着当前WiFi的信息。

    private WifiConfiguration isExsits(String SSID) {
            List<WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
            for (WifiConfiguration existingConfig : existingConfigs) {
                if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
                    return existingConfig;
                }
            }
            return null;
        }

    如果之前连接过,则返回WiFi的配置信息,否则返回空对象。然后接着处理连接的逻辑

    if (config == null) {
                        if (type != WIFICIPHER_NOPASS) {//需要密码
                            final EditText editText = new EditText(MainActivity.this);
                            final int finalType = type;
                            new AlertDialog.Builder(MainActivity.this).setTitle("请输入Wifi密码").setIcon(
                                    android.R.drawable.ic_dialog_info).setView(
                                    editText).setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    Log.w("AAA", "editText.getText():" + editText.getText());
                                    config = createWifiInfo(scanResult.SSID, editText.getText().toString(), finalType);
                                    connect(config);
                                }
                            })
                                    .setNegativeButton("取消", null).show();
                            return;
                        } else {
                            config = createWifiInfo(scanResult.SSID, "", type);
                            connect(config);
                        }
                    } else {
                        connect(config);
                    }

    当没有获取到所要连接WiFi的配置信息时,我们就需要用到前面获取到的加密方式判断是否需要输入密码。如果加密方式为WAP或WEP时,则弹出提示框提示用户输入WiFi密码。用户输入密码后再调用connect(WifiConfiguration config)方法

    如果可以获取到所要连接WiFi的配置信息,则直接调用connect(WifiConfiguration config)。

    private void connect(WifiConfiguration config) {
            int wcgID = wifiManager.addNetwork(config);
            wifiManager.enableNetwork(wcgID, true);
        }

    直接调用WifiManger的addNetwork方法,将配置信息传进去后,会创建一个新的网络描述的身份并返回回来,如果返回来是-1,则表示创建失败。获取到身份后,调用enableNetwork方法就能开始连接WiFi了。到了这里,我们连接部分就完成了一半,接下来需要继续处理WiFi连接过程中返回来的状态。这里同样我们是需要用到广播接收者来处理。

    if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
      NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    
                    if (info.getState().equals(NetworkInfo.State.DISCONNECTED)) {
                        text_state.setText("连接已断开");
                    } else if (info.getState().equals(NetworkInfo.State.CONNECTED)) {
                        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                        final WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                        text_state.setText("已连接到网络:" + wifiInfo.getSSID());
    
                        }
                    } else {
                        NetworkInfo.DetailedState state = info.getDetailedState();
                        if (state == state.CONNECTING) {
                            text_state.setText("连接中...");
                        } else if (state == state.AUTHENTICATING) {
                            text_state.setText("正在验证身份信息...");
                        } else if (state == state.OBTAINING_IPADDR) {
                            text_state.setText("正在获取IP地址...");
                        } else if (state == state.FAILED) {
                            text_state.setText("连接失败");
                        }
                    }
    
                }

    上面是广播接收者中的关键代码。WiFi在连接的过程中系统会发出WifiManager.NETWORK_STATE_CHANGED_ACTION的广播,当接收者接收到这条广播时,获取NetworkInfo的state来判断当前的连接状态。状态值分别代表如下

    NetworkInfo.State.DISCONNECTED //连接已断开
    NetworkInfo.State.CONNECTED //已成功连接
    

    除了这两个状态之外,这里还判断了其他状态

    NetworkInfo.DetailedState state = info.getDetailedState();
                        if (state == state.CONNECTING) {
                            text_state.setText("连接中...");
                        } else if (state == state.AUTHENTICATING) {
                            text_state.setText("正在验证身份信息...");
                        } else if (state == state.OBTAINING_IPADDR) {
                            text_state.setText("正在获取IP地址...");
                        } else if (state == state.FAILED) {
                            text_state.setText("连接失败");
                        }

    DetailedState中包含了很多连接状态的信息,这里只对部分状态进行处理,其他状态值解析具体如下

    IDLE:空闲
    SCANNING:正在扫描
    CONNECTING:连接中
    AUTHENTICATING:正在进行身份验证
    OBTAINING_IPADDR:正在获取Ip地址
    CONNECTED:已连接
    SUSPENDED:已暂停
    DISCONNECTING:正在断开连接
    DISCONNECTED:已断开
    FAILED:失败
    BLOCKED:已阻止
    VERIFYING_POOR_LINK:暂时关闭(网络状况不佳)
    CAPTIVE_PORTAL_CHECK:判断是否需要浏览器二次登录

     

    跟蓝牙通讯一样,WiFi热点数据传输也是要运用到Socket。这里我创建了两个线程ConnectThread和ListenerThread,分别去处理数据传输和监听连接。

    ConnectThread

    **
     * 连接线程
     * Created by 坤 on 2016/9/7.
     */
    public class ConnectThread extends Thread{
    
        private final Socket socket;
        private Handler handler;
        private InputStream inputStream;
        private OutputStream outputStream;
    
        public ConnectThread(Socket socket, Handler handler){
            setName("ConnectThread");
            this.socket = socket;
            this.handler = handler;
        }
    
        @Override
        public void run() {
            if(socket==null){
                return;
            }
            handler.sendEmptyMessage(MainActivity.DEVICE_CONNECTED);
            try {
                //获取数据流
                inputStream = socket.getInputStream();
                outputStream = socket.getOutputStream();
    
                byte[] buffer = new byte[1024];
                int bytes;
                while (true){
                    //读取数据
                    bytes = inputStream.read(buffer);
                    if (bytes > 0) {
                        final byte[] data = new byte[bytes];
                        System.arraycopy(buffer, 0, data, 0, bytes);
    
                        Message message = Message.obtain();
                        message.what = MainActivity.GET_MSG;
                        Bundle bundle = new Bundle();
                        bundle.putString("MSG",new String(data));
                        message.setData(bundle);
                        handler.sendMessage(message);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 发送数据
         */
        public void sendData(String msg){
            if(outputStream!=null){
                try {
                    outputStream.write(msg.getBytes());
                    Message message = Message.obtain();
                    message.what = MainActivity.SEND_MSG_SUCCSEE;
                    Bundle bundle = new Bundle();
                    bundle.putString("MSG",new String(msg));
                    message.setData(bundle);
                    handler.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                    Message message = Message.obtain();
                    message.what = MainActivity.SEND_MSG_ERROR;
                    Bundle bundle = new Bundle();
                    bundle.putString("MSG",new String(msg));
                    message.setData(bundle);
                    handler.sendMessage(message);
                }
            }
        }
    }

    ConnectThread的构造中,传入了Socket和Handler。Socket用来获取数据以及发送数据,Handler用来更新UI了。在run方法中,我们从Socket中获取到了输入流和输出流,然后循环地读取InputStream的数据,当读取到数据时,则通过Handler将数据更新到UI上。在sendData方法中主要是通过OutputStream写入数据,然后将写入结果通过Handler更新到UI上。

    ListenerThread监听线程处理的逻辑就比较简单,通过端口号获取ServerSocket后调用accept()阻塞线程,直到有设备连接上后就通过Handler更新UI。这里需要注意的是连接上的设备的端口号必须与这里的端口号相同。接着我们看看Hander获取到消息后做了哪些处理。

    private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case DEVICE_CONNECTING:
                        connectThread = new ConnectThread(listenerThread.getSocket(),handler);
                        connectThread.start();
                        break;
                        ... ...
                }
            }
        };

    可以看到Handler获取到数据后,通过listenerThread.getSocket()将获取到Socket和handler一同创建了ConnectThread实例。

    接下来就是用这两个线程来处理数据传输了。

     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ... ...
            listenerThread = new ListenerThread(PORT, handler);
            listenerThread.start();
        }

    在onCreate中我们创建ListenerThread并启动它,让它监听是否有设备连接上来。当然这里需要先开启WiFi热点后才会有设备连接上来。这是开启热点并等待设备连接的情况。当然我们也可以主动去连接其他开启着热点的设备。

    在监听WiFi连接情况的广播接收者中加入下面的代码

    if (info.getState().equals(NetworkInfo.State.CONNECTED)) {
                        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                        final WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                        text_state.setText("已连接到网络:" + wifiInfo.getSSID());
    
                        if (wifiInfo.getSSID().equals(WIFI_HOTSPOT_SSID)) {
                            //如果当前连接到的wifi是热点,则开启连接线程
                            new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        ArrayList<String> connectedIP = getConnectedIP();
                                        for (String ip : connectedIP) {
                                            if (ip.contains(".")) {
    
                                                Socket socket = new Socket(ip, PORT);
                                                connectThread = new ConnectThread(socket, handler);
                                                connectThread.start();
                                            }
                                        }
    
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }).start();
                        }
                    } else {
                        ...
                        }
                }

    这里本地固定了其他设备WiFi热点的SSID,如果当前连接的WiFi的SSID跟我们之前保存的SSID一致,则证明我们连上了我们需要的WiFi热点。然后通过getConnectedIP()获取WiFi热点的IP地址,通过这个IP地址和端口号创建一个Socket,然后创建ConnectThread来处理数据传输。到这里我们可以看到,PORT和SSID这两个数据是需要两个设备事先协议好的。

    最后再看看Handler完整的代码

    private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case DEVICE_CONNECTING:
                        connectThread = new ConnectThread(listenerThread.getSocket(),handler);
                        connectThread.start();
                        break;
                    case DEVICE_CONNECTED:
                        textview.setText("设备连接成功");
                        break;
                    case SEND_MSG_SUCCSEE:
                        textview.setText("发送消息成功:" + msg.getData().getString("MSG"));
                        break;
                    case SEND_MSG_ERROR:
                        textview.setText("发送消息失败:" + msg.getData().getString("MSG"));
                        break;
                    case GET_MSG:
                        textview.setText("收到消息:" + msg.getData().getString("MSG"));
                        break;
                }
            }
        };

    至此,WiFi热点数据传输也就介绍完了。如果有什么疑问,欢迎和本人一起探讨。

    最后附上源码地址

    CSDN 原文:https://blog.csdn.net/a1533588867/article/details/52460636?utm_source=copy 

    展开全文
  • Android Wifi开发Demo示例

    热门讨论 2016-04-24 10:12:08
    Android Wifi开发的Demo程序,包括Wifi的搜索、连接、数据的传输。
  • Android WiFi开发教程(一)——WiFi热点的创建与关闭

    万次阅读 多人点赞 2016-09-07 14:28:02
    教程将围绕一个小Demo初步与大家一同探讨WiFi开发。先上效果图 Demo功能比较简单,四个按钮、两个文本和一个列表。功能主要有创建WiFi热点,关闭WiFi热点,搜索WiFi,连接WiFi,数据通讯。源码会在教

    相对于BlueTooth,WiFi是当今使用最广的一种无线网络传输技术, 几乎所有智能手机、平板电脑和笔记本电脑都支持Wi-Fi上网。因此,掌握基本的WiFI开发技术是非常必要的。本教程将围绕一个小Demo初步与大家一同探讨WiFi开发。

    先上效果图

    这里写图片描述
    这里写图片描述
    这里写图片描述

    Demo功能比较简单,四个按钮、两个文本和一个列表。功能主要有创建WiFi热点,关闭WiFi热点,搜索WiFi,连接WiFi,数据通讯。源码会在教程结尾提供。

    本章节主要介绍WiFi热点的创建和关闭

    需要用到的权限

    Android6.0以上的系统别忘了动态申请权限

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

    WiFi热点的创建

    /**
         * 创建Wifi热点
         */
        private void createWifiHotspot() {
            if (wifiManager.isWifiEnabled()) {
                //如果wifi处于打开状态,则关闭wifi,
                wifiManager.setWifiEnabled(false);
            }
            WifiConfiguration config = new WifiConfiguration();
            config.SSID = WIFI_HOTSPOT_SSID;
            config.preSharedKey = "123456789";
            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.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedPairwiseCiphers
                    .set(WifiConfiguration.PairwiseCipher.CCMP);
            config.status = WifiConfiguration.Status.ENABLED;
            //通过反射调用设置热点
            try {
                Method method = wifiManager.getClass().getMethod(
                        "setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
                boolean enable = (Boolean) method.invoke(wifiManager, config, true);
                if (enable) {
                    textview.setText("热点已开启 SSID:" + WIFI_HOTSPOT_SSID + " password:123456789");
                } else {
                    textview.setText("创建热点失败");
                }
            } catch (Exception e) {
                e.printStackTrace();
                textview.setText("创建热点失败");
            }
        }
    

    这里我们需要用到一个很重要的API——WifiManager。源码中是有这么一段介绍:

    This class provides the primary API for managing all aspects of Wi-Fi
    connectivity. Get an instance of this class by calling
    {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}.
    

    可以了解到,我们能够通过WifiManager来管理WiFi的连接。而通过Context.getSystemService(Context.WIFI_SERVICE)就能获取到它的实例。

    wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    

    在开启热点的时候,我们需要确保WiFi是关闭状态,因为大部分手机都是不支持热点和WiFi是同时开启的。接着就需要创建WifiConfiguration这个类,由于配置我们所要创建的热点的属性。这里我们所需注意的主要是SSID、preSharedKey和KeyMgmt。 分别对应热点的名称、密码和加密方式。

    配置完属性后,我们就可以通过Java的反射机制去创建热点。

    WiFi热点的关闭

    /**
         * 关闭WiFi热点
         */
        public void closeWifiHotspot() {
            try {
                Method method = wifiManager.getClass().getMethod("getWifiApConfiguration");
                method.setAccessible(true);
                WifiConfiguration config = (WifiConfiguration) method.invoke(wifiManager);
                Method method2 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
                method2.invoke(wifiManager, config, false);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    

    跟创建WiFI热点一样,关闭的时候同样需要用到Java的反射机制。在调用Method的invoke方法时,将最后一个参数改成false就可以了。

    相对来说,WiFi热点的创建与关闭还是比较简单的。欢迎继续阅读下一篇Android WiFi开发教程(二)——WiFi的搜索和连接

    展开全文
  • android开发教程wifi开发示例

    千次阅读 2021-05-28 08:52:44
    1、 WIFI网卡的状态WIFI网卡的状态信息都以整型变量的形式存放在 android.net.wifi.WifiManager 类中,有以下状态:WIFI_STATE_DISABLEDWIFI网卡不可用WIFI_STATE_DISABLINGWIFI网卡正在关闭WIFI_STATE_ENABLEDWIFI...

    1、 WIFI网卡的状态

    WIFI网卡的状态信息都以整型变量的形式存放在 android.net.wifi.WifiManager 类中,有以下状态:

    WIFI_STATE_DISABLED

    WIFI网卡不可用

    WIFI_STATE_DISABLING

    WIFI网卡正在关闭

    WIFI_STATE_ENABLED

    WIFI网卡可用

    WIFI_STATE_ENABLING

    WIFI网卡正在打开

    WIFI_STATE_UNKNOWN

    WIFI网卡状态未知

    2、 操作WIFI 网卡所需的权限

    CHANGE_NETWORK_STATE

    允许应用程序改变网络连接状态

    CHANGE_WIFI_STATE

    允许应用程序改变WIFI 连接状态

    ACCESS_NETWORK_STATE

    允许应用程序获取网络的状态信息

    ACCESS_WIFI_STATE

    允许应用程序获得WIFI 的状态信息

    3、 改变WIFI 网卡的状态

    对WIFI 网卡进行操作需要通过对 WifiManager 对象来进行,获取该对象的方法如下:

    WifiManager wifiManager=(WifiManager) Context.getSystemService(Service.WIFI_SERVICE);

    打开WIFI 网卡:

    wifiManager.setWifiEnabled(true);

    关闭WIFI 网卡

    wifiManager.setWifiEnabled(false);

    获取网卡的当前状态:

    wifiManager.getWifiState();

    示例代码:由于Android模拟器不支持wifi操作,所以例子需要在实体手机上运行

    AndroidManifest.xml

    package="me.bym" android:versionCode="1" android:versionName="1.0">

    Activity

    package me.bym;

    import android.app.Activity;

    import android.content.Context;

    import android.net.wifi.WifiManager;

    import android.os.Bundle;

    import android.view.View;

    import android.view.View.OnClickListener;

    import android.widget.Button;

    import android.widget.Toast;

    public class WifiActivity extends Activity {

    private Button startWifiButton = null;

    private Button shutdownWifiButton = null;

    private Button checkStateButton = null;

    private WifiManager wifiManager = null;

    private String res = ""; // 用来存放操作结果信息的字符串

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    startWifiButton = (Button) findViewById(R.id.StartWifiButton);

    shutdownWifiButton = (Button) findViewById(R.id.ShutdownWifiButton);

    checkStateButton = (Button) findViewById(R.id.CheckStateButton);

    startWifiButton.setOnClickListener(new StartWifiListener());

    shutdownWifiButton.setOnClickListener(new ShutdownWifiListener());

    checkStateButton.setOnClickListener(new CheckStateListener());

    }

    class StartWifiListener implements OnClickListener {

    @Override

    public void onClick(View v) {

    wifiManager = (WifiManager) WifiActivity.this

    .getSystemService(Context.WIFI_SERVICE);

    if (wifiManager.setWifiEnabled(true)) {

    res = "启动wifi服务成功";

    } else {

    res = "启动wifi服务失败";

    }

    Toast.makeText(WifiActivity.this, res, Toast.LENGTH_SHORT).show();

    }

    }

    class ShutdownWifiListener implements OnClickListener {

    @Override

    public void onClick(View v) {

    wifiManager = (WifiManager) WifiActivity.this

    .getSystemService(Context.WIFI_SERVICE);

    if (wifiManager.setWifiEnabled(false)) {

    res = "关闭wifi服务成功";

    } else {

    res = "关闭wifi服务失败";

    }

    Toast.makeText(WifiActivity.this, res, Toast.LENGTH_SHORT).show();

    }

    }

    class CheckStateListener implements OnClickListener {

    @Override

    public void onClick(View v) {

    wifiManager = (WifiManager) WifiActivity.this

    .getSystemService(Context.WIFI_SERVICE);

    switch (wifiManager.getWifiState()) {

    case WifiManager.WIFI_STATE_DISABLED:

    res = "WIFI已关闭";

    break;

    case WifiManager.WIFI_STATE_DISABLING:

    res = "WIFI正在关闭中";

    break;

    case WifiManager.WIFI_STATE_ENABLED:

    res = "WIFI已启用";

    break;

    case WifiManager.WIFI_STATE_ENABLING:

    res = "WIFI正在启动中";

    break;

    case WifiManager.WIFI_STATE_UNKNOWN:

    res = "未知WIFI状态";

    break;

    }

    Toast.makeText(WifiActivity.this, res, Toast.LENGTH_SHORT).show();

    }

    }

    }

    be3bd483eaef73bfc1346ac1c1d1732f.png

    展开全文
  • Android Wifi开发教程

    2018-05-03 17:20:37
    转载自:https://blog.csdn.net/a1533588867/article/details/52459284本文主要讲三个方面:1.wifi热点的创建和关闭2.wifi的搜索和连接3.wifi数据传输一、Wifi热点的创建和关闭 1.权限申请(如果版本大于6.0,还...
  • Android开发Wifi基础教程本文实例讲述了Android开发Wifi的基础知识。分享给大家供大家参考。具体如下:Android提供了WifiManager这个类,通过这个类可以进行wifi相关的各种操作。通过wifiManager = (WifiManager) ...
  • import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import org.xml.sax.InputSource; import org.xml.sax....
  • AndroidWiFi的部分进行简单介绍,有WiFi中的四个主要的类,代码教学。
  • WiFi是一种无线联网技术,比较常见的就是通过无线...AndroidWiFi编程提供了一些重要的包,这些包在android.net.wifi包下面。主要包括以下几个类和接口:1、canResult主要用来描述已经检测出的接入点,包括接入点的...
  • 在上一篇中我们介绍了WiFi热点的创建和关闭,如果你还没阅读过,建议先阅读上一篇文章Android WiFi开发教程(一)——WiFi热点的创建与关闭。 本章节主要继续介绍WiFi的搜索和连接。 WiFi的搜索 /* 搜索wifi热点 ...
  • break; } break; default: ...public void openWiFi() { if (!isWifiEnabled() && null != mWifiManager) { mWifiManager.setWifiEnabled(true); } } 八,关闭WIFI /** 关闭Wifi */ publ
  • Android WiFi开发教程(三)——WiFi热点数据传输

    万次阅读 多人点赞 2016-09-07 16:15:11
    在上一篇文章中介绍了WiFi的搜索和连接,如果你还没阅读过,建议先阅读上一篇Android WiFi开发教程(二)——WiFi的搜索和连接。本篇接着简单介绍手机上如何通过WiFi热点进行数据传输。跟蓝牙通讯一样,WiFi热点数据...
  • 主要介绍了Android开发Wifi基础教程,实例分析了Wifi的各种常见基本技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • 您可能感兴趣的文章:Android获取当前已连接的wifi信号强度的方法在Android里完美实现基站和WIFI定位android开发教程wifi开发示例Android开发之Wifi基础教程Android判断是Wifi还是4G网络代码Android连接指定Wifi的...
  • Android无线Wifi开发

    千次阅读 2016-12-25 18:13:14
    WIFI就是一种无线联网技术,常见的是使用无线路由器。那么在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网。如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为“热点”。
  • WIFI网卡的状态信息都以整型变量的形式存放在 android.net.wifi.WifiManager 类中,有以下状态: WIFI_STATE_DISABLED WIFI网卡不可用 WIFI_STATE_DISABLING WIFI网卡正在关闭 WIFI_STATE_ENABLED WIFI网卡...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,788
精华内容 2,315
关键字:

android wifi开发教程