Android通过WiFi建立Socket套接字通信并获取数据

目录

前言

权限申请

获取WIFI信息

建立Socket套接字连接

接收Wifi数据

发送数据

综合代码

使用方式


前言

        本文主要讲述Android 11如何获取WIFI权限并通过TCP/IP协议使用Socket套接字与设备进行通信,由于通信背景是与嵌入式设备通信并不涉及到与互联网操作,所以在这之间没有什么协议加密等相关操作,由于笔者技术有限,本文中所提供源代码仅供参考。

接下来正文开始。

权限申请

        Android使用Wifi通信得先有相应的权限,因为是与连接的设备直接的通信,所以要有这三个权限。权限在开发文件AndroidManifest.xml中申请。这几个权限就是获取连接wifi的主机地址,wifi连接的状态。没有这些权限就建立不了通信。

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

 看好放置的位置,别放错了位置了,不然报错不管。当然,这几个权限不需要动态权限申请。

获取WIFI信息

        之后咱就创建WIfiConnectManager这个工具类封装好变量。这一段就是单纯的使用WIfiManager获取到连接Wifi的地址,如果获取不到就返回null,基本上只有没有连接到wifi或者没有开启Wifi才会返回null。其中Handler就是消息机制,用于接收数据。

public class WifiConnectManager {

    private final String ip;

    private final int port;

    private Socket socket;

    private Handler handler;

    private WifiConnectListener connectListener;

    public ExecutorService executorService = Executors.newCachedThreadPool();

    private WifiConnectManager(String ip, int port){
        this.ip = ip;
        this.port = port;
    }


    public static WifiConnectManager getWifiConnect(Context context, int port){
        WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if(wifiManager != null){
            //TODO 获取WIIF 的ip
            DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
            String ip =  Formatter.formatIpAddress(dhcpInfo.gateway);
            return new WifiConnectManager(ip,port);
        }
        return null;
    }
}

建立Socket套接字连接

        之后在这个类中增加方法connect,这个方法就用作建立连接。可以看到用到了WifiConnectListener,这个是内部类,在下面的全部代码中会放出来,这个类主要监听Wifi的连接状态。在这里用到了线程池(线程池的创建是用提供的方法,虽然Android提示要自己创建我觉得用他提供的就行)之后就是检测Socket是否连接上。当然,网络通信是后台操作 这个一定要注意。

public void connect(final WifiConnectListener listener){
        this.connectListener = listener;
        System.out.println("ip: "+ip);
        if(executorService.isShutdown()){
            executorService = Executors.newCachedThreadPool();
        }
        executorService.execute(() -> {
            if(socket != null && socket.isConnected()){
                try {
                    socket.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            socket = new Socket();
            try {
                socket.connect(new InetSocketAddress(ip,port),3000);
                if(socket.isConnected()){
                    if(listener != null){
                        connectListener.onConnectSuccess();
                        return;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(connectListener != null) {
                connectListener.onConnectError();
            }
        });
    }

接收Wifi数据

        还是在这个类中创建onGetData方法,这个方法得有个锁,切记只能执行一次,你也不想同时接收了多条数据导致出现奇奇怪怪的问题吧。

        之后的这个bytes就很有讲究,他的大小取决于你的协议包一个包的字节的长度,如果有很多就需要你修改这个值了。这个就是引用InputStream的输入流通过while不断的获取数据,while的循环条件是socket保持通信状态,如果不再保持就赶紧跳出去。

public synchronized void onGetData(Handler handler){
    this.handler = handler;
    executorService.execute(() -> {
        while (socket.isConnected()){
            try {
                InputStream stream = socket.getInputStream();
                if(stream != null){
                    //注意这个10是只接收10个字节,如果你觉得你的数据很多。。这个要改
                    //是根据协议改
                    byte[] bytes = new byte[10];
                    int i = stream.read(bytes);
                    Message message = new Message();
                    message.what = 1;
                    message.obj = bytes;
                    WifiConnectManager.this.handler.sendMessage(message);
                }else{
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
                break;
            }
        }
        if(connectListener != null){
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            connectListener.onConnectCancel();
        }
    });
}

发送数据

        发送数据就很简单,发送byte[]字节就可以,使用OutputStream发送,其他人提供的都是发送完就赶紧的close了,咱别这样,不然发一次就直接断开连接收不到数据了。保持好长连接状态(可能你还需要双线程去守护监听是否断开反正看你操作了)。

public synchronized void sendData(final byte[] bytes){
    executorService.execute(() -> {
        if(socket.isConnected()){
            try {
                OutputStream stream = socket.getOutputStream();
                stream.write(bytes);
                
                return;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if(connectListener != null){
            connectListener.onConnectCancel();
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    });
}

综合代码

所有的方法整合起来就是这样的。

import android.content.Context;
import android.net.DhcpInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Message;
import android.text.format.Formatter;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class WifiConnectManager {

    private final String ip;

    private final int port;

    private Socket socket;

    private Handler handler;

    private WifiConnectListener connectListener;

    public ExecutorService executorService = Executors.newCachedThreadPool();

    private WifiConnectManager(String ip, int port){
        this.ip = ip;
        this.port = port;
    }


    /**
     * 获取静态接口
     * @param context Activity
     * @param port 断开               
     * */
    public static WifiConnectManager getWifiConnect(Context context, int port){
        WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if(wifiManager != null){
            //TODO 获取WIIF 的ip
            DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
            String ip =  Formatter.formatIpAddress(dhcpInfo.gateway);
            return new WifiConnectManager(ip,port);
        }
        return null;
    }

    /**
     * 建立连接
     * @param listener 监听器
     * */
    public void connect(final WifiConnectListener listener){
        this.connectListener = listener;
        System.out.println("ip: "+ip);
        if(executorService.isShutdown()){
            executorService = Executors.newCachedThreadPool();
        }
        executorService.execute(() -> {
            if(socket != null && socket.isConnected()){
                try {
                    socket.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            socket = new Socket();
            try {
                socket.connect(new InetSocketAddress(ip,port),3000);
                if(socket.isConnected()){
                    if(listener != null){
                        connectListener.onConnectSuccess();
                        return;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(connectListener != null) {
                connectListener.onConnectError();
            }
        });
    }

    /**
     * 接收Wifi数据 通过消息机制回调
     * @param handler 消息机制
     * */
    public synchronized void onGetData(Handler handler){
        this.handler = handler;
        executorService.execute(() -> {
            while (socket.isConnected()){
                try {
                    InputStream stream = socket.getInputStream();
                    if(stream != null){
                        byte[] bytes = new byte[10];
                        int i = stream.read(bytes);
                        Message message = new Message();
                        message.what = 1;
                        message.obj = bytes;
                        WifiConnectManager.this.handler.sendMessage(message);
                    }else{
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
            }
            if(connectListener != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                connectListener.onConnectCancel();
            }
        });


    }

    /**
     * 发送数据包
     * @param bytes 数据
     * */
    public synchronized void sendData(final byte[] bytes){
        executorService.execute(() -> {
            if(socket.isConnected()){
                try {
                    OutputStream stream = socket.getOutputStream();
                    stream.write(bytes);
                    return;
                } catch (IOException e) {
                    e.printStackTrace();
                }


            }
            if(connectListener != null){
                connectListener.onConnectCancel();
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    /**
     * 关闭socket通信
     * */
    public void close(){
        if(socket != null){
            try {
                socket.close();
                executorService.shutdownNow();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public interface WifiConnectListener {

        /**
         * 回调连接成功
         * */
        void onConnectSuccess();

        /**
         * 回调连接失败
         * */
        void onConnectError();

        /**
         * 回调连接错误
         * */
        void onConnectCancel();

    }

}

使用方式

        推荐在onCreate方法中创建初始化的方法inifSocket,之后再创建Handler消息机制接收。

private void initSocket() {
        wifiConnectManager = WifiConnectManager.getWifiConnect(this,端口);
        wifiConnectListener = new WifiConnectManager.WifiConnectListener() {
            @Override
            public void onConnectSuccess() {
                Toast.makeText(MainActivity.mainActivity, "连接成功", Toast.LENGTH_SHORT).show();
                wifiConnectManager.onGetData(handler);
            }
            @Override
            public void onConnectError() {
                Toast.makeText(MainActivity.mainActivity, "网络错误,请重试", Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onConnectCancel() {
                Toast.makeText(MainActivity.mainActivity, "连接断开", Toast.LENGTH_SHORT).show();
            }
        };
        if(wifiConnectManager != null) {
            wifiConnectManager.connect(wifiConnectListener);
        }else{
            Toast.makeText(this, "网络错误,请重试", Toast.LENGTH_SHORT).show();
        }
    }

消息机制接收:

public Handler handler = new Handler(Looper.myLooper()){
        @Override
        public void handleMessage(@NonNull Message msg) {
            if(msg.what == 1){

                //TODO 接收数据
                byte[] bytes = (byte[])msg.obj;
                StringBuilder stringBuilder = new StringBuilder();
                for (byte b:bytes
                     ) {
                    stringBuilder.append(String.format("%X",b)).append(" ");

                }
                //打印
                Log.i("socket",stringBuilder.toString());
                
            }
        }
    };

猜你喜欢

转载自blog.csdn.net/qq_38174131/article/details/129725075
今日推荐