您可以阅读本文,了解Android端互动直播课的集成操作。

Demo运行指引

  1. 前提条件

    开发前的环境要求如下表所示,详情请参见使用限制

    类别 说明
    系统版本 支持Android 4.1及以上。
    API版本 不低于16。
    CPU架构 支持真机架构armeabi、armeabi-v7a、arm64-v8a (不支持模拟器x86架构)。
  2. 获取Demo源码
    如果您需要互动直播课开源示例项目,请添加钉钉群获取:顶顶群码
  3. 运行Demo
    1. 打开Android Studio,点击Open an existing Android Studio project选择demo目录下的ApsaraInteractiveClass_Player。 ApsaraInteractiveClass_Player
    2. 点击Sync Project with Gradle Files按钮同步下工程,下载maven库。Maven
    3. 选择真机,点击build and run按钮进行编译并运行。build and run

快速跑通Demo

在运行Demo前,需先跑通server端的代码,然后将server的请求地址粘贴到com.aliyun.rtc.interactiveclassplayer.constant.Constant文件中的BASE_URL变量,分享地址也需要用户自己将自己的域名复制给BASE_WEB_PLAY变量。

BASE_URL变量,如:https://xxxxxx。

快速跑通

功能实现流程

  1. 项目结构说明

    项目名解释,如下所示:

    • AlivcVoiceCall:功能实现库。
    • AliyunVideoCommon:公共库。
    • app:Demo启动入口。
    • thirdparty-lib:第三方库的引用。
    目录
    • BottomFunctionAdapter:底部功能按钮列表adapter。
    • StudentListAdapter:学生列表adapter。
    • Constant:常量数据管理类,在这配置server端请求域名和分享链接的域名。
    • network:网络请求。
    • play:阿里云播放器。
    • rtc:RTC。
    • ui:放的互动界面和登录界面。
    • util:工具类。
    • view:自定义view。
    目录2
  2. 功能实现流程
    • 学生身份入会。
      1. 初始化播放器(播放器为视频直播产品提供,具体请参考视频直播播放器)。
           //1.初始化
           mAliPlayer = AliPlayerFactory.createAliPlayer(ApplicationContextUtil.getAppContext());
           //先获取配置
           PlayerConfig config = mAliPlayer.getConfig();
           //设置网络超时时间,单位ms
           config.mNetworkTimeout = 30000;
           config.mMaxDelayTime = 100;
           //设置超时重试次数。每次重试间隔为networkTimeout。networkRetryCount=0则表示不重试,重试策略app决定,默认值为2
           config.mNetworkRetryCount = 1;
           //设置配置给播放器
           mAliPlayer.setConfig(config);
           //值范围0-1,此比例是按系统当前音量再乘以此比例就是当前播放的音量
           mAliPlayer.setVolume(1.0f);
           //设置预览surfaceview
           mAliPlayer.setDisplayView(mPlaySurfaceview);
      2. 获取直播链接,获取成功后调用播放器的设置播放资源方法setDataSource()和prepare()。
        OkHttpCientManager.getInstance().doGet(Constant.getLivePlayUrl(), params, new OkhttpClient.HttpCallBack() {
                    @Override
                    public void onSuccess(String result) {
                        isStudentRole = true;
                        if (TextUtils.isEmpty(result)) {
                            return;
                        }
                        try {
                            PlayUrlResponse response = new Gson().fromJson(result, PlayUrlResponse.class);
                            if (response.getData() != null && response.getData().getPlayUrl() != null) {
                                PlayHelper.getInstance().setPlayUrl(response.getData().getPlayUrl().getFlv());
                            }
                            PlayHelper.getInstance().prepare();
                        } catch (JsonSyntaxException e) {
                            e.printStackTrace();
                        }
                    }
        
                    @Override
                    public void onFaild(String errorMsg) {
                        Log.i(TAG, "onFaild: " + errorMsg);
                    }
                });
      3. 在prepare成功回调后调用开始播放方法。
        //准备成功事件
            @Override
            public void onPrepared() {
                mAliPlayer.start();
            }
    • 学生上麦。
      1. 初始化RTC SDK。
         //对h5页面的支持
         AliRtcEngine.setH5CompatibleMode(1);
         mEngine = AliRtcEngine.getInstance(ApplicationContextUtil.getAppContext());
         //设置视频固定横屏显示
         mEngine.setDeviceOrientationMode(AliRtcEngine.AliRtcOrientationMode.AliRtcOrientationModeLandscapeLeft);
         //默认横屏时交换视频宽高
         mEngine.setVideoSwapWidthAndHeight(true, AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
         //默认开启扬声器
         mEngine.enableSpeakerphone(true);
         mEngine.enableHighDefinitionPreview(false);
         //自动发布、手动订阅
         mEngine.setAutoPublishSubscribe(true, false);
      2. 暂停播放器并隐藏。
      3. 以互动模式入会。
        //设置AliRtcAuthInfo用户信息,通过server api获取到用户信息和rtc服务器的token信息,拿到信息后
        //设置给AliRtcAuthInfo就可以调用joinChannel加入频道进行通话
        AliRtcAuthInfo userInfo = “从server端获取”;
        //调用join方法加入房间,displayName用户昵称
        mEngine.joinChannel(aliRtcAuthInfo, displayName);
        //调用joinChannel后在AliRtcEngieEventListener.onJoinChannelResult(int i)接受回调信息
        if (i != 0) {//加入房间失败
            //将本地画面添加到小屏
            addVideoStreamInfo(mRtcAuthInfo.getUserid(), AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera, true);
        } else {
            UIHandlerUtil.getInstance().postRunnable(new Runnable() {
                @Override
                public void run() {
                    mAdapter.initAllBtnStatus();
                    ToastUtils.showInCenter(AlivcClassRoomActivity.this, getString(R.string.alivc_biginteractiveclass_string_hint_join_room_faild));
                }
            });
        }
    • 小大流切换。
      切换大小流之后需要重新订阅,订阅成功后会自动切换,不需要重新设置预览。
      mEngine.configRemoteCameraTrack(userId, master, enable);
       // 订阅远端音频流。
       mEngine.configRemoteAudio(userId, true);
       // 订阅远端屏幕流。
       mEngine.configRemoteScreenTrack(userId, true);
       mEngine.subscribe(userId);
    • 主屏和小屏切换。
      只需要将展示的soponsurfaceview位置互换即可,无需重复订阅。
      AlivcVideoStreamInfo alivcVideoStreamInfo = mAlivcVideoStreamInfos.get(position);
      //将正在显示的id设置给小屏
      if (mDisplayVideoStreamInfo != null) {
          mAlivcVideoStreamInfos.set(position, mDisplayVideoStreamInfo);
          //小屏切换到大流
          RtcManager.getInstance().configRemoteCameraTrack(mDisplayVideoStreamInfo.getUserId(), false, true);
          mDisplayVideoStreamInfo = alivcVideoStreamInfo;
          mStudentListAdapter.notifyItemChanged(position);
      }
      //刷新大屏
      reflushContainerView(alivcVideoStreamInfo);
       AliRtcEngine.AliVideoCanvas aliVideoCanvas = alivcVideoStreamInfo.getAliVideoCanvas();
       if (aliVideoCanvas != null && aliVideoCanvas.view != null) {
           // true 在最顶层,会遮挡一切view
           aliVideoCanvas.view.setZOrderOnTop(false);
           //true 如已绘制SurfaceView则在surfaceView上一层绘制。
           aliVideoCanvas.view.setZOrderMediaOverlay(false);
           mContainerView.removeAllViews();
           mContainerView.addView(aliVideoCanvas.view);
       }
      StudentListAdapter中的bindview代码。
      //已经添加并开始预览就只切换展示的spoonsurfaceview
      if (sophonSurfaceView.getParent() != null) {
          ((ViewGroup) sophonSurfaceView.getParent()).removeView(sophonSurfaceView);
      }
      // true 在最顶层,会遮挡一切view
      sophonSurfaceView.setZOrderOnTop(false);
      //true 如已绘制SurfaceView则在surfaceView上一层绘制。
      sophonSurfaceView.setZOrderMediaOverlay(true);
      mRlContainer.removeAllViews();
      mRlContainer.addView(sophonSurfaceView, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
    • 静音模式。
      静音模式就是停止发布本地音频流。
      mEngine.muteLocalMic(false);
    • 取消静音模式。
      取消静音模式就是发布本地音频流。
      mEngine.muteLocalMic(true);
    • 扬声器模式。
      mEngine.enableSpeakerphone(true);
    • 取消扬声器模式。
      mEngine.enableSpeakerphone(false);
    • 离开房间。
      mEngine.leaveChannel();
    • 摄像头翻转。
      mEngine.switchCamera();
    • 预览本地视频流。
          /**
           * 播放本地视频流
           * @param localAliVideoCanvas canvas
           * @param aliRtcVideoTrackCamera 类型
           */
          public void setLocalViewConfig(AliRtcEngine.AliVideoCanvas localAliVideoCanvas, AliRtcEngine.AliRtcVideoTrack aliRtcVideoTrackCamera) {
              if (mEngine != null) {
                  mEngine.setLocalViewConfig(localAliVideoCanvas, aliRtcVideoTrackCamera);
              }
          }
    • 预览远端视频流。
          /**
           * 设置播放远端视频流
           */
          public void setRemoteViewConfig(AliRtcEngine.AliVideoCanvas aliVideoCanvas, String uid, AliRtcEngine.AliRtcVideoTrack aliRtcVideoTrack) {
              if (mEngine != null) {
                  mEngine.setRemoteViewConfig(aliVideoCanvas, uid, aliRtcVideoTrack);
              }
          }