跳转至

Android 集成方法

1. 前言

在你阅读此文档时,我们假定您已具备基础的 Android应用开发经验,并能够理解相关基础概念.

1.1 请联系拓课销售人员获取拓课云平台企业账号

1.2 请到拓课云官方网站下载TalkCloud Android sdk

1.3 此demo的targetSdkVersion为31 ,minsdk为23, gradle 为4.4 , 请调校好本地环境

1.4 SDK aar 包在目录 talkplus/app/lib 下分别为 :

classroomsdkrelease(底层库-必须导入)

WhiteBoardSDK-release(课件白板UI库-必须导入)

eduhdsdkrelease(教室ui库-必须导入)

2 集成步骤

2.1.1 如果使用拓课云plus 样式则修改App ID, 图标, 包名, FileProvide 和 AutoUpdateUtil.Class中companydimain对应的公司域名即可.

2.1.2 aar方式集成,将 talkplus/app/lib 下 aar 文件拷贝到自己项目的 lib 目录下, 并通过 implementation fileTree方式, 引用由于本sdk中的ui库引用了第三方样式, 需要通过重新导入三方库才可正常使用
注意 有三方库冲突的引用需改为本sdk的版本,如无法改动需要联系商务或者收获 告之需求重新获取sdk

2.2.3 gradle设置: 添加下列代码后,执行gradle编译, 下载第三方库资源:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//非必选 教室内需要语音字幕功能的依赖。(此功能收费请找商务了解开通)
implementation 'com.microsoft.cognitiveservices.speech:client-sdk:1.24.0'

//必需依赖
implementation 'com.llew.huawei:verifier:1.1.2'
implementation com.android.support:appcompat-v7:28.0.0
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.tencent.edu:TAISDK:1.2.3.89''

//如果只使用互动课堂相关(一对一,一对多教室),可以不引用tencent相关包, 如下:
implementation 'com.tencent.liteav:LiteAVSDK_Professional:9.5.11346'

2.2 配置Application

1
2
3
4
5
6
    ScreenScale.init(this);//适配方案
    TKPluginsManager.getInstance().setContext(this).setShareData("appId"/微信,"appSecret"/微信).setStatisticsData("appId","channel").init();//配置umeng 具体详见2.5
    //解决通过反射解决在HuaWei手机出现Register too many Broadcast Receivers的crash
    if (!Tools.phoneIsSony(context)) {
        LoadedApkHuaWei.hookHuaWeiVerifier(this);
    }

2.3 配置相关参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//设置教室内通知样式的app名称
FunctionSetManage.getInstance().setAppName(R.string.app_name);
//设置教室内通知样式logo
FunctionSetManage.getInstance().setAppLogo(R.drawable.tk_logo);
//设置进入教室时是否跳过设备检测页面(选择添加)
FunctionSetManage.getInstance().setIsSkipDeviceTesting(this,false);
//设置关闭崩溃日志收集的弹窗
FunctionSetManage.getInstance().setIsSkipCrashHandleDialog(true);
//设置关闭功能引导(选择添加)
FunctionSetManage.getInstance().setIsGuide(getApplicationContext(),true);
//设置进教室的音量百分比(选择添加)
FunctionSetManage.getInstance().setMaxVolume(0.5);
//设置教室crash时日志收集的标识 例:talk
FunctionSetManage.getInstance().setCarshEnterprise("talk");
//显示崩溃弹窗 4634版本新增
FunctionSetManage.getInstance().setIsSkipCrashHandleDialog(true);
//是否开启设备检测上报 默认不开启
FunctionSetManage.getInstance().setReportDeviceTest(true);
//日志异常捕获-拓课云
new CrashHandler(this);
//是否显示教室内部设置弹框隐私协议,默认不显示
FunctionSetManage.getInstance().setIsShowSettingPrivacyAgreement(this, false);
//针对非老师端的设置, 默认false下课后 非老师端不直接退出教室 弹出课程结束界面。设置ture,非老师端不会弹出结束界面 直接退出  toast 提示课程结束(4.15.1.4新增配置项)
FunctionSetManage.getInstance().setDirectExit(false);

2.3.1 单独设备检测页

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//是否开启设备检测上报 默认不开启
FunctionSetManage.getInstance().setReportDeviceTest(true);

/**
* 进入动态设备检测页面
*
* @param domain   企业域名
* @param userid   用户id
* @param activity
  */
  public void joinDynamicDeviceTesting(Activity activity, String domain, String userid) {
  Intent intent = new Intent(activity, DynamicDeviceTestingActivity.class);
  intent.putExtra("domain", domain);
  intent.putExtra("userid", userid);
  activity.startActivity(intent);
  }

 ```

2.4 进入教室

2.4.1 注册进入教室信息回调

实现接口
<li>MeetingNotify</li>
<li>JoinmeetingCallBack</li>

``` java
//注册接口:
RoomClient.getInstance().regiestInterface(this,this);

2.4.2 进入教室 ( RoomClient.class )

调用joinRoom方法之后, 如果加入房间不成功,会有相对应的错误回调如下:

|MeetingNotify 接口介绍| 说明| |--|--| |void onKickOut(int var1)|

  • var1=0: 您已被老师请出教室!
  • var1=1: 有相同身份的用户进入!
  • var1=401: 当前课程已结束
  • var1=402: 当前课程已被取消
  • | |void onWarning(int var1) |
  • var1=1: 没有视频权限
  • var1=2: 没有音频权限
  • | |void onClassBegin()| 课程开始| |void onClassDismiss()| 课程结束| |void onLeftRoomComplete()| 离开课堂成功后的回调| |void onEnterRoomFailed(int result,String desc)|
  • result=失败原因代码
  • desc=失败的原因描述
  • | |void joinRoomComplete()| 进入课堂成功后的回调| |void onCameraDidOpenError()| 摄像头打开失败回调|

    2.4.3 上课 方法 joinRoom 调用方式

    1
    2
    3
    4
    5
    6
    7
    8
        //param:Map格式,内含进入房间所需的基本参数,例如:
        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put("serial", "12345678"); 房间号
        params.put("password", "1111"); 预约房间时指定的密码注意不同身份对应不同密码
        params.put("nickname","tom");本地用户的昵称
        params.put("userrole",2);学生2老师0旁听生6巡课4
        //params.put("userid","111");用户id,可选(相同id 会互踢慎用)
        RoomClient.getInstance().joinRoom(this, params);
    

    2.4.4 播放回放(常规录制件,含记录播放进度选填) 方法 joinPlayBackRoom

    1
    2
    3
    4
    5
    6
    7
    8
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("domain", "www");//企业id
    //域名加端口号+回放路径
    params.put("path","global.talk-cloud.net:8081/749f3185-eadb-475b-83ed-b5944430be43-1414270898/");
    params.put("serial", "1008611");//教室号
    params.put("recordtitle", "*******");//根据后台返回的数据(回放标题)
    params.put("skipTime", "30");//进度值,秒(记录播放进度时才传)
    RoomClient.getInstance().joinPlayBackRoom(this, params);
    

    2.4.5 播放回放(MP4视频) 方法 joinPlayMp4Back

    RoomClient.getInstance().joinPlayMp4Back (this, “MP4播放地址”);

    1
    2
    3
    4
    5
    6
    7
    进入mp4的播放页面需要记录时长的
    *
    @param activity
    @param mp4Url mp4 播放地址
    @param skipTime 当前进度时长
    */
    public void joinPlayMp4Back(Activity activity,String mp4Url,String skipTime)
    

    2.4.6加载不同的gif需要调用的方法

    SkinTool.getmInstance().setLoadingImg(Object loadingImg);参数可以是String类型的url或者本地int类型drawable

    Caution

    1
    2
    3
    1、在app首页的onCreate里面调用,并且需要在SkinTool.getmInstance().setLoadingSkin(this, loadingImageView);方法之前调用
    2、不需要替换loading GIF的话不需要调用
    3、当需要链接进教室的时候需要在handleIntentemm方法里面添加
    

    2.4.7 进入播放mp4 回放 调用方法 带统计

    1
    2
    3
    4
    5
    6
    7
    8
        Map<String, String> params = new HashMap<String, String>();
        params.put(user_id, “”); //用户id
        params.put(company_id, “”);//企业id
        params.put(mp4Title, “”);//标题
        params.put(recordtitle, “”);//需要服务端返回
        params.put(mp4Url, https://recorddemo.talk-cloud.net/987c9582-5680-4de7-beae-b18ccdb1406b-141912260/record.mp4");//回放地址
        params.put(serial, “”);//教室号
        RoomClient.getInstance().joinPlayBackMp4(this,params);
    

    2.5 功能接口

    必须导入TalkPlusFunctionDomain-release 该版本只开放了 umeng统计和分享的接口实现,不需要umeng统计和分享的客户可以不再依赖三方库的包了 以下三种方式都需要在application里配置

    2.5.1 不需要umeng功能

    1
    2
    在application里配置
    TKPluginsManager.getInstance().setContext(this).setPluginShareType(TKPluginsConstants.PLUGIN_SHARE_TYPE_NONE).setPluginStatisticsType(TKPluginsConstants.PLUGIN_STATISTICS_TYPE_NONE).init();
    

    2.5.2 需要umeng功能 由拓课云实现此功能

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    在application里配置
            TKPluginsManager.getInstance().setContext(this).setShareData("appId"/微信,"appSecret"/微信).setStatisticsData("appId","channel").init();
            并依赖 //友盟基础组件
            //友盟统计
            //友盟基础组件
            implementation'com.umeng.umsdk:common:9.3.8'
            implementation'com.umeng.umsdk:asms:1.2.2' // asms包依赖(必选)
            implementation'com.umeng.umsdk:oaid_lenovo:1.0.0' // (可选)
            implementation'com.umeng.umsdk:oaid_mi:1.0.0' // (可选)
            implementation'com.umeng.umsdk:oaid_oppo:1.0.4' // (可选)
            implementation'com.umeng.umsdk:oaid_vivo:1.0.0.1' // (可选)
            implementation'com.umeng.umsdk:crash:0.0.4' // native crash包依赖(必选)
            implementation'com.umeng.umsdk:share-core:7.1.4' //友盟分享核心库
            implementation'com.umeng.umsdk:share-board:7.1.4'
            implementation'com.umeng.umsdk:share-wx:7.1.4'
    

    2.5.3 需要umeng 功能 自己实现

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    在application里配置
     TKPluginsManager.getInstance().setContext(this).setShareApi(new TkShareApi() {
            @Override
            public void initShare(Context context) {
    
            }
    
            @Override
            public boolean isShowShareButton(Context context) {
                return false;
            }
    
            @Override
            public void onShare(Context context, String shareLink, String shareTitle, String sharePic, String shareDesc, CallBack callBack) {
    
            }
    
            @Override
            public void onUmengActivityResult(int requestCode, int resultCode, Intent data) {
    
            }
    
            @Override
            public void onRelease() {
    
            }
    
        }).setStatisticsApi(new TkStatisticsApi() {
            @Override
            public void initStatistics(Context context) {
    
            }
    
            @Override
            public void onEventObject( String eventId, HashMap map) {
    
            }
    
        }).init();
    

    |TKPluginsManager |方法介绍 |说明 |--|--|--| |setContext(Context context) |设置上下文| Context 上下文 |setPluginShareType(int type ) |分享 |TKPluginsConstants.PLUGIN_SHARE_TYPE_UMENG,TKPluginsConstants.PLUGIN_SHARE_TYPE_NONE |setPluginStatisticsType(int type) |统计 |TKPluginsConstants.PLUGIN_STATISTICS_TYPE_NONE,TKPluginsConstants.PLUGIN_STATISTICS_TYPE_UMENG |setShareApi(TkShareApi shareApi) |分享自定义实现 |TkShareApi实现类 |setStatisticsApi(TkStatisticsApi statisticsApi) |统计自定义实现 |TkStatisticsApi实现类 |setStatisticsData(String statisticsAppKey, String statisticsChannel) |友盟统计需要参数 |友盟统计appKey,友盟统计渠道 |setShareData(String shareAppId, String shareAppSecret) |微信分享参数 微信申请APPId,APPSecret |init() |初始化设置 |

    |TkShareaApi| 接口介绍| 说明 |--|--|--| |void initShare(Context context ) |上下文 |Context 上下文 |boolean isShowShareButton(Context context) |是否显示分享按钮 |Context 上下文 |void onShare(Context context, String shareLink, String shareTitle, String sharePic, String shareDesc, CheckBox playShare) |分享 shareLink,分享链接, shareTitle标题, sharePic 图片, shareDesc描述, playShare 分享按钮分享成功后手动置为false |void onUmengActivityResult(int requestCode, int resultCode, Intent data) |分享回调 |requestCode 请求code, resultCode返回code, Intent data 数据 |void onRelease()| 释放| 无

    |TkStatisticsApi |接口介绍| 说明 |--|--|--| |void initStatistics(Context context) |初始化统计sdk |Context 上下文 |void onEventObject( String eventId, HashMap map) |eventId:login_page_select_role 登录页面选择身份,上报设备类型和用户身份 |Role 0:老师,1:助教,2:学生,4:巡课 暂无使用 | |eventId: video_layout 上报视频布局类型 |layoutType: 视频居右,视频居左,主讲布局,自由布局 | |eventId: user_list_icon_click 花名册点击事件上报 |key, value: 取消/授权画笔,打开/关闭麦克风,加入/移除黑名单,设为/取消 主讲人,上下台 | |eventId: video_list_icon_click 视频上控件点击事件上报 |key, value: 取消/授权画笔,打开/关闭麦克风,加入/移除黑名单,设为/取消 主讲人,上下台,奖励减少奖杯,打开关闭摄像头,视频交换,视频复位 | |eventId: all_control 全体场控 |key, value:全体开关麦,全体允许禁止翻页课件,全体奖励,全体复位 | |eventId: chat_page_translate 聊天页面翻译事件 |key, value: 全体开关麦,全体允许禁止翻页课件,全体奖励,全体复位

    3 常见问题

    • 进入教室 加载动画
    1
    java.lang.ClassCastException:SkinCompatLinearLayout cannot be cast to relativelayout
    

    解决方法 : 加载动画xml不使用标签加载,提取xml文件至include处

    • 如何替换 logo 在 app 模块的 drawable 目录下 tk_logo.png

    • 奖杯动画过程中,缩放动画在某些机型上会显示不全,原因是动画被父布局遮盖

    解决方案:允许子view超过父布局即可,即给父view设置属性

    1
    2
             android:clipChildren="false"
             android:clipToPadding="false"
    

    参考

    参考文件1:RefDoc#01

    参考文件2:RefDoc#02

    参考文件3:RefDoc#03

    • 集成xwalk时出现 error inflating class org.xwalk.core.xwalkview (3.2.4以前版本)

    解决方案:build.gradle中android/defaultConfig下添加

    1
    2
    3
        ndk {
            abiFilters "armeabi", "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    
    • 集成过程中在某一些机型上出现进教室崩溃 (3.2.4以前版本)

    报错:PackageManager$NameNotFoundException: com.google.android.gms

    原因:webview和XWalkView冲突导致的

    解决方案:建议把项目中的webview换成XWalkView,XWalkView的用法和webview极其类似。而且比webview兼容性更好。

    • 使用https协议,joinRoom函数的参数port (端口) 传443。RoomClient中TKRoomManager.useSecureSocket改为true。

    • 当需要多页面进入教室时A-B,需要在A页面重新注册监听 B页面不用调用 RoomClient.getInstance().resetInstance();

    使用AutoSize框架的时候,出现UI错误的时候,需要在application里面初始化如下方法 当使用fragment适配时AutoSizeConfig.getInstance() .setCustomFragment(true);需要在进入教室时callback回调code等于0的时候设置为false,退出教室的时候设置成true

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(DeviceTestingActivity.class);        
    
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(LargeClassRoomActivity.class); 
    
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(LivePlayBackActivity.class);         
    
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(OneToManyActivity.class); 
    
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(OneToOneActivity.class); 
    
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(VideoViewPlayActivity.class); 
    
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(HelpWebViewActivity.class); 
    
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(TKEndClassActivity.class); 
    
     AutoSizeConfig.getInstance().getExternalAdaptManager().addCancelAdaptOfActivity(TransparentActivity.class);
    
    • 3.6.2 以后集成了umeng分享 需要在app 下的build.gradle 的defaultConfig 里添加
    1
    manifestPlaceholders = [qqappid: 1106834082]
    
    • 3.6.3 版本以后无需配置,根据功能接口配置来确定是否需要umeng功能

    • 3.6.4 版本后 把请求权限放入在进入教室流程里,需要把之前版本集成的请求权限代码删除 并按照新文档 在activity里添加 权限请求结果回调代码 详见文档-进入教室 2.4.1.1

    © 2016-2023 北京拓课网络科技有限公司 版权所有  京ICP备17018423号-1 京公网安备11010502043461号