融云如何支持视频消息的功能
融云正式的视频消息还在开发当中 目前 IMLib 完全可以自行开发 , IMKit 也可以通过如下的方式进行视频消息的发送
- /**
- * 发送图片消息上传到服务器
- * @param firstImgPath 视频第一帧画面的本地 path
- * @param videoPath 视频存储的本地路径
- * @param mConversationType 会话类型
- * @param targetId 目标id
- */
- public void sendVideoMessage(String firstImgPath,final String videoPath, Conversation.ConversationType mConversationType,String targetId) {
- if (TextUtils.isEmpty(firstImgPath)) {
- new RuntimeException(“firstImgPath is null”);
- return;
- }
- File f = new File(firstImgPath);
- if (!f.exists()) {
- new RuntimeException(“image file is null”);
- return;
- }
- if (TextUtils.isEmpty(videoPath)) {
- new RuntimeException(“videoPath is null”);
- return;
- }
- if (mConversationType == null) {
- new RuntimeException(“ConversationType is null”);
- return;
- }
- if (TextUtils.isEmpty(targetId)) {
- new RuntimeException(“targetId is null”);
- return;
- }
- ImageMessage imageMessage = ImageMessage.obtain(Uri.parse(“file://” + firstImgPath), Uri.parse(“file://” + firstImgPath));
- io.rong.imlib.model.Message message = io.rong.imlib.model.Message.obtain(targetId, mConversationType, imageMessage);
- RongIM.getInstance().getRongIMClient().sendImageMessage(message, null, null, new RongIMClient.SendImageMessageWithUploadListenerCallback() {
- @Override
- public void onAttached(final io.rong.imlib.model.Message message, final RongIMClient.uploadImageStatusListener watcher) {
- message.setSentStatus(Message.SentStatus.SENDING);
- RongIMClient.getInstance().setMessageSentStatus(message.getMessageId(), message.getSentStatus());
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- ImageMessage img = (ImageMessage) message.getContent();
- img.setLocalUri(Uri.parse((videoPath)));
- io.rong.imlib.model.Message msg = io.rong.imlib.model.Message.obtain(message.getTargetId(), message.getConversationType(), img);
- RongIMClient.getInstance().uploadMedia(msg, new RongIMClient.UploadMediaCallback() {
- @Override
- public void onProgress(io.rong.imlib.model.Message message, int progress) {
- watcher.update(progress);
- }
- @Override
- public void onError(io.rong.imlib.model.Message message, RongIMClient.ErrorCode errorCode) {
- watcher.error();
- }
- @Override
- public void onSuccess(io.rong.imlib.model.Message message) {
- watcher.success();
- }
- });//
- }
- };
- new Handler().post(runnable);
- }
- @Override
- public void onError(io.rong.imlib.model.Message message, RongIMClient.ErrorCode code) {
- }
- @Override
- public void onSuccess(io.rong.imlib.model.Message message) {
- message.setSentStatus(Message.SentStatus.SENT);
- RongIMClient.getInstance().setMessageSentStatus(message.getMessageId(), message.getSentStatus());
- }
- @Override
- public void onProgress(io.rong.imlib.model.Message message, int progress) {
- }
- });
- }
对上面这段代码做下讲解 : 上面的代码片段已经封装好了一个完整的 可以直接发送视频的方法 只要你是集成的 融云 2.26+ 以上的版本 你就可以把上面的代码 copy 过去直接用了 注意 cpoy 过去需要自己处理一下包名
然后我们看看 四个参数 : 会话类型 和 id 就不用多解释了 这个来确定你需要像谁发这个消息 , fristImgPath 这个参数就是视频的 第一帧的图 这个是个 file:/// 的本地路径 因为最终消息是需要在会话界面上做展示 然后你看到的第一帧的图片点击以后 开始下载播放视频 再来看 videoPath 也是一个本地的 视频路径 下面我们来看一下具体用法:
通过上图可见 我已经准备好了一个 测试的 videotest.mp4 视频文件 5MB
- //获取到 视频的 第一帧的 bitmap
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- mmr.setDataSource(“/storage/sdcard1/DCIM/Camera/videotest.mp4”);
- Bitmap bitmap = mmr.getFrameAtTime();
- String firstPath = saveMyBitmap(“firstImagePath”,bitmap);
- RongIM.getInstance().sendVideoMessage(firstPath,“file:///storage/sdcard1/DCIM/Camera/videotest.mp4”, Conversation.ConversationType.PRIVATE,“32324”);
- finish();
- }
- });
- String[] versionInfo = getVersionInfo();
- mCurrentVersion.setText(versionInfo[1]);
- }
- public String saveMyBitmap(String bitName,Bitmap mBitmap){
- File f = new File(“/storage/sdcard1/DCIM/Camera/” + bitName + “.png”);
- try {
- f.createNewFile();
- } catch (IOException e) {
- }
- FileOutputStream fOut = null;
- try {
- fOut = new FileOutputStream(f);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
- try {
- fOut.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- try {
- fOut.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return “/storage/sdcard1/DCIM/Camera/” + bitName + “.png”;
- }
通过上面代码 您可以看到 我先获取本地的 视频文件路径 然后通过 Android 的 Media 获取到了视频的第一帧的 bitmap 然后通过 saveMyBitmap() 方法 将bitmap 转换为保存为本地 路径 并且返回 uri 给我 这样先获取到了第一帧的参数 视频的 路径我们已经有的 然后就可以直接对某个用户做发送了
当我先调用获取第一帧的方法 我们先看看 手机内到底生成了那张图片没有
目前可以根据上图看到 第一帧 在调用过方法后 已经生成 1.97MB 有点大 这么是测试 所以没有进行压缩 有需要的开发者在这里可以自行进行压缩 路径 和 文件名也和我们上面代码中的相吻合
下面我们来看一下 视频第一帧展示在界面上 并且视频上传的进度展示 由于此处进度最好需要视频来展示 这边笔者截取了好几帧的发送过程给大家做展示
可以从上图看到 视频在界面上首先展示了第一帧的 图片 然后上传视频的 进度也一直在刷 35% 74% 88% 到最后发送完成的图片在下面
到此时这个视频消息已经发送完成 视频已经通过融云的 uploadMidea 上传到了 七牛的存储上 变成了一个 RetomeUri 远程路径 接收端也是一样的道理 可以在接收消息的监听里面获取到 这个 ImageMessage (此处完善后应该是 VideoMessage) 两者效果一样都是 调用 uploadMidea 向云上做存储 , 接收端再消息体里面获取到这个 RetomeUri 就可以根据这个 RetomeUri 然后调用 downloadMidea (此方法是向七牛去下载这个视频) 下载到接收端 然后自行做处理
注意:uploadMidea downloadMidea 是融云提供的上传下载方法 此处你可以上传到自己的服务端做存储 另外需要注意的是 在 sendVideoMessage() 方法内 也有 上传进度的回调 我们使用了这个进度 然后也可以看到上面图片上 有视频上传的进度