"碰一碰发视频"是近年来智能硬件领域的新型交互方式。本文将基于Android平台,从零实现一个支持NFC触碰触发、P2P直连传输的视频发送客户端,涵盖近场通信、视频编解码、传输协议等关键技术点,并提供完整代码实现。
技术架构与选型
核心组件
近场通信层:Android Beam(兼容NFC-A/B/F)
传输协议:Wi-Fi Direct + WebSocket(低延迟大文件传输)
视频处理:MediaCodec硬编解码 + H.265压缩
安全验证:ECDH密钥交换 + AES-GCM加密
开发环境
Android Studio 2023.1.1
最低API Level:24(Android 7.0+)
测试设备:需支持NFC与Wi-Fi Direct
核心功能实现
1. NFC触碰事件处理
注册NFC监听并解析NDEF消息:
java
复制
下载
public class NfcActivity extends AppCompatActivity { private NfcAdapter nfcAdapter; @Override protected void onCreate(Bundle savedInstanceState) { // 初始化NFC适配器 nfcAdapter = NfcAdapter.getDefaultAdapter(this); handleIntent(getIntent()); } private void handleIntent(Intent intent) { if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); NdefMessage msg = (NdefMessage) rawMsgs[0]; String payload = new String(msg.getRecords()[0].getPayload()); // 示例:收到设备ID"DEVICE_123456" startVideoTransfer(payload); } } }
2. Wi-Fi Direct连接建立
自动创建P2P群组并获取IP地址:
java
复制
下载
private void setupWifiDirect() { WifiP2pManager manager = (WifiP2pManager) getSystemService(WIFI_P2P_SERVICE); Channel channel = manager.initialize(this, getMainLooper(), null); manager.createGroup(channel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { // 获取本机IP地址 WifiP2pGroup group = ...; // 通过requestGroupInfo获取 String groupOwnerIP = group.getOwner().deviceAddress; } @Override public void onFailure(int reason) { Log.e("WifiDirect", "组网失败: " + reason); } }); }
3. 视频分块传输协议
基于WebSocket实现断点续传:
java
复制
下载
public class VideoSender { private WebSocketClient webSocketClient; public void sendVideo(File videoFile) { try { webSocketClient = new WebSocketClient(new URI("ws://"+targetIP+":8080")) { @Override public void onMessage(ByteBuffer bytes) { // 处理ACK确认包 int blockIndex = bytes.getInt(); if(blockIndex == currentBlock) { sendNextBlock(); } } }; webSocketClient.connect(); // 分块发送(每块2MB) FileInputStream fis = new FileInputStream(videoFile); byte[] buffer = new byte[2 * 1024 * 1024]; while(fis.read(buffer) != -1) { webSocketClient.send(buffer); } } catch (Exception e) { e.printStackTrace(); } } }
性能优化方案
1. 视频预处理流水线
kotlin
复制
下载
val mediaCodec = MediaCodec.createEncoderByType("video/hevc") mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE) mediaCodec.start() // 使用Surface输入提升编码效率 val inputSurface = mediaCodec.createInputSurface() val encoderThread = HandlerThread("VideoEncoder").apply { start() } // H.265硬编码参数设置 val format = MediaFormat.createVideoFormat("video/hevc", width, height).apply { setInteger(MediaFormat.KEY_BIT_RATE, 2_000_000) setInteger(MediaFormat.KEY_FRAME_RATE, 30) setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface) }
2. 传输加速策略
智能分块:根据网络质量动态调整块大小(512KB-4MB)
双通道传输:同时使用Wi-Fi Direct和BLE广播元数据
缓存预取:优先传输视频关键帧(I帧)
安全增强设计
1. 设备身份认证流程
图表
代码
下载
设备B设备A设备B设备A发送NFC挑战码(随机数R1)返回加密的R1+设备证书验证证书签名,生成会话密钥
2. 视频流加密实现
java
复制
下载
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey(); cipher.init(Cipher.ENCRYPT_MODE, secretKey); ByteBuffer outputBuffer = ByteBuffer.allocate(1024); cipher.doFinal(inputBuffer, outputBuffer); // 加密视频块
常见问题排查
问题现象 | 解决方案 |
---|---|
NFC触发无响应 | 检查AndroidManifest.xml是否声明<uses-permission android:name="android.permission.NFC"/> |
传输速度慢 | 在Wi-Fi Direct连接前调用manager.setWifiP2pChannels(149, 0) 指定5GHz频段 |
视频花屏 | 确保接收端H.265解码器支持Main Profile Level 5.1 |
完整项目结构
复制
下载
app/ ├── libs/ │ └── libuvc.so # USB摄像头支持库 ├── src/ │ ├── nfc/ # NFC通信模块 │ ├── transfer/ # 传输协议实现 │ ├── codec/ # 音视频编解码 │ └── ui/ # 交互界面 build.gradle # 依赖配置:implementation 'org.java-websocket:Java-WebSocket:1.5.3'
结语
本文实现了一个支持碰一碰触发、低延迟传输的视频发送客户端。未来可扩展方向包括:
集成WebRTC实现实时视频通话
添加AR滤镜等实时处理功能
支持离线模式下的Mesh网络传输
完整源码已开源(替换为GitHub地址),欢迎开发者共同完善。在商业应用中需注意遵守《网络安全法》对近场通信设备的管理要求。
注意事项:
测试需使用支持H.265硬编码的Android设备
传输大文件时建议外接供电防止电量耗尽
遵循GPL-3.0开源协议