如何使用Wearable ChannelClient sendFile传输PNG及附加数据并打包解析
实现方案
核心思路
自定义二进制打包格式,将附加数据和PNG文件拼接为一个完整文件传输,接收端按约定格式拆分即可,无需修改ChannelClient的原有传输逻辑。
你可以参考如下约定的打包格式(可根据自己需求调整字段长度):
- 前4字节:PNG文件的总字节长度(int类型)
- 接下来4字节:需要传输的int类型附加数据
- 接下来1字节:布尔类型附加数据(0对应false,1对应true)
- 接下来4字节:文本附加数据的UTF-8编码字节长度
- 接下来N字节:文本附加数据的UTF-8编码内容
- 剩余所有字节:原始PNG文件的二进制内容
手机端发送代码调整
先按上述格式拼接生成临时传输文件,再调用sendFile发送:
// 1. 读取原始PNG文件 File pngFile = new File("/data/user/0/com.xxx.yyy/files/test.png"); byte[] pngBytes = Files.readAllBytes(pngFile.toPath()); // 2. 准备附加数据(替换为实际业务数据) int extraInt = 123; boolean extraBool = true; String extraText = "测试附加文本"; byte[] textBytes = extraText.getBytes(StandardCharsets.UTF_8); // 3. 按约定格式拼接为完整的传输字节 ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(pngBytes.length); // PNG长度 dos.writeInt(extraInt); // int附加数据 dos.writeByte(extraBool ? 1 : 0); // 布尔附加数据 dos.writeInt(textBytes.length); // 文本长度 dos.write(textBytes); // 文本内容 dos.write(pngBytes); // PNG内容 dos.flush(); byte[] transferBytes = baos.toByteArray(); // 4. 生成临时传输文件 File transferFile = new File(getFilesDir(), "transfer_temp.bin"); FileOutputStream fos = new FileOutputStream(transferFile); fos.write(transferBytes); fos.close(); // 5. 调用ChannelClient发送临时文件 channelClient.sendFile(channel, Uri.fromFile(transferFile)).addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { Log.d(TAG, "channelTest.sendFile.onComplete: "); // 发送完成后可删除临时文件 transferFile.delete(); } });
可穿戴设备端接收代码调整
收到文件后按约定格式拆包,分别解析出附加数据和PNG文件:
@Override public void onChannelOpened(@NonNull ChannelClient.Channel channel) { super.onChannelOpened(channel); Log.d(TAG, "onChannelOpened: node=" + channel.getNodeId() + "; path=" + channel.getPath() + ";"); // 接收完整的传输文件 File transferFile = new File(getApplicationContext().getFileStreamPath("transfer_temp.bin").getPath()); final Uri fileUri = Uri.fromFile(transferFile); Wearable.getChannelClient(getApplicationContext()).receiveFile(channel, fileUri, false); Wearable.getChannelClient(getApplicationContext()).registerChannelCallback(new ChannelClient.ChannelCallback() { @Override public void onInputClosed(@NonNull ChannelClient.Channel channel, int i, int i1) { super.onInputClosed(channel, i, i1); Log.d(TAG, "onInputClosed: "); try { // 读取传输文件的所有字节 byte[] transferBytes = Files.readAllBytes(transferFile.toPath()); DataInputStream dis = new DataInputStream(new ByteArrayInputStream(transferBytes)); // 按约定格式拆包 int pngLength = dis.readInt(); int extraInt = dis.readInt(); boolean extraBool = dis.readByte() == 1; int textLength = dis.readInt(); byte[] textBytes = new byte[textLength]; dis.read(textBytes); String extraText = new String(textBytes, StandardCharsets.UTF_8); byte[] pngBytes = new byte[pngLength]; dis.read(pngBytes); // 解析PNG为Bitmap Bitmap image = BitmapFactory.decodeByteArray(pngBytes, 0, pngLength); // 此处可处理解析出来的附加数据和PNG图片 Log.d(TAG, "解析到的附加数据:int=" + extraInt + ",布尔=" + extraBool + ",文本=" + extraText); // 用完可删除临时传输文件 transferFile.delete(); } catch (IOException e) { e.printStackTrace(); } Wearable.getChannelClient(getApplicationContext()).close(channel); } }); }
注意事项
- 打包和解包的字段顺序、长度必须完全一致,否则会出现解析错误
- 如果附加文本可能包含特殊字符,统一使用UTF-8编码避免乱码
- 大文件传输时建议添加进度监听,避免ANR
内容的提问来源于stack exchange,提问作者lcj
相关产品推荐
相关产品推荐

