Android Socket 连接设备接收H264裸流数据并解码播放 Demo

这是一个简化版的Android项目,演示如何通过Socket连接硬件设备接收H264裸流数据并进行解码播放。文章介绍了创建Service管理Socket连接、使用aidl接口、在Application中绑定Service和注册广播的步骤,适合初学者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做视频流相关的项目,发现 网上很少这方面的demo,很多都是长篇大论的理论知识,研究的太深,不利于小白快速 上手。所以我提炼了自己项目中这一块的内容,打包个小 demo ,只要 拿去稍作修改基本就能跑了。

基本需求是:硬件设备端有wifi模块,WiFi模块AP模式作为服务端发送信号出来,APP作为客户端,连接wifi模块的热点,形成局域网环境,再通过Socket连接服务端进行通信。 

本文不做深度剖析,只介绍 Demo 中的开发方式。

先看demo结构

很简单,就几个文件。

开发步骤:

一. 创建 Service ,用于管理Socket连接、发送、接收消息。

    Service中,首先定义初始化和释放Socket的 方法,再写一个子线程用来调用Socket的初始化方法开始连接,并发送心跳数据包 。

    /**
     * 发送心跳包  每 3 秒发送一次
     */
    private Handler mHandler = new Handler();
    private Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) { //如果当前时间 - 上一次发送时间 >= 3 秒  再次发送心跳包
                boolean isSuccess = sendMsg("心跳指令");// 发送心跳包内容,自行修改为自己的协议指令
                if (!isSuccess) { //false 发送心跳不成功
                    Intent intent = new Intent(SOCKET_DISCONNECT);
                    sendBroadcast(intent); //发送断开广播  告诉界面
                    mHandler.removeCallbacks(heartBeatRunnable);
                    mReadThread.release();
                    releaseLastSocket(mSocket); //释放socket
                    isConnect=false;
                    new InitSocketThread().start(); //重连
                } else {
                    Intent intent = new Intent(SOCKET_CONNECT);
                    sendBroadcast(intent);
                }
            }
            mHandler.postDelayed(this, HEART_BEAT_RATE);
        }
    };

    /**
     * 初始化socket 并开始发送心跳包
     * 由心跳包控制 socket 重连机制 : 心跳发送失败会重新调用这个方法不断重连,直到连接成功
     */
    private void initSocket() {
        Socket socket = null;
        SocketAddress socketAddress = new InetSocketAddress(HOST ,PORT);
        try {
            socket = new Socket();
            socket.connect(socketAddress,6000); // 6秒超时
            if(socket.isConnected()){
                isConnect=true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        mSocket = new WeakReference<Socket>(socket);
        mReadThread = new ReadThread(socket);
        mReadThread.start();
        mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);// 准备发送心跳包
    }

    /**
     * 释放socket
     * @param mSocket
     */
    private void releaseLastSocket(WeakReference<Socket> mSocket) {
        try {
            if (null != mSocket) {
                Socket sk = mSocket.get();
                if (sk != null) {
                    if (!sk.isClosed()) {
                        sk.close();
                    }
                    sk = null;
                    mSocket = null;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 开始连接socket的线程
     */
    class InitSocketThread extends Thread {
        @Override
        public void run() {
            super.run();
            initSocket();
        }
    }

 接着再定义发送数据的方法和接收数据的子线程。

    /**
     * 发送消息
     * 假设通信协议为 :包头 + 内容长度 + 内容
     * @param msg  内容
     * @return
     */
    public boolean sendMsg(String msg) {
        if (null == mSocket || null == mSocket.get()) {
            return false;
        }
        Socket soc = mSocket.get();
        try {
            if (!soc.isClosed() && !soc.isOutputShutdown()) {
                String message = msg;
                byte[] b_head = MSG_HEAD.getBytes(); //包头
                byte[] b_length = StringUtil.toHH(message.getBytes().length); //内容长度
                byte[] b_msg = StringUtil.arrayCopy(b_head, b_length, message.getBytes()); //拼接组合成完整数据包: 包头 + 内容长度 + 内容
                OutputStream os = soc.getOutputStream();
                os.write(b_msg); //写入完整数据包
                os.flush();
                sendTime = System.currentTimeMillis(); // 每次发送成功数据,就改一下最后成功发送的时间,节省心跳间隔时间
                SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Log.e(TAG, "发送成功的时间:" + dateformat.format(sendTime) + " ---msg=" + message + ",长度=" + message.getBytes().length);
            } else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 接收消息
     * 假设数据包格式为 :包头 4byte + 内容长度 4byte + 内容(裸流)
     * 需要修改为自身项目中的协议 数据格式
     */
    public class ReadThread extends Thread {
        private WeakReference<Socket> mWeakSocket;
        private boolean isStart = true;
        public static final int PACKET_HEAD_LENGTH = 4;//包头长度
        public static final int PACKET_CONTENT_LENGTH = 4;//内容长度
        public ReadThread(Socket socket) {
            mWeakSocket = new WeakReference<Socket>(socket);
        }
        public void release() {
            isStart = false;
            releaseLastSocket(mW
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值