美文网首页Android知识
腾讯云视频接入初探

腾讯云视频接入初探

作者: 浪漫晨风 | 来源:发表于2017-04-13 11:47 被阅读1497次

    今日来公司的项目要求接入视频,如是根据需求对网易云视频,anychat,腾讯云视频进行了技术调研,因为基于响应时间,降噪等诸多效果的测试,考虑,最终选择了腾讯云视频。因为腾讯云视频刚刚推出不久,demo,文档写的不是太集中,故在集成时出现多个坑。现对集成步骤做一下简单归纳:

    1.集成播放列表:

    直播播放列表需要开通查询统计信息(Beta)

    该接口的相关文档地址:https://www.qcloud.com/document/product/267/6110
    这个接口需要提交工单才会开通,默认是不开通的。
    开通后会产生appid和推流鉴权key (这个东西会在生成sign时使用,sign生成的规则是推流鉴权key直接拼接过期时间)

     String playUrl ="http://statcgi.video.qcloud.com/common_access?"+
                "cmd=1251175924&interface=Get_LiveStat"+
                        "&Param.n.page_no=1"+"&Param.n.page_size=20"+
                        "&t="+time+"&sign="+signValue;
    

    cmd后面需要根据你自己的需要更换成自己的appid,我的核心代码如下:
    sign是推流鉴权key直接拼接过期时间进行md5生成:

    md5工具类:

    public class MD5Utils {
          static String MD5(String sourceStr) {
                String result = "";
                try {
                    MessageDigest md = MessageDigest.getInstance("MD5");
                    md.update(sourceStr.getBytes());
                    byte b[] = md.digest();
                    int i;
                    StringBuffer buf = new StringBuffer("");
                    for (int offset = 0; offset < b.length; offset++) {
                        i = b[offset];
                        if (i < 0)
                            i += 256;
                        if (i < 16)
                            buf.append("0");
                        buf.append(Integer.toHexString(i));
                    }
                    result = buf.toString();
                    System.out.println("MD5(" + sourceStr + ",32) = " + result);
                    System.out.println("MD5(" + sourceStr + ",16) = " + buf.toString().substring(8, 24));
                } catch (NoSuchAlgorithmException e) {
                    System.out.println(e);
                }
                return result;
            }
    
    }
    

    过期时间戳转化工具类:

    public class TimeUtils {
    //日期转化为时间戳
         public static String dateToStamp(String s) throws Exception{
                String res;
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = simpleDateFormat.parse(s);
                long ts = (date.getTime()+300000)/1000;
                res = String.valueOf(ts);
                return res;
            }
         public static String stampToDate(String s){
                String res;
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                long lt = new Long(s);
                Date date = new Date(lt);
                res = simpleDateFormat.format(date);
                return res;
            }
    }
    

    查询时间列表的核心逻辑:

        public static void main(String[] args) throws Exception {
            OkHttpClient client = new OkHttpClient();
           SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
              String time="";
            try {
                //获取当前日期的时间戳
                time = TimeUtils.dateToStamp(sdf.format(new Date()));
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
               System.out.println(time);
                 //推流鉴权key
                String key="7407d5829e270dd92661ffcf06169bcf";
                String signValue=MD5Utils.MD5(key+time);
                String playUrl ="http://statcgi.video.qcloud.com/common_access?"+
                "cmd=1251175924&interface=Get_LiveStat"+
                        "&Param.n.page_no=1"+"&Param.n.page_size=20"+
                        "&t="+time+"&sign="+signValue;
                System.out.println(playUrl);
            Request request = new Request.Builder().url(playUrl).build();
            Response response = client.newCall(request).execute();
            
            if (response.isSuccessful()) {
                System.out.println(response.body().string());
                
            } else {
                throw new IOException("Unexpected code " + response);
            }
    
    

    获取成功会如下显示:

    {"errmsg":"has no stream is living","message":"has no stream is living","output":null,"ret":0,"retcode":0}
    

    如果有推流的话是:

    {"errmsg":"","message":"","output":{"stream_count":1,"stream_info":[{"bandwidth":0.0,"client_ip":"125.46.216.125","flr":1.0,"fps":0,"online":0,"server_ip":"123.138.162.79","speed":0,"stream_name":"8818_b262bb2709","time":"2017-04-13 11:04:13"}],"total_bandwidth":0.0,"total_online":0},"ret":0,"retcode":0}
    

    返回的是json这个由你自己的业务需求定

    2.登录用户体系:

    腾讯提供了两种账户体系,一种是托管的,一种是独立的,托管的是需要注册登录腾讯tls体系,账户管理交由腾讯,独立的就是不对现有用户体系有影响,而是在需要调用腾讯的时候,去到腾讯上验证一下,就像融云的token一样。

    2.1托管体系注册

    android:

    
    accountHelper.TLSStrAccReg("xtfgq", "12345678", new TLSStrAccRegListener() {
                @Override
                public void OnStrAccRegSuccess(TLSUserInfo tlsUserInfo) {
    //                tlsUserInfo.
    
                    Log.e("vv","111");
                }
    
                @Override
                public void OnStrAccRegFail(TLSErrInfo tlsErrInfo) {
                    Log.e("vv","222");
                }
    
                @Override
                public void OnStrAccRegTimeout(TLSErrInfo tlsErrInfo) {
                    Log.e("vv","333");
                }
            });
    

    需要在oncreate中完成初始化,这里面的appid与前面的不同,(特别注意),这个是开通腾讯云云通信里面的那个千万不要搞错。

     accountHelper=TLSAccountHelper.getInstance().init(SettingActivity.this,1251175924,12001,"1.0.1");
    

    托管登录:

      loginHelper = TLSLoginHelper.getInstance()
                    .init(getApplicationContext(), 11270, 12001, "1.0.1");
            loginHelper.TLSPwdLogin("用户帐号", "用户密码".getBytes(), new TLSPwdLoginListener(){
                @Override
                public void OnPwdLoginSuccess(TLSUserInfo tlsUserInfo) {
      final TIMUser user = new TIMUser();
                    user.setIdentifier("用户帐号");
                    user.setAccountType("12001");
                    user.setAppIdAt3rd(String.valueOf(Constants.sdkAppId));
                    TIMManager.getInstance().login(
                            Constants.sdkAppId,                   //sdkAppId,由腾讯分配
                            user,
                            loginHelper.getUserSig("用户帐号"),                    //用户帐号签名,由私钥加密获得,具体请参考文档
                            new TIMCallBack() {//回调接口
    
                                @Override
                                public void onSuccess() {//登录成功
                                    Log.e("vvv","succuss");
                                //根据逻辑跳到不同界面
                                }
    
                                @Override
                                public void onError(int code, String desc) {//登录失败
    
                                    //错误码code和错误描述desc,可用于定位请求失败原因
                                    //错误码code含义请参见错误码表
                                    Log.e("eer","eeror");
    
                                }
                            });
    
                }
    
                @Override
                public void OnPwdLoginReaskImgcodeSuccess(byte[] bytes) {
    
                }
    
                @Override
                public void OnPwdLoginNeedImgcode(byte[] bytes, TLSErrInfo tlsErrInfo) {
    
                }
    
                @Override
                public void OnPwdLoginFail(TLSErrInfo tlsErrInfo) {
    
                }
    
                @Override
                public void OnPwdLoginTimeout(TLSErrInfo tlsErrInfo) {
    
                }
            });
    

    2.2 独立模式,即usersinger需从自己的服务器获得,可参考usersinger生成文档:https://www.qcloud.com/document/product/269/1510

    客户端不需要像刚才那样先登陆tls,然后在成功回调里调用 TIMManager.getInstance().login,而是直接从自己的服务取得usersinger,
    代码如下:

     final TIMUser user = new TIMUser();
                            user.setIdentifier(userid);
                            user.setAccountType("12001");
                            user.setAppIdAt3rd(String.valueOf(Constants.sdkAppId));
                            TIMManager.getInstance().login(
                                    Constants.sdkAppId,                   //sdkAppId,由腾讯分配
                                    user,
                                   sig,                    //用户帐号签名,由私钥加密获得,具体请参考文档
                                    new TIMCallBack() {//回调接口
    
                                        @Override
                                        public void onSuccess() {//登录成功
                                            Log.e("vvv","succuss");
                                        
                                        
    
                                        }
    
                                        @Override
                                        public void onError(int code, String desc) {//登录失败
    
                                            //错误码code和错误描述desc,可用于定位请求失败原因
                                            //错误码code含义请参见错误码表
                                            Log.e("eer","eeror");
    
                                        }
                                    });
    

    最后,不管哪中模式,都需要调用修改昵称的腾讯接口,否则会出现发弹幕上用户名变成数字方面的问题。

     public void setMyNickName(String nickName){
            TIMFriendshipManager.getInstance().setNickName(nickName, new TIMCallBack() {
                @Override
                public void onError(int i, String s) {
    
                }
    
                @Override
                public void onSuccess() {
    
                }
            });
        }
    
    

    3.加入聊天室:

     private void joinIMChatRoom(final String chatRoomId) {
    
            mGroupConversation = TIMManager.getInstance().getConversation(TIMConversationType.Group, chatRoomId);
    
            TIMGroupManager.getInstance().applyJoinGroup(chatRoomId, Constants.APPLY_CHATROOM + chatRoomId, new TIMCallBack() {
                @Override
                public void onError(int i, String s) {
                    //已经在是成员了
                    if (i == Constants.IS_ALREADY_MEMBER) {
    
                        initTIMListener(chatRoomId);
    
                    }
                }
    
                @Override
                public void onSuccess() {
    
                    initTIMListener(chatRoomId);
                }
            });
    
        }
    

    消息监听:

      public void initTIMListener(String chatRoomId) {
            mGroupConversation = TIMManager.getInstance().getConversation(TIMConversationType.Group, chatRoomId);
            TIMManager.getInstance().addMessageListener(msgListener);
    
        }
     /**
         * 群消息回调
         */
        private TIMMessageListener msgListener = new TIMMessageListener() {
            @Override
            public boolean onNewMessages(List<TIMMessage> list) {
                //SxbLog.d(TAG, "onNewMessages readMessage " + list.size());
                //解析TIM推送消息
                parseIMMessage(list);
                return false;
            }
        };
     /**
         * 解析消息回调
         *
         * @param list 消息列表
         */
        private void parseIMMessage(List<TIMMessage> list) {
            List<TIMMessage> tlist = list;
    
            if (tlist.size() > 0) {
                if (mGroupConversation != null)
                    mGroupConversation.setReadMessage(tlist.get(0));
            }
    
    
            for (int i = tlist.size() - 1; i >= 0; i--) {
                TIMMessage currMsg = tlist.get(i);
                for (int j = 0; j < currMsg.getElementCount(); j++) {
                    if (currMsg.getElement(j) == null)
                        continue;
                    TIMElem elem = currMsg.getElement(j);
                    TIMElemType type = elem.getType();
    
                    //系统消息
                    if (type == TIMElemType.GroupSystem) {
                        if (TIMGroupSystemElemType.TIM_GROUP_SYSTEM_DELETE_GROUP_TYPE == ((TIMGroupSystemElem) elem).getSubtype()) {
    
                        }
    
    
                    }
    
                    //最后处理文本消息
                    if (type == TIMElemType.Text) {
                        if (currMsg.isSelf()) {
                            handleTextMessage(elem, name);
                        } else {
                            TIMUserProfile sendUser = currMsg.getSenderProfile();
                           String nick="";
                            if(sendUser!=null){
                                nick=sendUser.getNickName();
                            }else{
                                nick=currMsg.getSender();
                            }
                            handleTextMessage(elem,nick);
                        }
                    }
                }
            }
        }
    
    

    发送消息:

     mGroupConversation = TIMManager.getInstance().getConversation(TIMConversationType.Group, groupId);
    
            mGroupConversation.sendMessage(msg, new TIMValueCallBack<TIMMessage>() {//发送消息回调
                @Override
                public void onError(int code, String desc) {//发送消息失败
                    //错误码code和错误描述desc,可用于定位请求失败原因
                    //错误码code含义请参见错误码表
                    if (code == 85) { //消息体太长
                        if (null != getActivity()) {
                            Toast.makeText(getActivity(), "输入内容太长", Toast.LENGTH_SHORT).show();
                        }
                    } else if (code == 6011) {//群主不存在
                        if (null != getActivity()) {
                            Toast.makeText(getActivity(), "群主不存在", Toast.LENGTH_SHORT).show();
                        }
                    }
    
                }
    
                @Override
                public void onSuccess(TIMMessage timMessage) {//发送消息成功
                    mBoolRefreshLock=false;
                    for (int j = 0; j < timMessage.getElementCount(); j++) {
                        TIMElem elem = (TIMElem) timMessage.getElement(0);
                        if (timMessage.isSelf()) {
                            handleTextMessage(elem, name);
                        } else {
                            TIMUserProfile sendUser = timMessage.getSenderProfile();
                            String name;
                            if (sendUser != null) {
                                name = sendUser.getNickName();
                            }
                            else {
                                name = timMessage.getSender();
                            }
                            //String sendId = timMessage.getSender();
    
                            handleTextMessage(elem,name);
                        }
                    }
                }
            });
        }
    

    处理消息文本:

      /**
         * 处理文本消息解析
         *
         * @param elem
         * @param name
         */
        private void handleTextMessage(TIMElem elem, String name) {
            TIMTextElem textElem = (TIMTextElem) elem;
            if (textElem.getText() != null) {
                refreshTextListView(name, textElem.getText(), Constants.TEXT_TYPE);
            }
    
        }
     /**
         * 消息刷新显示
         *
         * @param name    发送者
         * @param context 内容
         * @param type    类型 (上线线消息和 聊天消息)
         */
        public void refreshTextListView(String name, String context, int type) {
            ChatEntity entity = new ChatEntity();
            entity.setSenderName(name);
            entity.setContext(context);
            entity.setType(type);
            notifyRefreshListView(entity);
            mListViewMsgItems.setVisibility(View.VISIBLE);
            if (mListViewMsgItems.getCount() > 1) {
                if (true)
                    mListViewMsgItems.setSelection(0);
                else
                    mListViewMsgItems.setSelection(mListViewMsgItems.getCount() - 1);
            }
        }
    

    最后实现效果如图:


    2.png

    相关文章

      网友评论

        本文标题:腾讯云视频接入初探

        本文链接:https://www.haomeiwen.com/subject/rxqbattx.html