"碰一碰发视频"是近年来智能硬件领域的新型交互方式。本文将基于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;@Overrideprotected 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() {@Overridepublic void onSuccess() {// 获取本机IP地址WifiP2pGroup group = ...; // 通过requestGroupInfo获取String groupOwnerIP = group.getOwner().deviceAddress;}@Overridepublic 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")) {@Overridepublic 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开源协议