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;

    public Activity context;

    private Handler handler;

    private WifiConnectListener connectListener;

    public ExecutorService executorService = Executors.newCachedThreadPool();

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


    public static WifiConnectManager getWifiConnect(Activity 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(context,ip,port);
        }
        return null;
    }
}

建立Socket套接字连接

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

public void connect(final WifiConnectListener listener){
        this.connectListener = listener;
        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),6000);
                if(socket.isConnected()){
                    if(listener != null){
                        connectListener.onConnectSuccess();
                        return;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(connectListener != null) {
                context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        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();
                }
                context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        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);
                    stream.flush();
                    //如果要保持长连接 就不要关闭
//                    stream.close();
                    return;
                } catch (IOException e) {
                    e.printStackTrace();
                }


            }
            context.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(connectListener != null){
                        connectListener.onConnectCancel();

                    }
                }
            });
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

综合代码

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


import android.app.Activity;
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;

    public Activity context;

    private Handler handler;

    private WifiConnectListener connectListener;

    public ExecutorService executorService = Executors.newCachedThreadPool();

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


    public static WifiConnectManager getWifiConnect(Activity 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(context,ip,port);
        }
        return null;
    }

    public void connect(final WifiConnectListener listener){
        this.connectListener = listener;
        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),6000);
                if(socket.isConnected()){
                    if(listener != null){
                        connectListener.onConnectSuccess();
                        return;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(connectListener != null) {
                context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        connectListener.onConnectError();
                    }
                });

            }
        });
    }

    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();
                }
                context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        connectListener.onConnectCancel();
                    }
                });

            }
        });


    }

    public synchronized void sendData(final byte[] bytes){
        executorService.execute(() -> {
            if(socket.isConnected()){
                try {
                    OutputStream stream = socket.getOutputStream();
                    stream.write(bytes);
                    stream.flush();
                    //如果要保持长连接 就不要关闭
//                    stream.close();
                    return;
                } catch (IOException e) {
                    e.printStackTrace();
                }


            }
            context.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(connectListener != null){
                        connectListener.onConnectCancel();

                    }
                }
            });
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }


    public void close(){
        if(socket != null){
            try {
                socket.close();
            } 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());
                
            }
        }
    };

发送数据

if(connectManager != null){
    //你要发送的字节
    byte[] b1 = new byte[10];
    wifiConnectManager.sendData(b1);
}

  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值