Procházet zdrojové kódy

增加腾讯SDK版本网络教室module

Pq před 1 rokem
rodič
revize
1ebd52889b
100 změnil soubory, kde provedl 7369 přidání a 0 odebrání
  1. 13 0
      BaseLibrary/src/main/java/com/cooleshow/base/utils/LOG.java
  2. 17 0
      BaseLibrary/src/main/java/com/cooleshow/base/utils/helper/QMUIDisplayHelper.java
  3. 34 0
      BaseLibrary/src/main/java/com/cooleshow/base/widgets/DialogUtil.java
  4. 1 0
      classRoom/.gitignore
  5. 66 0
      classRoom/build.gradle
  6. 0 0
      classRoom/consumer-rules.pro
  7. 21 0
      classRoom/proguard-rules.pro
  8. 26 0
      classRoom/src/androidTest/java/com/dayayuemeng/classroom/ExampleInstrumentedTest.java
  9. 20 0
      classRoom/src/main/AndroidManifest.xml
  10. 103 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/AccompanimentListAdapterV2.java
  11. 47 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/BarrageChatMessageAdapter.java
  12. 166 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/ClassRoomMessageAdapter.java
  13. 52 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/FixPagerAdapter.java
  14. 90 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/NewGongGeListAdapter.java
  15. 100 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/NewMetronomeAdapter.java
  16. 63 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/NotOnlineMembersListAdapter.java
  17. 74 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/OnlineMembersListAdapter.java
  18. 157 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/TcAddPhotoListAdapter.java
  19. 136 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/VideoListAdapter.java
  20. 72 0
      classRoom/src/main/java/com/dayayuemeng/classroom/adapter/WhiteBoardListAdapter.java
  21. 12 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/ApiConstant.java
  22. 62 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/ErrorCode.java
  23. 71 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/HttpClientManager.java
  24. 263 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/LiveTeachingApi.java
  25. 62 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/LiveTeachingUrls.java
  26. 47 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/RequestState.java
  27. 82 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/Result.java
  28. 11 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/ResultCallback.java
  29. 51 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/StateLiveData.java
  30. 45 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/WhiteBoardApi.java
  31. 45 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/retrofit/CallBackWrapper.java
  32. 13 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/retrofit/HttpLogger.java
  33. 121 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/retrofit/RetrofitClient.java
  34. 25 0
      classRoom/src/main/java/com/dayayuemeng/classroom/api/retrofit/RetrofitUtil.java
  35. 322 0
      classRoom/src/main/java/com/dayayuemeng/classroom/bean/ClassMember.java
  36. 25 0
      classRoom/src/main/java/com/dayayuemeng/classroom/bean/GonggeVideoListBean.java
  37. 215 0
      classRoom/src/main/java/com/dayayuemeng/classroom/bean/LoginResult.java
  38. 13 0
      classRoom/src/main/java/com/dayayuemeng/classroom/bean/UserInfo.java
  39. 115 0
      classRoom/src/main/java/com/dayayuemeng/classroom/bean/VideoListBean.java
  40. 33 0
      classRoom/src/main/java/com/dayayuemeng/classroom/bean/WhiteBoard.java
  41. 141 0
      classRoom/src/main/java/com/dayayuemeng/classroom/bean/WhiteCreateBean.java
  42. 33 0
      classRoom/src/main/java/com/dayayuemeng/classroom/bean/WhiteSdkRoomInfo.java
  43. 17 0
      classRoom/src/main/java/com/dayayuemeng/classroom/constants/ARouterSealClass.java
  44. 37 0
      classRoom/src/main/java/com/dayayuemeng/classroom/constants/ClassRoomConstants.java
  45. 32 0
      classRoom/src/main/java/com/dayayuemeng/classroom/constants/DeviceType.java
  46. 35 0
      classRoom/src/main/java/com/dayayuemeng/classroom/constants/InviteAction.java
  47. 41 0
      classRoom/src/main/java/com/dayayuemeng/classroom/constants/RightOperate.java
  48. 80 0
      classRoom/src/main/java/com/dayayuemeng/classroom/constants/Role.java
  49. 8 0
      classRoom/src/main/java/com/dayayuemeng/classroom/constants/TTMessageConstants.java
  50. 12 0
      classRoom/src/main/java/com/dayayuemeng/classroom/contract/MainVideoFragmentContractView.java
  51. 22 0
      classRoom/src/main/java/com/dayayuemeng/classroom/contract/NewConversationView.java
  52. 60 0
      classRoom/src/main/java/com/dayayuemeng/classroom/contract/StudentNetClassRoomContract.java
  53. 43 0
      classRoom/src/main/java/com/dayayuemeng/classroom/contract/TeacherNetClassRoomContract.java
  54. 20 0
      classRoom/src/main/java/com/dayayuemeng/classroom/contract/TopOperateControlView.java
  55. 31 0
      classRoom/src/main/java/com/dayayuemeng/classroom/helper/ClassRoomEnterHelper.java
  56. 98 0
      classRoom/src/main/java/com/dayayuemeng/classroom/helper/OpenClassRoomHelper.java
  57. 103 0
      classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TCClassRoomTextMessage.java
  58. 149 0
      classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTControlDeviceStateMessage.java
  59. 112 0
      classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTDeviceStateChangedMessage.java
  60. 96 0
      classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTDisplayMessage.java
  61. 176 0
      classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTMemberChangedMessage.java
  62. 146 0
      classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTMusicSyncMessage.java
  63. 151 0
      classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTPlayBeatMessage.java
  64. 21 0
      classRoom/src/main/java/com/dayayuemeng/classroom/listener/OnWhiteBoardListener.java
  65. 32 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/ClassMemberChangedAction.java
  66. 23 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/DeviceChange.java
  67. 16 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/DeviceChangeToast.java
  68. 55 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/DeviceControlInvite.java
  69. 14 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/DeviceSoudValum.java
  70. 52 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/DownLoadSong.java
  71. 143 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/DownLoadSongStatus.java
  72. 40 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/InsertImageBean.java
  73. 44 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/MetronomeInfo.java
  74. 29 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/PassedTime.java
  75. 69 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/PlayMidi.java
  76. 131 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/ScreenDisplay.java
  77. 44 0
      classRoom/src/main/java/com/dayayuemeng/classroom/model/VideoClassMemberData.java
  78. 28 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/AssistantPermissionGroup.java
  79. 32 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/ClassExecutedPermission.java
  80. 86 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/ClassPermission.java
  81. 27 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/LecturerPermissionGroup.java
  82. 33 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/ListenerPermissionGroup.java
  83. 27 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/PermissionGroup.java
  84. 29 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/PermissionGroupFactory.java
  85. 37 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/PermissionGroupLevel.java
  86. 36 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/RolePermissionGroup.java
  87. 32 0
      classRoom/src/main/java/com/dayayuemeng/classroom/permission/StudentPermissionGroup.java
  88. 48 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/MainVideoFragmentPresenter.java
  89. 21 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/NewAccompanimentListPresenter.java
  90. 112 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/NewConversationPresenter.java
  91. 37 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/NewGongGeFragmentPresenter.java
  92. 400 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/StudentNetClassRoomPresenter.java
  93. 30 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/StudentPreviewBigFragmentPresenter.java
  94. 296 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/TeacherNetClassRoomPresenter.java
  95. 77 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/TopOperateControlPresenter.java
  96. 41 0
      classRoom/src/main/java/com/dayayuemeng/classroom/presenter/VideoListFragmentPresenter.java
  97. 96 0
      classRoom/src/main/java/com/dayayuemeng/classroom/receiver/HeadsetPlugReceiver.java
  98. 31 0
      classRoom/src/main/java/com/dayayuemeng/classroom/repository/BaseRepository.java
  99. 439 0
      classRoom/src/main/java/com/dayayuemeng/classroom/repository/ClassRepository.java
  100. 127 0
      classRoom/src/main/java/com/dayayuemeng/classroom/repository/OnClassEventListener.java

+ 13 - 0
BaseLibrary/src/main/java/com/cooleshow/base/utils/LOG.java

@@ -19,12 +19,25 @@ public class LOG {
         }
     }
 
+    public static void d(String tag,String msg) {
+        if (DEBUG) {
+            Log.d(tag, msg);
+        }
+    }
+
+
     public static void e(String msg) {
         if (DEBUG) {
             Log.e(TAG, msg);
         }
     }
 
+    public static void e(String tag,String msg) {
+        if (DEBUG) {
+            Log.e(tag, msg);
+        }
+    }
+
     public static void i(String msg) {
         if (DEBUG) {
             Log.i(TAG, msg);

+ 17 - 0
BaseLibrary/src/main/java/com/cooleshow/base/utils/helper/QMUIDisplayHelper.java

@@ -650,4 +650,21 @@ public class QMUIDisplayHelper {
     public static boolean xiaomiIsNotchSetToShowInSetting(Context context) {
         return Settings.Global.getInt(context.getContentResolver(), XIAOMI_DISPLAY_NOTCH_STATUS, 0) == 0;
     }
+
+    public static void hideStatusBar(Activity activity) {
+        if (activity == null) return;
+        Window window = activity.getWindow();
+        if (window == null) return;
+        // 隐藏状态栏
+        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+        window.getDecorView().setSystemUiVisibility(
+                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                        | View.SYSTEM_UI_FLAG_FULLSCREEN);
+        WindowManager.LayoutParams lp = window.getAttributes();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+            lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        }
+        window.setAttributes(lp);
+    }
 }

+ 34 - 0
BaseLibrary/src/main/java/com/cooleshow/base/widgets/DialogUtil.java

@@ -2,6 +2,7 @@ package com.cooleshow.base.widgets;
 
 import android.view.Gravity;
 import android.view.View;
+import android.widget.ImageView;
 import android.widget.TextView;
 
 import androidx.fragment.app.FragmentManager;
@@ -38,6 +39,39 @@ public class DialogUtil {
                 .show(fragmentmanager);
     }
 
+    public static void showInCenterWithClose(FragmentManager fragmentmanager, int resourcesId, String title, String content, OnDialogButtonClickListener onDialogButtonClickListener) {
+        if (fragmentmanager == null) {
+            return;
+        }
+        CommonDialog.init().setLayoutId(resourcesId)
+                .setConvertListener(new ViewConvertListener() {
+                    @Override
+                    public void convertView(ViewHolder holder, BaseDialog dialog) {
+                        TextView tvTitle = holder.getView(R.id.tv_title);
+                        TextView tvContent = holder.getView(R.id.tv_content);
+                        TextView btncancel = holder.getView(R.id.btn_cancel);
+                        TextView btnCommit = holder.getView(R.id.btn_commit);
+                        ImageView iv_live_common_popu_close = holder.getView(R.id.iv_close);
+                        tvTitle.setText(title);
+                        tvContent.setText(content);
+                        iv_live_common_popu_close.setOnClickListener(v -> dialog.dismiss());
+                        btncancel.setOnClickListener(view -> {
+                            onDialogButtonClickListener.onCancel(view);
+                            dialog.dismiss();
+                        });
+                        btnCommit.setOnClickListener(view -> {
+                            onDialogButtonClickListener.onCommit(view);
+                            dialog.dismiss();
+                        });
+                    }
+                })
+                .setDimAmount(0.2f)
+                .setOutCancel(false)
+                .setGravity(Gravity.CENTER)
+
+                .show(fragmentmanager);
+    }
+
     /*居中显示*/
     public static void showInCenter(FragmentManager fragmentmanager, int resourcesId, String title, String content, OnDialogButtonClickListener onDialogButtonClickListener) {
         if (fragmentmanager == null) {

+ 1 - 0
classRoom/.gitignore

@@ -0,0 +1 @@
+/build

+ 66 - 0
classRoom/build.gradle

@@ -0,0 +1,66 @@
+plugins {
+    id 'com.android.library'
+    id 'org.jetbrains.kotlin.android'
+//    id 'kotlin-parcelize'
+    id 'kotlin-android'
+//    id 'kotlin-android-extensions'
+}
+apply plugin: 'kotlin-kapt'
+apply plugin: 'kotlin-android-extensions'
+
+kapt {
+    arguments {
+        arg("AROUTER_MODULE_NAME", project.getName())
+    }
+}
+android {
+    compileSdkVersion 32
+
+    defaultConfig {
+        minSdkVersion rootProject.ext.android.minSdkVersion
+        targetSdkVersion rootProject.ext.android.targetSdkVersion
+        versionCode rootProject.ext.android.versionCode
+        versionName rootProject.ext.android.versionName
+        javaCompileOptions {
+            annotationProcessorOptions {
+                arguments = [AROUTER_MODULE_NAME: project.getName()]
+            }
+        }
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles "consumer-rules.pro"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+
+    buildFeatures {
+        viewBinding = true
+    }
+}
+
+dependencies {
+
+    implementation 'androidx.appcompat:appcompat:1.3.0'
+    implementation 'com.google.android.material:material:1.4.0'
+    testImplementation 'junit:junit:4.13.2'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+    implementation 'androidx.lifecycle:lifecycle-livedata:2.1.0-alpha04'
+    implementation 'androidx.lifecycle:lifecycle-viewmodel:2.1.0-alpha04'
+    implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
+    implementation project(path: ':tclive')
+    implementation project(path: ':chatModule')
+    implementation project(path: ':BaseLibrary')
+    implementation project(path: ':usercenter')
+//    implementation project(path: ':live_teaching')
+    implementation 'com.h6ah4i.android.widget.verticalseekbar:verticalseekbar:1.0.0'
+}

+ 0 - 0
classRoom/consumer-rules.pro


+ 21 - 0
classRoom/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
classRoom/src/androidTest/java/com/dayayuemeng/classroom/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.dayayuemeng.classroom;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.dayayuemeng.classroom.test", appContext.getPackageName());
+    }
+}

+ 20 - 0
classRoom/src/main/AndroidManifest.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.dayayuemeng.classroom">
+
+    <application>
+        <activity
+            android:name=".ui.TeacherNetClassRoomActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:launchMode="singleTask"
+            android:screenOrientation="landscape"
+            android:windowSoftInputMode="adjustPan" />
+
+        <activity
+            android:name=".ui.StudentNetClassRoomActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:launchMode="singleTask"
+            android:screenOrientation="landscape"
+            android:windowSoftInputMode="adjustPan" />
+    </application>
+</manifest>

+ 103 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/AccompanimentListAdapterV2.java

@@ -0,0 +1,103 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.dayayuemeng.classroom.R;
+import com.dayayuemeng.classroom.bean.ClassMember;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2020/6/9 10:43
+ */
+public class AccompanimentListAdapterV2 extends BaseQuickAdapter<ClassMember.ScheduleStudentMusicScoresBean,AccompanimentListAdapterV2.ViewHolder> {
+
+    List<ClassMember.ScheduleStudentMusicScoresBean> menberList = new ArrayList<>();
+    private String musicScoreAccompanimentId;
+
+    public AccompanimentListAdapterV2() {
+        super(R.layout.item_accompaniment_list_layout);
+        addChildClickViewIds(R.id.iv_type,R.id.tv_status);
+    }
+
+
+    public void setData(List<ClassMember.ScheduleStudentMusicScoresBean> classMembers, String musicScoreAccompanimentId) {
+        this.musicScoreAccompanimentId = musicScoreAccompanimentId;
+        setList(classMembers);
+    }
+
+    @Override
+    protected void convert(@NonNull ViewHolder viewHolder, ClassMember.ScheduleStudentMusicScoresBean musicScoresBean) {
+        viewHolder.tvName.setText(musicScoresBean.getMusicScoreName());
+        if (!TextUtils.isEmpty(musicScoresBean.getUrl()) && !TextUtils.isEmpty(musicScoresBean.getMp3Url())) {
+            //原生或者伴奏
+            if (musicScoresBean.getIsAccompaniment() == 0) {
+                viewHolder.ivType.setImageResource(R.drawable.tc_ic_live_teaching_acoustic);
+            } else {
+                viewHolder.ivType.setImageResource(R.drawable.tc_icon_live_teaching_accompaniment);
+            }
+        } else if (!TextUtils.isEmpty(musicScoresBean.getUrl())) {
+            viewHolder.ivType.setImageResource(R.drawable.tc_ic_live_teaching_acoustic);
+        } else if (!TextUtils.isEmpty(musicScoresBean.getMp3Url())) {
+            viewHolder.ivType.setImageResource(R.drawable.tc_icon_live_teaching_accompaniment);
+        }
+
+
+        if (!TextUtils.isEmpty(musicScoreAccompanimentId) && musicScoreAccompanimentId.equals(musicScoresBean.getMusicScoreAccompanimentId())) {
+            viewHolder.tvName.setTextColor(getContext().getResources().getColor(R.color.color_00b2a7));
+            viewHolder.viewSelect.setBackgroundResource(R.drawable.shape_ecfbfa_6dp);
+            viewHolder.ivPlayTag.setVisibility(View.VISIBLE);
+        } else {
+            viewHolder.tvName.setTextColor(getContext().getResources().getColor(R.color.color_333333));
+            viewHolder.viewSelect.setBackgroundColor(Color.TRANSPARENT);
+            viewHolder.ivPlayTag.setVisibility(View.GONE);
+        }
+        //无需显示下载状态
+        viewHolder.tvStatus.setVisibility(View.GONE);
+        if (musicScoresBean.getDownStatus() == 1) {
+            viewHolder.tvStatus.setText("已下载");
+            viewHolder.tvStatus.setTextColor(getContext().getResources().getColor(com.cooleshow.base.R.color.color_666666));
+        } else if (musicScoresBean.getDownStatus() == 2) {
+            viewHolder.tvStatus.setText("下载失败");
+            viewHolder.tvStatus.setTextColor(getContext().getResources().getColor(R.color.red_dot));
+        } else {
+            viewHolder.tvStatus.setText("下载中");
+            viewHolder.tvStatus.setTextColor(getContext().getResources().getColor(R.color.live_green));
+        }
+    }
+
+    public class ViewHolder extends BaseViewHolder {
+        ImageView ivType;
+        TextView tvName;
+        TextView tvStatus;
+        View viewSelect;
+        ImageView ivPlayTag;
+
+        public ViewHolder(View itemView) {
+            super(itemView);
+            ivType = itemView.findViewById(R.id.iv_type);
+            tvName = itemView.findViewById(R.id.tv_name);
+            tvStatus = itemView.findViewById(R.id.tv_status);
+            viewSelect = itemView.findViewById(R.id.view_select);
+            ivPlayTag = itemView.findViewById(R.id.iv_play_tag);
+        }
+    }
+
+
+}

+ 47 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/BarrageChatMessageAdapter.java

@@ -0,0 +1,47 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.text.TextUtils;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.daya.tclive.bean.TTMessage;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.daya.tclive.message.TCTextMessage;
+import com.dayayuemeng.classroom.R;
+import com.dayayuemeng.classroom.im.message.TCClassRoomTextMessage;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Author by pq, Date on 2023/7/24.
+ */
+public class BarrageChatMessageAdapter extends BaseQuickAdapter<TTMessage, BaseViewHolder> {
+    public BarrageChatMessageAdapter() {
+        super(R.layout.item_barrage_chat_msg_layout);
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, TTMessage message) {
+        String nickName = getNickName(message);
+        holder.setText(R.id.tv_name,nickName+":");
+        TCClassRoomTextMessage content = (TCClassRoomTextMessage) message.getContent();
+        if (content == null) {
+            return;
+        }
+        holder.setText(R.id.tv_text,content.getText());
+
+    }
+
+    private String getNickName(TTMessage message) {
+        //昵称
+        String name = "用户";
+        BaseTIMMessageContent content = message.getContent();
+        if (content.getSendUserInfo() != null) {
+            name = "用户" + content.getSendUserInfo().getSendUserId();
+            if (!TextUtils.isEmpty(content.getSendUserInfo().getSendUserName())) {
+                name = content.getSendUserInfo().getSendUserName();
+            }
+        }
+        return name;
+    }
+}

+ 166 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/ClassRoomMessageAdapter.java

@@ -0,0 +1,166 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.utils.GlideImageLoaderUtils;
+import com.cooleshow.usercenter.helper.UserHelper;
+import com.daya.tclive.bean.SendUserInfo;
+import com.daya.tclive.bean.TTMessage;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.dayayuemeng.classroom.R;
+import com.dayayuemeng.classroom.im.message.TCClassRoomTextMessage;
+import com.dayayuemeng.classroom.utils.RongDateUtils;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Author by pq, Date on 2023/5/12.
+ */
+public class ClassRoomMessageAdapter extends BaseQuickAdapter<TTMessage, BaseViewHolder> {
+    private static final int OTHER = 2014;
+    private static final int TODAY = 6;
+    private static final int YESTERDAY = 15;
+    private final String mUserId;
+
+    public ClassRoomMessageAdapter() {
+        super(R.layout.item_tt_message_layout);
+        mUserId = UserHelper.getImUserId();
+    }
+
+    private boolean isSend(String id) {
+        return TextUtils.equals(id, mUserId);
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, TTMessage uiMessage) {
+        if (uiMessage != null && uiMessage.getContent() != null) {
+            boolean isSender = isSend(uiMessage.getSenderUserId());
+            initTime(holder, uiMessage);
+            initUserInfo(holder, uiMessage, isSender);
+            initContent(holder, isSender, uiMessage);
+        } else {
+        }
+    }
+
+    private void initTime(BaseViewHolder holder, TTMessage uiMessage) {
+        String time = RongDateUtils.getConversationFormatDate(uiMessage.getTimeStamp(), getContext());
+        holder.setText(R.id.rc_time, time);
+
+        int pos = holder.getLayoutPosition();
+        TTMessage pre = null;
+        if (pos > 0) {
+            pre = getData().get(pos - 1);
+        }
+
+        if (pre != null && isShowChatTime(uiMessage.getTimeStamp(), pre.getTimeStamp(), 180)) {
+            holder.setGone(R.id.rc_time, false);
+        } else {
+            holder.setGone(R.id.rc_time, true);
+        }
+    }
+
+    public static boolean isShowChatTime(long currentTime, long preTime, int interval) {
+
+        int typeCurrent = judgeDate(new Date(currentTime));
+        int typePre = judgeDate(new Date(preTime));
+
+        if (typeCurrent == typePre) {
+            return (currentTime - preTime) > interval * 1000;
+        } else {
+            return true;
+        }
+    }
+
+    public static int judgeDate(Date date) {
+        // 今天
+        Calendar calendarToday = Calendar.getInstance();
+        calendarToday.set(Calendar.HOUR_OF_DAY, 0);
+        calendarToday.set(Calendar.MINUTE, 0);
+        calendarToday.set(Calendar.SECOND, 0);
+        calendarToday.set(Calendar.MILLISECOND, 0);
+        // 昨天
+        Calendar calendarYesterday = Calendar.getInstance();
+        calendarYesterday.add(Calendar.DATE, -1);
+        calendarYesterday.set(Calendar.HOUR_OF_DAY, 0);
+        calendarYesterday.set(Calendar.MINUTE, 0);
+        calendarYesterday.set(Calendar.SECOND, 0);
+        calendarYesterday.set(Calendar.MILLISECOND, 0);
+
+        Calendar calendarTomorrow = Calendar.getInstance();
+        calendarTomorrow.add(Calendar.DATE, 1);
+        calendarTomorrow.set(Calendar.HOUR_OF_DAY, 0);
+        calendarTomorrow.set(Calendar.MINUTE, 0);
+        calendarTomorrow.set(Calendar.SECOND, 0);
+        calendarTomorrow.set(Calendar.MILLISECOND, 0);
+
+        // 目标日期
+        Calendar calendarTarget = Calendar.getInstance();
+        calendarTarget.setTime(date);
+
+        if (calendarTarget.before(calendarYesterday)) {// 是否在calendarT之前
+            return OTHER;
+        } else if (calendarTarget.before(calendarToday)) {
+            return YESTERDAY;
+        } else if (calendarTarget.before(calendarTomorrow)) {
+            return TODAY;
+        } else {
+            return OTHER;
+        }
+    }
+
+    public void initUserInfo(final BaseViewHolder holder, final TTMessage uiMessage, boolean isSender) {
+        BaseTIMMessageContent content = uiMessage.getContent();
+        SendUserInfo sendUserInfo = content.getSendUserInfo();
+        holder.setGone(R.id.rc_left_portrait, isSender);
+        holder.setGone(R.id.rc_right_portrait, !isSender);
+        ImageView view = holder.getView(isSender ? R.id.rc_right_portrait : R.id.rc_left_portrait);
+        if (content.getSendUserInfo() != null && content.getSendUserInfo().getAvatarUrl() != null) {
+            GlideImageLoaderUtils.getInstance().loadImage(getContext(), content.getSendUserInfo().getAvatarUrl(), view, com.daya.tclive.R.drawable.icon_default_head);
+        }
+        ImageView iv_tag = holder.getView(R.id.iv_tag);
+        if (!isSender) {
+            holder.setGone(R.id.rc_title, false);
+            holder.setText(R.id.rc_title, !TextUtils.isEmpty(sendUserInfo.getSendUserName()) ? sendUserInfo.getSendUserName() : "用户");
+        } else {
+            holder.setGone(R.id.rc_title, true);
+        }
+    }
+
+    private void initContent(final BaseViewHolder holder, boolean isSender, final TTMessage uiMessage) {
+//        holder.setBackgroundResource(R.id.rc_content, isSender ? R.drawable.rc_ic_message_bubble_right : R.drawable.rc_ic_message_bubble_left);
+        holder.setBackgroundResource(R.id.rc_content, isSender ? R.drawable.shape_c9e7fe_10dp : R.drawable.shape_white_10dp);
+        LinearLayout layout = holder.getView(R.id.rc_layout);
+        layout.setGravity(isSender ? Gravity.END : Gravity.START);
+        FrameLayout rc_content = holder.getView(R.id.rc_content);
+        rc_content.removeAllViews();
+        View view = onCreateMessageContentView(rc_content, uiMessage);
+        if (view != null) {
+            rc_content.addView(view);
+        }
+    }
+
+    protected View onCreateMessageContentView(ViewGroup parent, TTMessage message) {
+        BaseTIMMessageContent content = message.getContent();
+        if (content instanceof TCClassRoomTextMessage) {
+            TCClassRoomTextMessage textMessage = (TCClassRoomTextMessage) content;
+            TextView textView = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.tt_text_message_item, parent, false);
+            textView.setText(textMessage.getText());
+            return textView;
+        }
+        return null;
+    }
+}

+ 52 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/FixPagerAdapter.java

@@ -0,0 +1,52 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.view.ViewGroup;
+
+import java.util.List;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentStatePagerAdapter;
+
+public class FixPagerAdapter extends FragmentStatePagerAdapter {
+
+    // Tabs上显示的title
+    private String[]       titles;
+    // Tabs对应的fragment集合
+    private List<Fragment> fragments;
+
+    public FixPagerAdapter(FragmentManager fm, String[] titles, List<Fragment> fragments) {
+        super(fm);
+        this.titles = titles;
+        this.fragments = fragments;
+    }
+
+
+    @Override
+    public Fragment getItem(int position) {
+        return fragments.get(position);
+    }
+
+    @Override
+    public int getCount() {
+        return fragments == null ? 0 : fragments.size();
+    }
+
+    @Override
+    public Object instantiateItem(ViewGroup container, int position) {
+
+        Fragment fragment = null;
+        try {
+            fragment = (Fragment) super.instantiateItem(container, position);
+        } catch (Exception e) {
+        }
+
+        return fragment;
+    }
+
+
+    @Override
+    public CharSequence getPageTitle(int position) {
+        return titles[position];
+    }
+}

+ 90 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/NewGongGeListAdapter.java

@@ -0,0 +1,90 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.usercenter.helper.UserHelper;
+import com.dayayuemeng.classroom.R;
+import com.dayayuemeng.classroom.bean.GonggeVideoListBean;
+import com.dayayuemeng.classroom.bean.VideoListBean;
+import com.dayayuemeng.classroom.constants.Role;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Author by pq, Date on 2023/5/5.
+ */
+public class NewGongGeListAdapter extends BaseQuickAdapter<GonggeVideoListBean, BaseViewHolder> {
+    private String userId;
+    private String currentPreviewUserId;
+
+    public NewGongGeListAdapter() {
+        super(R.layout.item_new_gong_ge_layout);
+        addChildClickViewIds(R.id.view_root_click);
+        userId = UserHelper.getImUserId();
+    }
+
+    public String getCurrentPreviewUserId() {
+        return currentPreviewUserId;
+    }
+
+    public void setCurrentPreviewUserId(String currentPreviewUserId) {
+        this.currentPreviewUserId = currentPreviewUserId;
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, GonggeVideoListBean videoListBean) {
+        FrameLayout fl_root = holder.getView(R.id.fl_root);
+        RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) fl_root.getLayoutParams();
+        layoutParams.height = videoListBean.getHeight();
+        fl_root.setLayoutParams(layoutParams);
+
+        holder.setText(R.id.tv_name, getNickName(videoListBean));
+        boolean isTeacher = videoListBean.getRole() == Role.LECTURER;
+        View view = holder.getView(R.id.tv_role_text);
+        view.setVisibility(isTeacher ? View.VISIBLE : View.GONE);
+
+        ImageView iv_mic_status = holder.getView(R.id.iv_mic_status);
+        iv_mic_status.setImageResource(videoListBean.isMicrophone() ? R.drawable.tc_icon_mic_level_1 : R.drawable.tc_icon_mic_level_off);
+
+        RelativeLayout fl_video_container = holder.getView(R.id.fl_video_container);
+        TXCloudVideoView videoView = videoListBean.getVideoView();
+        fl_video_container.removeAllViews();
+        if (videoView != null && !TextUtils.equals(currentPreviewUserId,videoListBean.getUserId())) {
+            if (videoView.getParent() != null) {
+                ViewGroup parent = (ViewGroup) videoView.getParent();
+                parent.removeView(videoView);
+            }
+            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+            params.addRule(RelativeLayout.CENTER_IN_PARENT);
+            fl_video_container.addView(videoView, params);
+        }
+        boolean camera = videoListBean.isCamera();
+        View iv_camera_tip = holder.getView(R.id.iv_camera_tip);
+        if(isOwner(videoListBean.getUserId()) && !camera){
+            iv_camera_tip.setVisibility(View.VISIBLE);
+        }else{
+            iv_camera_tip.setVisibility(View.GONE);
+        }
+    }
+
+    private boolean isOwner(String targetUserId){
+        return TextUtils.equals(userId,targetUserId);
+    }
+
+    private String getNickName(VideoListBean bean) {
+//        if (TextUtils.equals(bean.getUserId(), userId)) {
+//            return "我";
+//        }
+        return bean.getUserName();
+    }
+}

+ 100 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/NewMetronomeAdapter.java

@@ -0,0 +1,100 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.content.Context;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+
+import com.dayayuemeng.classroom.R;
+
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2020/6/18 15:29
+ */
+public class NewMetronomeAdapter extends BaseAdapter {
+
+
+    private Context mContext;
+    private int     count         = 4;
+    private int     selectPositon = 0;
+    private double  delayMillis   = 0d;
+
+    public NewMetronomeAdapter(Context context) {
+        this.mContext = context;
+    }
+
+
+    public void setData(int count, double delayMillis) {
+        selectPositon=0;
+        this.delayMillis = delayMillis;
+        this.count = count;
+        notifyDataSetChanged();
+    }
+
+    @Override
+    public int getCount() {
+        return count;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return null;
+    }
+
+    @Override
+    public long getItemId(int position) {
+
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        ViewHolder viewHolder = null;
+        if (convertView == null) {
+            convertView = LayoutInflater.from(mContext).inflate(R.layout.tc_item_layout_metronome_list_layout, parent, false);
+            viewHolder = new ViewHolder();
+            viewHolder.ivMetronome = (ImageView) convertView.findViewById(R.id.iv_metronome);
+            convertView.setTag(viewHolder);
+        } else {
+            viewHolder = (ViewHolder) convertView.getTag();
+        }
+        if (position == selectPositon) {
+//            if (position == 0) {
+//                viewHolder.ivMetronome.setImageResource(R.drawable.bg_play_metronome_green_dots_shape);
+//            } else {
+//                viewHolder.ivMetronome.setImageResource(R.drawable.bg_play_metronome_white_dots_shape);
+//            }
+            viewHolder.ivMetronome.setImageResource(R.drawable.new_bg_play_metronome_green_dots_shape);
+            ViewHolder finalViewHolder = viewHolder;
+            if (delayMillis > 0) {
+                new Handler().postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        finalViewHolder.ivMetronome.setImageResource(R.drawable.new_bg_play_metronome_gray_dots_shape);
+                    }
+                }, (long) (delayMillis - 100));
+            }
+
+        } else {
+            viewHolder.ivMetronome.setImageResource(R.drawable.new_bg_play_metronome_gray_dots_shape);
+        }
+        return convertView;
+    }
+
+    public void notifyPositon(int selectPositon) {
+        this.selectPositon = selectPositon;
+        notifyDataSetChanged();
+    }
+
+
+    public class ViewHolder {
+        ImageView ivMetronome;
+    }
+}

+ 63 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/NotOnlineMembersListAdapter.java

@@ -0,0 +1,63 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.utils.GlideImageLoaderUtils;
+import com.dayayuemeng.classroom.R;
+import com.dayayuemeng.classroom.bean.ClassMember;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2020/6/9 10:43
+ */
+public class NotOnlineMembersListAdapter extends BaseQuickAdapter<ClassMember,NotOnlineMembersListAdapter.ViewHolder> {
+
+
+    public NotOnlineMembersListAdapter() {
+        super(R.layout.item_members_list_layout);
+    }
+
+
+    public void setData(List<ClassMember> classMembers) {
+        setList(classMembers);
+    }
+
+    @Override
+    protected void convert(@NonNull ViewHolder viewHolder, ClassMember member) {
+        GlideImageLoaderUtils.getInstance().loadCircleImage(getContext(), member.getHeadUrl(), com.cooleshow.base.R.drawable.icon_default_head, viewHolder.ivPortrait);
+        viewHolder.tvName.setText(member.getUserName());
+        viewHolder.ivMic.setVisibility(View.GONE);
+        viewHolder.iv_raise_hands.setVisibility(View.GONE);
+    }
+
+    public class ViewHolder extends BaseViewHolder {
+        ImageView ivPortrait;
+        TextView  tvName;
+        ImageView ivMic;
+        ImageView  iv_raise_hands;
+
+        public ViewHolder(View itemView) {
+            super(itemView);
+            ivPortrait = itemView.findViewById(R.id.iv_portrait);
+            tvName = itemView.findViewById(R.id.tv_name);
+            ivMic = itemView.findViewById(R.id.iv_mic);
+            iv_raise_hands = itemView.findViewById(R.id.iv_raise_hands);
+        }
+
+    }
+}

+ 74 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/OnlineMembersListAdapter.java

@@ -0,0 +1,74 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.utils.GlideImageLoaderUtils;
+import com.dayayuemeng.classroom.R;
+import com.dayayuemeng.classroom.bean.ClassMember;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2020/6/9 10:43
+ */
+public class OnlineMembersListAdapter extends BaseQuickAdapter<ClassMember,OnlineMembersListAdapter.ViewHolder> {
+
+    public OnlineMembersListAdapter() {
+        super(R.layout.item_members_list_layout);
+        addChildClickViewIds(R.id.iv_mic,R.id.iv_camera);
+    }
+
+
+    public void setData(List<ClassMember> classMembers) {
+        setList(classMembers);
+    }
+
+    public ClassMember getData(int pos) {
+        if (pos < getData().size()) {
+            return getData().get(pos);
+        }
+        return null;
+    }
+
+    @Override
+    protected void convert(@NonNull ViewHolder viewHolder, ClassMember member) {
+        GlideImageLoaderUtils.getInstance().loadCircleImage(getContext(), member.getHeadUrl(), com.daya.tclive.R.drawable.icon_default_head,viewHolder.ivPortrait);
+        viewHolder.tvName.setText(member.getUserName());
+        viewHolder.ivMic.setImageResource(member.isMicrophone() ? R.drawable.tc_icon_mic_level_2 : R.drawable.tc_icon_mic_level_off);
+        viewHolder.iv_raise_hands.setVisibility(member.isHandUpOn() ? View.VISIBLE : View.GONE);
+        viewHolder.iv_camera.setImageResource(member.isCamera() ? R.drawable.ic_memeber_camera_on : R.drawable.ic_memeber_camera_off);
+    }
+
+    public class ViewHolder extends BaseViewHolder {
+        ImageView ivPortrait;
+        TextView tvName;
+        ImageView ivMic;
+        ImageView iv_raise_hands;
+        ImageView iv_camera;
+
+        public ViewHolder(View itemView) {
+            super(itemView);
+            ivPortrait = itemView.findViewById(R.id.iv_portrait);
+            tvName = itemView.findViewById(R.id.tv_name);
+            ivMic = itemView.findViewById(R.id.iv_mic);
+            iv_raise_hands = itemView.findViewById(R.id.iv_raise_hands);
+            iv_camera = itemView.findViewById(R.id.iv_camera);
+        }
+
+    }
+
+}

+ 157 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/TcAddPhotoListAdapter.java

@@ -0,0 +1,157 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.cooleshow.base.utils.GlideImageLoaderUtils;
+import com.dayayuemeng.classroom.R;
+import com.luck.picture.lib.entity.LocalMedia;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2019/9/18 19:49
+ */
+public class TcAddPhotoListAdapter extends RecyclerView.Adapter<TcAddPhotoListAdapter.ViewHolder> {
+
+
+    private Context mContext;
+    List<LocalMedia> selectList = new ArrayList<>();
+    private int maxSelectNum;
+    private boolean isAddPhoto = true;
+    private boolean isNeedDel = false;
+
+    public TcAddPhotoListAdapter(Context mContex, int maxSelectNum, boolean isAddPhoto) {
+        this.mContext = mContex;
+        this.maxSelectNum = maxSelectNum;
+        this.isAddPhoto = isAddPhoto;
+
+    }
+
+    public TcAddPhotoListAdapter(Context mContex, int maxSelectNum, boolean isAddPhoto, boolean isNeedDel) {
+        this.mContext = mContex;
+        this.maxSelectNum = maxSelectNum;
+        this.isAddPhoto = isAddPhoto;
+        this.isNeedDel = isNeedDel;
+    }
+
+    public TcAddPhotoListAdapter(Context mContex, int maxSelectNum) {
+        this.mContext = mContex;
+        this.maxSelectNum = maxSelectNum;
+    }
+
+
+    @NonNull
+    @Override
+    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        View inflater = LayoutInflater.from(mContext).inflate(R.layout.item_photo_list_layout, parent, false);
+        return new ViewHolder(inflater);
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+        if (isAddPhoto) {
+            if (selectList.size() != position) {
+                GlideImageLoaderUtils.getInstance().loadCustRoundCircleImage(mContext, selectList.get(position).getPath(), holder.ivIcon, 5);
+                holder.iv_del.setVisibility(isNeedDel ? View.VISIBLE : View.GONE);
+                holder.fl_root.setBackgroundColor(Color.TRANSPARENT);
+            } else {
+                holder.ivIcon.setImageResource(R.drawable.ic_update_photo);
+                holder.iv_del.setVisibility(View.GONE);
+                holder.fl_root.setBackgroundResource(com.cooleshow.base.R.drawable.bg_add_photo_shape);
+            }
+        } else {
+            GlideImageLoaderUtils.getInstance().loadCustRoundCircleImage(mContext, selectList.get(position).getPath(), holder.ivIcon, 5);
+            holder.iv_del.setVisibility(View.GONE);
+        }
+
+    }
+
+
+    @Override
+    public int getItemCount() {
+        if (!isAddPhoto) {
+            return selectList.size();
+        }
+        if (selectList.size() == 0) {
+            return 1;
+        }
+        if (selectList.size() < maxSelectNum) {
+            return selectList.size() + 1;
+        }
+        return maxSelectNum;
+    }
+
+    public class ViewHolder extends RecyclerView.ViewHolder {
+
+        ImageView ivIcon;
+        ImageView iv_del;
+        FrameLayout fl_root;
+
+        public ViewHolder(View itemView) {
+            super(itemView);
+            ivIcon = itemView.findViewById(R.id.iv_icon);
+            iv_del = itemView.findViewById(R.id.iv_del);
+            fl_root = itemView.findViewById(R.id.fl_root);
+
+            ivIcon.setOnClickListener(view -> onItemClickListener.onItemClick(getLayoutPosition()));
+
+            iv_del.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    int layoutPosition = getLayoutPosition();
+                    if (selectList.size() != layoutPosition) {
+                        selectList.remove(layoutPosition);
+                        notifyDataSetChanged();
+                    }
+                }
+            });
+        }
+
+
+    }
+
+    public OnItemClickListener onItemClickListener;
+
+    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
+        this.onItemClickListener = onItemClickListener;
+    }
+
+    public interface OnItemClickListener {
+        void onItemClick(int position);
+    }
+
+    public void setData(List<LocalMedia> list) {
+        selectList.clear();
+        selectList.addAll(list);
+        notifyDataSetChanged();
+    }
+
+    public void addData(List<LocalMedia> list) {
+        for (int i = 0; i < list.size(); i++) {
+            LocalMedia localMedia = list.get(i);
+            selectList.add(localMedia);
+            if (selectList.size() >= maxSelectNum) {
+                break;
+            }
+        }
+        notifyDataSetChanged();
+    }
+
+    public List<LocalMedia> getDataList() {
+        return selectList;
+    }
+}

+ 136 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/VideoListAdapter.java

@@ -0,0 +1,136 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.base.common.BaseApplication;
+import com.cooleshow.base.utils.SizeUtils;
+import com.cooleshow.base.widgets.DensityUtil;
+import com.cooleshow.usercenter.helper.UserHelper;
+import com.dayayuemeng.classroom.R;
+import com.dayayuemeng.classroom.bean.VideoListBean;
+import com.dayayuemeng.classroom.constants.Role;
+import com.dayayuemeng.classroom.widget.CameraPlaceholderView;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+import com.tencent.trtc.TRTCCloudDef;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class VideoListAdapter extends BaseQuickAdapter<VideoListBean, BaseViewHolder> {
+    String userId;
+
+    public VideoListAdapter() {
+        super(R.layout.item_video_view_layout);
+        addChildClickViewIds(R.id.view_click_help);
+        userId = UserHelper.getImUserId();
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, VideoListBean bean) {
+        Log.i("classRoom", "convert:" + bean.toString());
+        holder.setText(R.id.tv_name, getNickName(bean));
+        CameraPlaceholderView iv_camera_off_tip = holder.getView(R.id.iv_camera_off_tip);
+        iv_camera_off_tip.setImageBorderWidth(SizeUtils.dp2px(1));
+        iv_camera_off_tip.setImageWH(SizeUtils.dp2px(42), SizeUtils.dp2px(42));
+        iv_camera_off_tip.setVisibility(bean.getCameraStatus() == 1 ? View.VISIBLE : View.GONE);
+
+        View tv_role_text_stu = holder.getView(R.id.tv_role_text_stu);
+        View tv_role_text1 = holder.getView(R.id.tv_role_text1);
+
+        View tv_hand_up_tag = holder.getView(R.id.tv_hand_up_tag);
+        tv_hand_up_tag.setVisibility(bean.isHandUpOn() ? View.VISIBLE : View.GONE);
+        boolean isTeacher = isTeacher(bean);
+        boolean isOwner = isOwner(bean);
+        if (BaseApplication.Companion.isTeacherClient()) {
+            tv_role_text_stu.setVisibility(View.GONE);
+            tv_role_text1.setVisibility(isTeacher ? View.VISIBLE : View.GONE);
+        } else {
+            tv_role_text1.setVisibility(isOwner ? View.VISIBLE : View.GONE);
+            tv_role_text_stu.setVisibility(isTeacher ? View.VISIBLE : View.GONE);
+        }
+
+        ImageView iv_mic_status = holder.getView(R.id.iv_mic_status);
+        iv_mic_status.setImageResource(bean.isMicrophone() ? R.drawable.tc_icon_mic_level_1 : R.drawable.tc_icon_mic_level_off);
+
+        View cl_root = holder.getView(R.id.cl_root);
+        if (bean.isOnMain()) {
+            setVisibility(false, cl_root);
+            showTipView(holder, bean);
+        } else {
+            setVisibility(true, cl_root);
+            showVideo(holder, bean);
+        }
+        ImageView iv_signal = holder.getView(R.id.iv_signal);
+    }
+
+    public void setVisibility(boolean visible, View itemView) {
+        RecyclerView.LayoutParams param = (RecyclerView.LayoutParams) itemView.getLayoutParams();
+        if (visible) {
+            param.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+            param.width = ViewGroup.LayoutParams.MATCH_PARENT;
+            itemView.setVisibility(View.VISIBLE);
+        } else {
+            itemView.setVisibility(View.GONE);
+            param.height = 0;
+            param.width = 0;
+        }
+        itemView.setLayoutParams(param);
+    }
+
+
+    private boolean isTeacher(VideoListBean bean) {
+        if (bean.getRole() == Role.LECTURER) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isOwner(VideoListBean bean) {
+        return TextUtils.equals(userId, bean.getUserId());
+    }
+
+    private String getNickName(VideoListBean bean) {
+//        if (TextUtils.equals(bean.getUserId(), userId)) {
+//            return "我";
+//        }
+        return bean.getUserName();
+    }
+
+    private void showVideo(BaseViewHolder holder, VideoListBean bean) {
+        FrameLayout fl_video_container = holder.getView(R.id.fl_video_container);
+        FrameLayout fl_tip = holder.getView(R.id.fl_tip);
+        fl_tip.setVisibility(View.GONE);
+        fl_video_container.setVisibility(View.VISIBLE);
+        TXCloudVideoView videoView = bean.getVideoView();
+        fl_video_container.removeAllViews();
+        if (videoView != null) {
+            if (videoView.getParent() != null) {
+                ViewGroup parent = (ViewGroup) videoView.getParent();
+                parent.removeView(videoView);
+            }
+            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+            params.gravity = Gravity.CENTER;
+            fl_video_container.addView(videoView, params);
+        }
+    }
+
+    private void showTipView(BaseViewHolder holder, VideoListBean bean) {
+        FrameLayout fl_video_container = holder.getView(R.id.fl_video_container);
+        FrameLayout fl_tip = holder.getView(R.id.fl_tip);
+        fl_tip.setVisibility(View.VISIBLE);
+        fl_video_container.setVisibility(View.GONE);
+        holder.setText(R.id.tv_tip, bean.getStatusTip());
+    }
+}

+ 72 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/adapter/WhiteBoardListAdapter.java

@@ -0,0 +1,72 @@
+package com.dayayuemeng.classroom.adapter;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+
+import com.dayayuemeng.classroom.R;
+import com.dayayuemeng.classroom.bean.WhiteBoard;
+
+import java.util.List;
+
+
+/**
+ * 课堂资源列表适配
+ */
+public class WhiteBoardListAdapter extends BaseAdapter {
+
+    private List<WhiteBoard> whiteBoardList;
+
+    @Override
+    public int getCount() {
+        return whiteBoardList != null && whiteBoardList.size() > 0 ? whiteBoardList.size() : 0;
+    }
+
+    @Override
+    public WhiteBoard getItem(int position) {
+        return whiteBoardList.get(position);
+
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return 0;
+    }
+
+    @Override
+    public View getView(int position, View convertView, final ViewGroup parent) {
+        final ViewHolder viewHolder;
+        if (convertView == null) {
+            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.class_item_white_board_list, parent, false);
+            viewHolder = new ViewHolder();
+            viewHolder.resourceNameTv = convertView.findViewById(R.id.tv_name);
+            viewHolder.resourcePreviewIv = convertView.findViewById(R.id.iv_preview);
+            convertView.setTag(viewHolder);
+        } else {
+            viewHolder = (ViewHolder) convertView.getTag();
+        }
+        WhiteBoard item = getItem(position);
+        viewHolder.resourceNameTv.setText(item.getName() + (position + 1));
+        return convertView;
+    }
+
+    /**
+     * 设置白板列表
+     * @param list
+     */
+    public void setWhiteBoardList(List<WhiteBoard> list) {
+        whiteBoardList = list;
+        notifyDataSetChanged();
+    }
+
+
+    private class ViewHolder {
+        TextView  resourceNameTv;
+        ImageView resourcePreviewIv;
+    }
+
+}

+ 12 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/ApiConstant.java

@@ -0,0 +1,12 @@
+package com.dayayuemeng.classroom.api;
+
+
+public class ApiConstant {
+    public final static int CONNECT_TIME_OUT = 10;
+    public final static int READ_TIME_OUT = 10;
+    public final static int WRITE_TIME_OUT = 10;
+
+    public final static String SP_NAME_NET = "net";
+    public final static String SP_KEY_NET_COOKIE_SET = "cookie_set";
+    public final static String SP_KEY_NET_HEADER_AUTH = "header_auth";
+}

+ 62 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/ErrorCode.java

@@ -0,0 +1,62 @@
+package com.dayayuemeng.classroom.api;
+
+
+import com.dayayuemeng.classroom.R;
+
+public enum ErrorCode {
+    API_ERR_REQUEST_PARA_ERR(1, R.string.error_api_common_error),
+    API_ERR_INVALID_AUTH(2, R.string.error_api_invalid_auth),
+    API_ERR_ACCESS_DENIED(3, R.string.error_api_permission_denied),
+    API_ERR_BAD_REQUEST(4, R.string.error_api_common_error),
+    API_ERR_OTHER(255, R.string.error_api_common_error),
+    API_ERR_IM_TOKEN_ERROR(10, R.string.error_api_server_error),
+    API_ERR_CREATE_ROOM_ERROR(11, R.string.error_api_create_room_error),
+    API_ERR_JOIN_ROOM_ERROR(12, R.string.error_api_join_room_error),
+    API_ERR_MESSAGE_ERROR(13, R.string.error_api_server_error),
+    API_ERR_ROOM_NOT_EXIST(20, R.string.error_api_room_not_exist),
+    API_ERR_USER_NOT_EXIST_IN_ROOM(21, R.string.error_api_user_not_in_room),
+    API_ERR_EXIT_ROOM_ERROR(22, R.string.error_api_exit_room_error),
+    API_ERR_LECTURER_NOT_EXIST_IN_ROOM(23, R.string.error_api_lecturer_not_in_room),
+    API_ERR_ASSISTANT_NOT_EXIST_IN_ROOM(24, R.string.error_api_assistant_not_in_room),
+    API_ERR_CREATE_WHITE_BOARD(25, R.string.error_api_create_white_board_error),
+    API_ERR_WHITE_BOARD_NOT_EXIST(26, R.string.error_api_white_board_not_exist),
+    API_ERR_DELETE_WHITE_BOARD(27, R.string.error_api_delete_white_error),
+    API_ERR_USER_EXIST_IN_ROOM(28, R.string.error_api_already_in_room),
+    API_ERR_CHANGE_SELF_ROLE(29, R.string.error_api_can_not_change_self_role),
+    API_ERR_APPLY_TICKET_INVALID(30, R.string.error_api_ticket_invalid),
+    API_ERR_OVER_MAX_COUNT(31, R.string.error_api_over_max_count),
+    API_ERR_LECTURER_EXIST_IN_ROOM(32, R.string.error_api_lecturer_has_exist),
+    API_ERR_DOWNGRADE_ROLE(33, R.string.error_api_downgrade_error),
+    API_ERR_CHANGE_ROLE(34, R.string.error_api_change_role_error),
+    NETWORK_ERROR(10000, R.string.error_network_error),
+    IM_ERROR(10003, R.string.error_im_common_error),
+    RTC_ERROR(10004, R.string.error_rtc_common_error),
+    UNKNOWN_ERROR(99999, R.string.error_unkown_error),
+    NONE_ERROR(-1, 0);
+
+    private int code;
+    private int messageResId;
+
+    ErrorCode(int code, int messageResId) {
+        this.code = code;
+        this.messageResId = messageResId;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public int getMessageResId() {
+        return messageResId;
+    }
+
+    public static ErrorCode fromCode(int code) {
+        for (ErrorCode errorCode : ErrorCode.values()) {
+            if (errorCode.code == code)
+                return errorCode;
+        }
+
+        return UNKNOWN_ERROR;
+    }
+
+}

+ 71 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/HttpClientManager.java

@@ -0,0 +1,71 @@
+package com.dayayuemeng.classroom.api;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+
+import com.dayayuemeng.classroom.api.retrofit.RetrofitClient;
+
+import static android.content.Context.MODE_PRIVATE;
+
+
+public class HttpClientManager {
+    private static final String            TAG = "HttpClientManager";
+    private static       HttpClientManager instance;
+    private              Context           context;
+    private RetrofitClient client;
+
+    private HttpClientManager(Context context) {
+        this.context = context;
+        client = new RetrofitClient(context, LiveTeachingUrls.DOMAIN);
+    }
+
+    public static HttpClientManager getInstance(Context context) {
+        if (instance == null) {
+            synchronized (HttpClientManager.class) {
+                if (instance == null) {
+                    instance = new HttpClientManager(context);
+                }
+            }
+        }
+
+        return instance;
+    }
+
+    public RetrofitClient getClient() {
+        return client;
+    }
+
+    /**
+     * 设置用户登录认证
+     *
+     * @param auth
+     */
+    public void setAuthHeader(String auth) {
+        SharedPreferences.Editor config = context.getSharedPreferences(ApiConstant.SP_NAME_NET, MODE_PRIVATE)
+                .edit();
+        config.putString(ApiConstant.SP_KEY_NET_HEADER_AUTH, auth);
+        config.commit();
+    }
+
+    /**
+     * 获取用户登录认证
+     *
+     * @return
+     */
+    public String getCurrentAuth() {
+        SharedPreferences sharedPreferences = context.getSharedPreferences(ApiConstant.SP_NAME_NET, MODE_PRIVATE);
+        return sharedPreferences.getString(ApiConstant.SP_KEY_NET_HEADER_AUTH, null);
+    }
+
+    /**
+     * 清除包括cookie和登录认证
+     */
+    public void clearRequestCache() {
+        SharedPreferences.Editor config = context.getSharedPreferences(ApiConstant.SP_NAME_NET, MODE_PRIVATE)
+                .edit();
+        config.remove(ApiConstant.SP_KEY_NET_HEADER_AUTH);
+        config.remove(ApiConstant.SP_KEY_NET_COOKIE_SET);
+        config.commit();
+    }
+}

+ 263 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/LiveTeachingApi.java

@@ -0,0 +1,263 @@
+package com.dayayuemeng.classroom.api;
+
+
+import com.dayayuemeng.classroom.bean.ClassMember;
+import com.dayayuemeng.classroom.bean.LoginResult;
+
+import java.util.List;
+
+import okhttp3.MultipartBody;
+import okhttp3.RequestBody;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.Field;
+import retrofit2.http.FormUrlEncoded;
+import retrofit2.http.GET;
+import retrofit2.http.Headers;
+import retrofit2.http.Multipart;
+import retrofit2.http.POST;
+import retrofit2.http.Part;
+import retrofit2.http.Query;
+import retrofit2.http.Streaming;
+import retrofit2.http.Url;
+
+public interface LiveTeachingApi {
+    /**
+     * 签到
+     * @return
+     */
+    @FormUrlEncoded
+    @POST(LiveTeachingUrls.SIGN_IN)
+    Call<Result<String>> signIn(@Field("roomId") String roomId);
+
+    /**
+     * 签到
+     * @return
+     */
+    @GET(LiveTeachingUrls.QUERY_NO_JOIN_STU)
+    Call<Result<List<ClassMember>>> queryNoJoinStu(@Query("roomId") String roomId);
+
+    /**
+     * 开关节拍器
+     * @return
+     */
+    @POST(LiveTeachingUrls.SEND_IMPLAY_MIDI_MESSAGE)
+    Call<Result<Boolean>> sendImPlayMidiMessage(@Body RequestBody body);
+
+    /**
+     * 登录
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.LOGIN)
+    Call<Result<LoginResult>> login(@Body RequestBody body);
+
+
+    /**
+     * 查询信息
+     * @param roomId
+     * @return
+     */
+    @GET(LiveTeachingUrls.INFO)
+    Call<Result<LoginResult>> info(@Query("roomId") String roomId);
+
+    /**
+     * 退出房间
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.ROOM_LEAVE)
+    Call<Result<Boolean>> leave(@Body RequestBody body);
+
+
+    /**
+     * 踢人
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.KICK_OFF)
+    Call<Result<Boolean>> kickOff(@Body RequestBody body);
+
+    /**
+     * 控制设备
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.DEVICE_CONTROL)
+    Call<Result<Boolean>> deviceControl(@Body RequestBody body);
+
+    /**
+     * 控制全员设备
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.DEVICE_BATCH_CONTROL)
+    Call<Result<Boolean>> deviceBatchControl(@Body RequestBody body);
+
+    /**
+     * 同意开启设备
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.DEVICE_APPROVE)
+    Call<Result<Boolean>> deviceApprove(@Body RequestBody body);
+
+    /**
+     * 拒绝开启设备
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.DEVICE_REJECT)
+    Call<Result<Boolean>> deviceReject(@Body RequestBody body);
+
+
+    /**
+     * 同步设备状态
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.DEVICE_SYNC)
+    Call<Result<Boolean>> deviceSync(@Body RequestBody body);
+
+
+    /**
+     * 降级
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.DOWNGRADE)
+    Call<Result<Boolean>> downgrade(@Body RequestBody body);
+
+    /**
+     * 申请发言
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.SPEECH_APPLY)
+    Call<Result<Boolean>> applySpeech(@Body RequestBody body);
+
+
+    /**
+     * 同意发言
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.SPEECH_APPROVE)
+    Call<Result<Boolean>> applyApprove(@Body RequestBody body);
+
+
+    /**
+     * 拒绝发言
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.SPEECH_REJECT)
+    Call<Result<Boolean>> applyReject(@Body RequestBody body);
+
+
+    /**
+     * 转移角色
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.TRANSFER_ROLE)
+    Call<Result<Boolean>> transferRole(@Body RequestBody body);
+
+
+    /**
+     * 要求升级
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.UPGRADE_INVITE)
+    Call<Result<Boolean>> upgradeInvite(@Body RequestBody body);
+
+
+    /**
+     * 接受升级
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.UPGRADE_APPROVE)
+    Call<Result<Boolean>> upgradeApprove(@Body RequestBody body);
+
+
+    /**
+     * 拒绝升级
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.UPGRADE_REJECT)
+    Call<Result<Boolean>> upgradeReject(@Body RequestBody body);
+
+
+    /**
+     * 设置角色, 设置为老师
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.CHANGE_ROLE)
+    Call<Result<Boolean>> changeRole(@Body RequestBody body);
+
+
+    /**
+     * 创建白板
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.WHITE_BOARD_CREATE)
+    Call<Result<String>> createWhiteBoard(@Body RequestBody body);
+
+
+    /**
+     * 删除白板
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.WHITE_BOARD_DELETE)
+    Call<Result<Boolean>> deleteWhiteBoard(@Body RequestBody body);
+
+
+    /**
+     * 切换共享画布区内容显示Id
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.SWITCH_DISPLAY)
+    Call<Result<Boolean>> switchDisplay(@Body RequestBody body);
+
+    /**
+     * 通知学生下载伴奏
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.PUSH_DOWNLOAD_EXAM_SONG_MSG)
+    Call<Result<Boolean>> pushDownloadexamSongMsg(@Body RequestBody body);
+
+    /**
+     * 学员伴奏下载回执
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.ADJUST_EXAM_SONG)
+    Call<Result<Boolean>> adjustExamSong(@Body RequestBody body);
+
+    /**
+     * 同步房间状态
+     * @param body
+     * @return
+     */
+    @POST(LiveTeachingUrls.JOIN_ROOM_STATUS_NOTIFY)
+    Call<Result<Boolean>> joinRoomStatusNotify(@Body RequestBody body);
+
+
+    /**
+     * 文件下载
+     * @return
+     */
+    @Streaming
+    @GET
+    @Headers({"User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4)"})
+    Call<ResponseBody> downloadFileWithFixedUrl(@Url String url);
+}

+ 62 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/LiveTeachingUrls.java

@@ -0,0 +1,62 @@
+package com.dayayuemeng.classroom.api;
+
+
+import com.cooleshow.base.BuildConfig;
+
+public class LiveTeachingUrls {
+
+//            public static final String DOMAIN = "http://192.168.3.38:8000/";
+
+    public static final String DOMAIN    = BuildConfig.BASE_SERVER_URL;
+    static final        String api       = "api-im/";
+    public static final String LOGIN     = api + "room/join";
+    public static final String hereWhite = api + "hereWhite/create";
+    public static final String SIGN_IN   = api + "room/signIn";
+    public static final String INFO     = api + "room/info";
+
+    public static final String ROOM_LEAVE               = api + "room/leave";
+    public static final String SEND_IMPLAY_MIDI_MESSAGE = api + "room/sendImPlayMidiMessage";
+    public static final String QUERY_NO_JOIN_STU        = api + "room/queryNoJoinStu";
+    // 列表操作
+    public static final String KICK_OFF                 = api + "room/kick";
+
+    public static final String DEVICE_CONTROL       = api + "room/device/control";
+    public static final String DEVICE_BATCH_CONTROL = api + "room/device/batchControl";
+
+    public static final String DEVICE_APPROVE = api + "room/device/approve";
+
+    public static final String DEVICE_REJECT = api + "room/device/reject";
+
+    public static final String DEVICE_SYNC = api + "room/device/sync";
+
+
+    public static final String DOWNGRADE = api + "room/downgrade";
+
+    public static final String SPEECH_APPLY = api + "room/speech/apply";
+
+    public static final String SPEECH_APPROVE = api + "room/speech/approve";
+
+    public static final String SPEECH_REJECT = api + "room/speech/reject";
+
+    public static final String TRANSFER_ROLE = api + "room/transfer";
+
+    public static final String UPGRADE_INVITE = api + "room/upgrade/invite";
+
+    public static final String UPGRADE_APPROVE = api + "room/upgrade/approve";
+
+    public static final String UPGRADE_REJECT = api + "room/upgrade/reject";
+
+    public static final String CHANGE_ROLE = api + "room/change-role";
+
+    public static final String WHITE_BOARD_CREATE = api + "room/whiteboard/create";
+
+    public static final String WHITE_BOARD_DELETE = api + "room/whiteboard/delete";
+
+
+    public static final String SWITCH_DISPLAY              = api + "room/display";
+    public static final String PUSH_DOWNLOAD_EXAM_SONG_MSG = api + "room/pushDownloadMusicScoreMsg";
+
+    public static final String ADJUST_EXAM_SONG = api + "room/adjustMusicScore";
+    public static final String JOIN_ROOM_STATUS_NOTIFY = api + "room/joinRoomStatusNotify";
+
+}

+ 47 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/RequestState.java

@@ -0,0 +1,47 @@
+package com.dayayuemeng.classroom.api;
+
+
+public class RequestState {
+    private State state;
+    private ErrorCode errorCode;
+
+    private RequestState(State state) {
+        this.state = state;
+        errorCode = ErrorCode.NONE_ERROR;
+    }
+
+    private RequestState(int errorCode) {
+        this.state = State.FAILED;
+        this.errorCode = ErrorCode.fromCode(errorCode);
+    }
+
+    public void setErrorCode(int errorCode) {
+        this.errorCode = ErrorCode.fromCode(errorCode);
+    }
+
+    public State getState() {
+        return state;
+    }
+
+    public ErrorCode getErrorCode() {
+        return errorCode;
+    }
+
+    public enum State {
+        LOADING,
+        SUCCESS,
+        FAILED
+    }
+
+    public static RequestState loading() {
+        return new RequestState(State.LOADING);
+    }
+
+    public static RequestState success() {
+        return new RequestState(State.SUCCESS);
+    }
+
+    public static RequestState failed(int errorCode) {
+        return new RequestState(errorCode);
+    }
+}

+ 82 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/Result.java

@@ -0,0 +1,82 @@
+package com.dayayuemeng.classroom.api;
+
+/**
+ * 网络请求结果基础类
+ *
+ * @param <R> 请求结果的实体类
+ */
+public class Result<R> {
+    private Data<R> data;
+
+    private int errCode;
+    private int code;
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    private String errDetail;
+
+    private String errMsg;
+
+    public Data<R> getData() {
+        return data;
+    }
+
+    public void setData(Data<R> data) {
+        this.data = data;
+    }
+
+    public int getErrCode() {
+        return errCode;
+    }
+
+    public void setErrCode(int errCode) {
+        this.errCode = errCode;
+    }
+
+    public String getErrDetail() {
+        return errDetail;
+    }
+
+    public void setErrDetail(String errDetail) {
+        this.errDetail = errDetail;
+    }
+
+    public String getErrMsg() {
+        return errMsg;
+    }
+
+    public void setErrMsg(String errMsg) {
+        this.errMsg = errMsg;
+    }
+
+    /**
+     * 获取请求结果中的的实体类
+     *
+     * @return R
+     */
+    public R getDataResult() {
+        if (data != null) {
+            return data.getResult();
+        }
+
+        return null;
+    }
+
+    public static class Data<R> {
+        public R result;
+
+        public R getResult() {
+            return result;
+        }
+
+        public void setResult(R result) {
+            this.result = result;
+        }
+    }
+}

+ 11 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/ResultCallback.java

@@ -0,0 +1,11 @@
+package com.dayayuemeng.classroom.api;
+
+/**
+ * 执行 Task 的回调
+ * @param <Result> 请求成功时的结果类
+ */
+public interface ResultCallback<Result> {
+    void onSuccess(Result result);
+
+    void onFail(int errorCode, String errorStr);
+}

+ 51 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/StateLiveData.java

@@ -0,0 +1,51 @@
+package com.dayayuemeng.classroom.api;
+
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Observer;
+
+/**
+ *  记录请求状态用的 LiveData
+ *  内部实现了当请求成功或失败时取消掉监听的功能
+ */
+public class StateLiveData extends MutableLiveData<RequestState> {
+    private LifecycleOwner observerOwner;
+
+    @Override
+    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super RequestState> observer) {
+        observerOwner = owner;
+        ObserverWrapper observerWrapper = new ObserverWrapper(observer);
+        super.observe(owner, observerWrapper);
+    }
+
+    public void loading() {
+        postValue(RequestState.loading());
+    }
+
+    public void success() {
+        postValue(RequestState.success());
+    }
+
+    public void failed(int errorCode) {
+        postValue(RequestState.failed(errorCode));
+    }
+
+    private class ObserverWrapper implements Observer<RequestState> {
+        Observer<? super RequestState> origin;
+
+        ObserverWrapper(Observer<? super RequestState> origin) {
+            this.origin = origin;
+        }
+
+        @Override
+        public void onChanged(RequestState o) {
+            origin.onChanged(o);
+
+            if (o.getState() != RequestState.State.LOADING) {
+                removeObservers(observerOwner);
+            }
+        }
+    }
+}

+ 45 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/WhiteBoardApi.java

@@ -0,0 +1,45 @@
+package com.dayayuemeng.classroom.api;
+
+
+
+import com.cooleshow.base.data.net.BaseResponse;
+import com.dayayuemeng.classroom.bean.WhiteCreateBean;
+
+import io.reactivex.rxjava3.core.Observable;
+import retrofit2.http.Field;
+import retrofit2.http.FormUrlEncoded;
+import retrofit2.http.POST;
+
+/**
+ * 白板API
+ */
+public interface WhiteBoardApi {
+    String TAG                         = "WhiteBoardApi";
+    String HERE_WHITE_URL              = "https://cloudcapiv4.herewhite.com/";
+    String CREATE_ROOM                 = "room?token=%s";
+    String JOIN_ROOM                   = "room/join?uuid=%s&token=%s";
+    String DELETE_ROOM                 = "room/close?token=%s";
+    // 参考服务提供商文档,token写在客户端是不安全的,你“可以”将 Mini Token 写入业务服务器的代码中,或服务端的配置文件中。https://developer.herewhite.com/#/zh-CN/v2/concept
+    String MINI_TOKEN                  = "WHITEcGFydG5lcl9pZD02dFBKT1lzMG52MHFoQzN2Z1BRUXVmN0t0RnVOVGl0bzBhRFAmc2lnPTMyZTRiNTMwNjkyN2RhN2I3NzI4MjMwOTJlZTNmNDJhNWI3MGMyMjU6YWRtaW5JZD0yMTEmcm9sZT1taW5pJmV4cGlyZV90aW1lPTE1ODkzNzY1MjEmYWs9NnRQSk9ZczBudjBxaEMzdmdQUVF1ZjdLdEZ1TlRpdG8wYURQJmNyZWF0ZV90aW1lPTE1NTc4MTk1Njkmbm9uY2U9MTU1NzgxOTU2OTQyNTAw";
+    String WHITE_BOARD_KEY             = "rongRTCWhite";
+    String WHITE_BOARD_SCENE_PATH      = "/DAYA";
+    String WHITE_BOARD_INIT_SCENE_PATH = "/init";
+
+    /**
+     * 创建白板房间
+     * @param
+     * @return
+     */
+    @FormUrlEncoded
+    @POST(LiveTeachingUrls.hereWhite)
+    Observable<BaseResponse<WhiteCreateBean>> hereWhiteCreat(@Field("name") String name, @Field("userNum") int userNum, @Field("courseScheduleId") String courseScheduleId);
+
+    /**
+     * 提交考勤申述
+     * @return
+     */
+    @FormUrlEncoded
+    @POST("api-teacher/teacherAttendance/addComplaints")
+    Observable<BaseResponse<String>> addComplaints(@Field("courseScheduleId") String courseScheduleId, @Field("url") String url, @Field("content") String content, @Field("complaintsType") String complaintsType);
+
+}

+ 45 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/retrofit/CallBackWrapper.java

@@ -0,0 +1,45 @@
+package com.dayayuemeng.classroom.api.retrofit;
+
+
+
+import com.cooleshow.base.utils.LOG;
+import com.dayayuemeng.classroom.api.ErrorCode;
+import com.dayayuemeng.classroom.api.Result;
+import com.dayayuemeng.classroom.api.ResultCallback;
+
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+public class CallBackWrapper<R> implements Callback<Result<R>> {
+    private ResultCallback<R> mCallBack;
+
+    public CallBackWrapper(ResultCallback<R> callBack) {
+        mCallBack = callBack;
+    }
+
+    @Override
+    public void onResponse(Call<Result<R>> call, Response<Result<R>> response) {
+        Result<R> body = response.body();
+        if (body != null) {
+            int errCode = body.getErrCode();
+
+            if (errCode == 0 || body.getCode() == 200) {
+                mCallBack.onSuccess(body.getDataResult());
+            } else {
+                LOG.e("url:" + call.request().url().toString()
+                        + " ,errorMsg:" + body.getErrMsg() + ", errorDetail:" + body.getErrDetail());
+                mCallBack.onFail(errCode, body.getErrMsg());
+            }
+        } else {
+            LOG.e("url:" + call.request().url().toString() + ", no response body");
+            mCallBack.onFail(ErrorCode.API_ERR_OTHER.getCode(), null);
+        }
+    }
+
+    @Override
+    public void onFailure(Call<Result<R>> call, Throwable t) {
+        LOG.e(call.request().url().toString() + " - " + (t != null ? t.getMessage() : ""));
+        mCallBack.onFail(ErrorCode.NETWORK_ERROR.getCode(), null);
+    }
+}

+ 13 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/retrofit/HttpLogger.java

@@ -0,0 +1,13 @@
+package com.dayayuemeng.classroom.api.retrofit;
+
+
+import com.cooleshow.base.utils.LOG;
+
+import okhttp3.logging.HttpLoggingInterceptor;
+
+public class HttpLogger implements HttpLoggingInterceptor.Logger {
+        @Override
+        public void log(String message) {
+            LOG.i( message);
+        }
+    }

+ 121 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/retrofit/RetrofitClient.java

@@ -0,0 +1,121 @@
+package com.dayayuemeng.classroom.api.retrofit;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+
+import com.cooleshow.base.data.net.SSLSocketClient;
+import com.dayayuemeng.classroom.api.ApiConstant;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.logging.HttpLoggingInterceptor;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+import static android.content.Context.MODE_PRIVATE;
+
+public class RetrofitClient {
+    private Context mContext;
+    private Retrofit mRetrofit;
+
+    public RetrofitClient(Context context, String baseUrl) {
+        mContext = context;
+
+        OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder()
+                .retryOnConnectionFailure(true)//错误重连
+                .sslSocketFactory(SSLSocketClient.getSSLSocketFactory(),  SSLSocketClient.getTrustManager())
+                .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
+                .addInterceptor(new AddHeaderInterceptor(mContext))
+                .addInterceptor(new ReceivedCookiesInterceptor(mContext))
+                .addInterceptor(new HttpLoggingInterceptor(new HttpLogger()).setLevel(HttpLoggingInterceptor.Level.BODY))
+                .connectTimeout(ApiConstant.CONNECT_TIME_OUT, TimeUnit.SECONDS)
+                .readTimeout(ApiConstant.READ_TIME_OUT, TimeUnit.SECONDS)
+                .writeTimeout(ApiConstant.WRITE_TIME_OUT, TimeUnit.SECONDS);
+
+        mRetrofit = new Retrofit.Builder()
+                .client(okHttpBuilder.build())
+                .baseUrl(baseUrl) //设置网络请求的Url地址
+                .addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
+                .build();
+    }
+
+    /**
+     * 接受cookie拦截器
+     */
+    public class ReceivedCookiesInterceptor implements Interceptor {
+        private Context mContext;
+
+        public ReceivedCookiesInterceptor(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public Response intercept(Chain chain) throws IOException {
+            Response originalResponse = chain.proceed(chain.request());
+
+            if (!originalResponse.headers("Set-Cookie").isEmpty()) {
+                HashSet<String> cookiesSet = new HashSet<>();
+
+                for (String header : originalResponse.headers("Set-Cookie")) {
+                    cookiesSet.add(header);
+                }
+
+                SharedPreferences.Editor config = mContext.getSharedPreferences(ApiConstant.SP_NAME_NET, MODE_PRIVATE)
+                        .edit();
+                config.putStringSet(ApiConstant.SP_KEY_NET_COOKIE_SET, cookiesSet);
+                config.commit();
+            }
+
+            return originalResponse;
+        }
+    }
+
+    /**
+     * 添加header包含cookie拦截器
+     */
+    public class AddHeaderInterceptor implements Interceptor {
+        private Context mContext;
+
+        public AddHeaderInterceptor(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public Response intercept(Chain chain) throws IOException {
+            Request.Builder builder = chain.request().newBuilder();
+            SharedPreferences preferences = mContext.getSharedPreferences(ApiConstant.SP_NAME_NET,
+                    Context.MODE_PRIVATE);
+
+            //添加cookie
+            HashSet<String> cookieSet = (HashSet<String>) preferences.getStringSet(ApiConstant.SP_KEY_NET_COOKIE_SET, null);
+            if (cookieSet != null) {
+                for (String cookie : cookieSet) {
+                    builder.addHeader("Cookie", cookie);
+                }
+            }
+
+            //添加用户登录认证
+            String auth = preferences.getString(ApiConstant.SP_KEY_NET_HEADER_AUTH, null);
+            if(auth != null) {
+                builder.addHeader("Authorization", auth);
+            }
+
+            return chain.proceed(builder.build());
+        }
+    }
+
+    public <T> T createService(Class<T> service) {
+        return mRetrofit.create(service);
+    }
+
+    private static void allowAllSSL() {
+
+    }
+}

+ 25 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/api/retrofit/RetrofitUtil.java

@@ -0,0 +1,25 @@
+package com.dayayuemeng.classroom.api.retrofit;
+
+import com.google.gson.Gson;
+
+import java.util.HashMap;
+
+import okhttp3.MediaType;
+import okhttp3.RequestBody;
+
+public class RetrofitUtil {
+    private final static MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json;charset=UTF-8");
+
+
+    /**
+     * 通过参数 Map 合集
+     * @param paramsMap
+     * @return
+     */
+    public static RequestBody createJsonRequest(HashMap<String, Object> paramsMap) {
+        Gson gson = new Gson();
+        String strEntity = gson.toJson(paramsMap);
+        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON,strEntity);
+        return body;
+    }
+}

+ 322 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/bean/ClassMember.java

@@ -0,0 +1,322 @@
+package com.dayayuemeng.classroom.bean;
+
+import android.text.TextUtils;
+
+import com.dayayuemeng.classroom.constants.Role;
+import com.google.gson.annotations.SerializedName;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class ClassMember implements Serializable {
+    private boolean camera;
+    private long joinTime;
+    private boolean microphone;
+    private int role;
+    private String userId;
+    private String headUrl;
+    private String userName;
+    private boolean musicMode;
+    private boolean handUpOn;//是否举手
+    private boolean isVisibiliyMic;//是否显示麦克风按钮
+    private boolean isOnStage;//是否上台
+
+    private PlayMidiJsonBean playMidiJson;
+    private List<ScheduleStudentMusicScoresBean> scheduleStudentMusicScores;
+
+
+    public String getHeadUrl() {
+        return headUrl;
+    }
+
+    public void setHeadUrl(String headUrl) {
+        this.headUrl = headUrl;
+    }
+
+    public boolean isMusicMode() {
+        return musicMode;
+    }
+
+    public void setMusicMode(boolean musicMode) {
+        this.musicMode = musicMode;
+    }
+
+    public boolean isHandUpOn() {
+        return handUpOn;
+    }
+
+    public void setHandUpOn(boolean handUpOn) {
+        this.handUpOn = handUpOn;
+    }
+
+    public boolean isOnStage() {
+        return isOnStage;
+    }
+
+    public void setOnStage(boolean onStage) {
+        isOnStage = onStage;
+    }
+
+    public boolean isVisibiliyMic() {
+        return isVisibiliyMic;
+    }
+
+    public void setVisibiliyMic(boolean visibiliyMic) {
+        isVisibiliyMic = visibiliyMic;
+    }
+
+    public boolean isCamera() {
+        return camera;
+    }
+
+    public void setCamera(boolean camera) {
+        this.camera = camera;
+    }
+
+    public long getJoinTime() {
+        return joinTime;
+    }
+
+    public void setJoinTime(long joinTime) {
+        this.joinTime = joinTime;
+    }
+
+    public boolean isMicrophone() {
+        return microphone;
+    }
+
+    public void setMicrophone(boolean microphone) {
+        this.microphone = microphone;
+    }
+
+    public Role getRole() {
+        return Role.createRole(role);
+    }
+
+    public void setRole(int role) {
+        this.role = role;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public PlayMidiJsonBean getPlayMidiJson() {
+        return playMidiJson;
+    }
+
+    public void setPlayMidiJson(PlayMidiJsonBean playMidiJson) {
+        this.playMidiJson = playMidiJson;
+    }
+
+
+    public static class PlayMidiJsonBean implements Serializable {
+        /**
+         * customType : 0
+         * enable : false
+         * userId :
+         * rate : 0
+         */
+
+        private int customType;
+        private boolean enable;
+        @SerializedName("userId")
+        private String userIdX;
+        private int rate;
+        private int playVolume;
+
+        public int getPlayVolume() {
+            return playVolume;
+        }
+
+        public void setPlayVolume(int playVolume) {
+            this.playVolume = playVolume;
+        }
+
+        public int getCustomType() {
+            return customType;
+        }
+
+        public void setCustomType(int customType) {
+            this.customType = customType;
+        }
+
+        public boolean isEnable() {
+            return enable;
+        }
+
+        public void setEnable(boolean enable) {
+            this.enable = enable;
+        }
+
+        public String getUserIdX() {
+            return userIdX;
+        }
+
+        public void setUserIdX(String userIdX) {
+            this.userIdX = userIdX;
+        }
+
+        public int getRate() {
+            return rate;
+        }
+
+        public void setRate(int rate) {
+            this.rate = rate;
+        }
+    }
+
+
+    public List<ScheduleStudentMusicScoresBean> getScheduleStudentMusicScores() {
+        return scheduleStudentMusicScores;
+    }
+
+    public void setScheduleStudentMusicScores(List<ScheduleStudentMusicScoresBean> scheduleStudentMusicScores) {
+        this.scheduleStudentMusicScores = scheduleStudentMusicScores;
+    }
+
+    public static class ScheduleStudentMusicScoresBean implements Serializable {
+        public ScheduleStudentMusicScoresBean() {
+
+        }
+
+        public ScheduleStudentMusicScoresBean(int accompanimentPlayStatus, int playStatus) {
+            this.accompanimentPlayStatus = accompanimentPlayStatus;
+            this.playStatus = playStatus;
+        }
+
+        public ScheduleStudentMusicScoresBean(int accompanimentPlayStatus, int downStatus, String musicScoreAccompanimentId, int playStatus, int speed, String url, String mp3Url, String musicScoreName) {
+            this.accompanimentPlayStatus = accompanimentPlayStatus;
+            this.downStatus = downStatus;
+            this.musicScoreAccompanimentId = musicScoreAccompanimentId;
+            this.playStatus = playStatus;
+            this.speed = speed;
+            this.url = url;
+            this.mp3Url = mp3Url;
+            this.musicScoreName = musicScoreName;
+        }
+
+        /**
+         * accompanimentPlayStatus : 0
+         * downStatus : 0
+         * id : 48
+         * musicScoreAccompanimentId : 86
+         * playStatus : 0
+         * speed : 90
+         * url :
+         * mp3Url :
+         */
+
+        private int accompanimentPlayStatus;
+        private int downStatus;
+        private String id;
+        private String musicScoreAccompanimentId;
+        private int playStatus;
+        private int speed;
+        private String url;
+        private String mp3Url;
+        private String musicScoreName;
+        private int isAccompaniment;
+
+
+        public int getIsAccompaniment() {
+            return isAccompaniment;
+        }
+
+        public void setIsAccompaniment(int isAccompaniment) {
+            this.isAccompaniment = isAccompaniment;
+        }
+
+        public String getMusicScoreName() {
+            return musicScoreName;
+        }
+
+        public void setMsicScoreName(String musicScoreName) {
+            this.musicScoreName = musicScoreName;
+        }
+
+        public int getAccompanimentPlayStatus() {
+            return accompanimentPlayStatus;
+        }
+
+        public void setAccompanimentPlayStatus(int accompanimentPlayStatus) {
+            this.accompanimentPlayStatus = accompanimentPlayStatus;
+        }
+
+        public int getDownStatus() {
+            return downStatus;
+        }
+
+        public void setDownStatus(int downStatus) {
+            this.downStatus = downStatus;
+        }
+
+        public String getId() {
+            return id;
+        }
+
+        public void setId(String id) {
+            this.id = id;
+        }
+
+        public String getMusicScoreAccompanimentId() {
+            return musicScoreAccompanimentId;
+        }
+
+        public void setMusicScoreAccompanimentId(String musicScoreAccompanimentId) {
+            this.musicScoreAccompanimentId = musicScoreAccompanimentId;
+        }
+
+        public int getPlayStatus() {
+            return playStatus;
+        }
+
+        public void setPlayStatus(int playStatus) {
+            this.playStatus = playStatus;
+        }
+
+        public int getSpeed() {
+            return speed;
+        }
+
+        public void setSpeed(int speed) {
+            this.speed = speed;
+        }
+
+        public String getUrl() {
+            return url;
+        }
+
+        public void setUrl(String url) {
+            this.url = url;
+        }
+
+        public String getMp3Url() {
+            return mp3Url;
+        }
+
+        public String getMp3UrlName() {
+            return TextUtils.isEmpty(mp3Url) ? "" : mp3Url.substring(mp3Url.lastIndexOf("/") + 1);
+        }
+
+        public String getUrlName() {
+            return TextUtils.isEmpty(url) ? "" : url.substring(url.lastIndexOf("/") + 1);
+        }
+
+        public void setMp3Url(String mp3Url) {
+            this.mp3Url = mp3Url;
+        }
+    }
+}

+ 25 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/bean/GonggeVideoListBean.java

@@ -0,0 +1,25 @@
+package com.dayayuemeng.classroom.bean;
+
+/**
+ * Author by pq, Date on 2023/5/5.
+ */
+public class GonggeVideoListBean extends VideoListBean {
+    private int height;
+    private int width;
+
+    public int getHeight() {
+        return height;
+    }
+
+    public void setHeight(int height) {
+        this.height = height;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public void setWidth(int width) {
+        this.width = width;
+    }
+}

+ 215 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/bean/LoginResult.java

@@ -0,0 +1,215 @@
+package com.dayayuemeng.classroom.bean;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class LoginResult implements Serializable {
+    private String            authorization;
+    private String            display;
+    private String            imToken;
+    private String            roomId;
+    private int surplusTime;
+    private int soundVolume; //音量
+    private String            whiteBoradUuid;//白板uuid 白板对象赋值
+    private String            whiteBoradRoomToken; //白板token白板对象赋值
+    private UserInfo          userInfo;
+    private List<ClassMember> members;
+    private List<WhiteBoard>  whiteboards;
+    private boolean autoCloseFlag ;//课程结束后是否自动关闭课程
+    private int autoCloseNetworkRoomTime ;//课程结束后多少分钟关闭网络教室
+    public String randomNumeric;// 1 自定义白板 0 默认白板
+    private RoomConfig rtcRoomConfig;
+    private String serviceProvider;//tencentCloud, rongCloud
+    private int studentNums;//多人或者单人
+
+    public RoomConfig getRtcRoomConfig() {
+        return rtcRoomConfig;
+    }
+
+    public void setRtcRoomConfig(RoomConfig rtcRoomConfig) {
+        this.rtcRoomConfig = rtcRoomConfig;
+    }
+
+    public String getServiceProvider() {
+        return serviceProvider;
+    }
+
+    public void setServiceProvider(String serviceProvider) {
+        this.serviceProvider = serviceProvider;
+    }
+
+    public int getStudentNums() {
+        return studentNums;
+    }
+
+    public boolean isAutoCloseFlag() {
+        return autoCloseFlag;
+    }
+
+    public int getAutoCloseNetworkRoomTime() {
+        return autoCloseNetworkRoomTime;
+    }
+
+    public void setAutoCloseFlag(boolean autoCloseFlag) {
+        this.autoCloseFlag = autoCloseFlag;
+    }
+
+    public void setAutoCloseNetworkRoomTime(int autoCloseNetworkRoomTime) {
+        this.autoCloseNetworkRoomTime = autoCloseNetworkRoomTime;
+    }
+
+    public int getSurplusTime() {
+        return surplusTime;
+    }
+
+    public void setSurplusTime(int surplusTime) {
+        this.surplusTime = surplusTime;
+    }
+
+    public String getWhiteBoradUuid() {
+        return whiteBoradUuid;
+    }
+
+    public void setWhiteBoradUuid(String whiteBoradUuid) {
+        this.whiteBoradUuid = whiteBoradUuid;
+    }
+
+    public String getWhiteBoradRoomToken() {
+        return whiteBoradRoomToken;
+    }
+
+    public void setWhiteBoradRoomToken(String whiteBoradRoomToken) {
+        this.whiteBoradRoomToken = whiteBoradRoomToken;
+    }
+
+    public String getAuthorization() {
+        return authorization;
+    }
+
+    public void setAuthorization(String authorization) {
+        this.authorization = authorization;
+    }
+
+    public String getDisplay() {
+        return display;
+    }
+
+    public void setDisplay(String display) {
+        this.display = display;
+    }
+
+    public String getImToken() {
+        return imToken;
+    }
+
+    public void setImToken(String imToken) {
+        this.imToken = imToken;
+    }
+
+    public String getRoomId() {
+        return roomId;
+    }
+
+    public void setRoomId(String roomId) {
+        this.roomId = roomId;
+    }
+
+    public UserInfo getUserInfo() {
+        return userInfo;
+    }
+
+    public void setUserInfo(UserInfo userInfo) {
+        this.userInfo = userInfo;
+    }
+
+    public List<ClassMember> getMembers() {
+        return members;
+    }
+
+    public void setMembers(List<ClassMember> members) {
+        this.members = members;
+    }
+
+    public List<WhiteBoard> getWhiteboards() {
+        return whiteboards;
+    }
+
+    public void setWhiteboards(List<WhiteBoard> whiteboards) {
+        this.whiteboards = whiteboards;
+    }
+
+    public int getSoundVolume() {
+        return soundVolume;
+    }
+
+    public void setSoundVolume(int soundVolume) {
+        this.soundVolume = soundVolume;
+    }
+
+    public static class RoomConfig implements Serializable{
+
+        /**
+         * appKey : 1400805079
+         * appSecret : c5f4ea6140128a36c842990446a2c89249ab886b5e1ea6893555aa635a0b3c30
+         * rtcAppKey : 1400805079
+         * rtcAppSecret : c5f4ea6140128a36c842990446a2c89249ab886b5e1ea6893555aa635a0b3c30
+         * rtcUserSig : eJw1jlsLgkAQhf-LPIfMZJor9OCCRCAUKUG9BXtpkGLdFgmi-96i9Xgu3*G8oWvaRL8cew1lSoQrRFxM7qg9lLBMEGb9VP3VOVZQUiwVmOFazAkr-QhseAIoDiD9GbbR2lW9EUNwfm8O0lJug7scM8Ywnk*NlZ2SQyvqvrtt680PDHyPhygvSBRIKX2*FFIwzA__
+         * userSig : eJw1jlsLgkAQhf-LPIfMZJor9OCCRCAUKUG9BXtpkGLdFgmi-96i9Xgu3*G8oWvaRL8cew1lSoQrRFxM7qg9lLBMEGb9VP3VOVZQUiwVmOFazAkr-QhseAIoDiD9GbbR2lW9EUNwfm8O0lJug7scM8Ywnk*NlZ2SQyvqvrtt680PDHyPhygvSBRIKX2*FFIwzA__
+         */
+
+        private String appKey;
+        private String appSecret;
+        private String rtcAppKey;
+        private String rtcAppSecret;
+        private String rtcUserSig;
+        private String userSig;
+
+        public String getAppKey() {
+            return appKey;
+        }
+
+        public void setAppKey(String appKey) {
+            this.appKey = appKey;
+        }
+
+        public String getAppSecret() {
+            return appSecret;
+        }
+
+        public void setAppSecret(String appSecret) {
+            this.appSecret = appSecret;
+        }
+
+        public String getRtcAppKey() {
+            return rtcAppKey;
+        }
+
+        public void setRtcAppKey(String rtcAppKey) {
+            this.rtcAppKey = rtcAppKey;
+        }
+
+        public String getRtcAppSecret() {
+            return rtcAppSecret;
+        }
+
+        public void setRtcAppSecret(String rtcAppSecret) {
+            this.rtcAppSecret = rtcAppSecret;
+        }
+
+        public String getRtcUserSig() {
+            return rtcUserSig;
+        }
+
+        public void setRtcUserSig(String rtcUserSig) {
+            this.rtcUserSig = rtcUserSig;
+        }
+
+        public String getUserSig() {
+            return userSig;
+        }
+
+        public void setUserSig(String userSig) {
+            this.userSig = userSig;
+        }
+    }
+}

+ 13 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/bean/UserInfo.java

@@ -0,0 +1,13 @@
+package com.dayayuemeng.classroom.bean;
+
+public class UserInfo extends ClassMember {
+    private boolean applySpeeching = false;
+
+    public boolean isApplySpeeching() {
+        return applySpeeching;
+    }
+
+    public void setApplySpeeching(boolean applySpeeching) {
+        this.applySpeeching = applySpeeching;
+    }
+}

+ 115 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/bean/VideoListBean.java

@@ -0,0 +1,115 @@
+package com.dayayuemeng.classroom.bean;
+
+import com.dayayuemeng.classroom.constants.Role;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class VideoListBean extends ClassMember {
+    private String streamId;
+    private String timestamp;
+    private String statusTip;
+    private boolean isOnMain;//是否在主屏
+    private TXCloudVideoView videoView;
+    private int signalLevel;//0-6个等级  1 2满格 3是2格 4是1格 5是空格 6和0是XX
+    private int cameraStatus; //0是开启 1是关闭
+
+    public int getCameraStatus() {
+        return cameraStatus;
+    }
+
+    public void setCameraStatus(int cameraStatus) {
+        this.cameraStatus = cameraStatus;
+    }
+
+    public int getSignalLevel() {
+        return signalLevel;
+    }
+
+    public void setSignalLevel(int signalLevel) {
+        this.signalLevel = signalLevel;
+    }
+
+    public boolean isOnMain() {
+        return isOnMain;
+    }
+
+    public void setOnMain(boolean onMain) {
+        isOnMain = onMain;
+    }
+
+    public String getStatusTip() {
+        return statusTip;
+    }
+
+    public void setStatusTip(String statusTip) {
+        this.statusTip = statusTip;
+    }
+
+    public String getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(String timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getStreamId() {
+        return streamId;
+    }
+
+    public void setStreamId(String streamId) {
+        this.streamId = streamId;
+    }
+
+    public String getName() {
+        return super.getUserName();
+    }
+
+    public void setName(String name) {
+        super.setUserName(name);
+    }
+
+    public String getUserId() {
+        return super.getUserId();
+    }
+
+    public void setUserId(String userId) {
+        super.setUserId(userId);
+    }
+
+    public void setRole(Role role) {
+        super.setRole(role.getValue());
+    }
+
+    public TXCloudVideoView getVideoView() {
+        return videoView;
+    }
+
+    public void setVideoView(TXCloudVideoView videoView) {
+        this.videoView = videoView;
+    }
+
+    public static VideoListBean createTeacherDefault(String userId) {
+        VideoListBean videoListBean = new VideoListBean();
+        videoListBean.setUserId(userId);
+        videoListBean.setRole(Role.LECTURER.getValue());
+        return videoListBean;
+    }
+
+    @Override
+    public String toString() {
+        return "VideoListBean{" +
+                "streamId='" + streamId + '\'' +
+                ", name='" + getUserName() + '\'' +
+                ", userId='" + getUserId() + '\'' +
+                ", userAvatar='" + getHeadUrl() + '\'' +
+                ", role=" + getRole() +
+                ", timestamp='" + timestamp + '\'' +
+                ", statusTip='" + statusTip + '\'' +
+                ", isOnMain=" + isOnMain +
+                ", videoView=" + videoView +
+                '}';
+    }
+}

+ 33 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/bean/WhiteBoard.java

@@ -0,0 +1,33 @@
+package com.dayayuemeng.classroom.bean;
+
+import java.io.Serializable;
+
+public class WhiteBoard implements Serializable {
+    private int curPg;
+    private String name;
+    private String whiteboardId;
+
+    public int getCurPg() {
+        return curPg;
+    }
+
+    public void setCurPg(int curPg) {
+        this.curPg = curPg;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getWhiteboardId() {
+        return whiteboardId;
+    }
+
+    public void setWhiteboardId(String whiteboardId) {
+        this.whiteboardId = whiteboardId;
+    }
+}

+ 141 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/bean/WhiteCreateBean.java

@@ -0,0 +1,141 @@
+package com.dayayuemeng.classroom.bean;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2019/11/6 18:38
+ */
+public class WhiteCreateBean {
+
+    /**
+     * adminId : 489
+     * courseScheduleId : 433
+     * createdAt : 1573036689566
+     * limit : 100
+     * mode : transitory
+     * name : Page1
+     * region : cn
+     * roomToken : WHITEcGFydG5lcl9pZD1EUzdrQ3JOenJnRU1Hc1ZnelV5T1czOFl3ZlJuTUF5MjMyMmkmc2lnPTE5OTNmNDY1NzU5NTI2MTRjYjNlOTRjYTE4NmI5MjllNjEzOWEzNzg6YWRtaW5JZD00ODkmcm9vbUlkPTcwODc1NTJmMzY2MjRhNTk5ZjI1ZWY0OTNmYjg1ZmZjJnRlYW1JZD02MTQmcm9sZT1yb29tJmV4cGlyZV90aW1lPTE2MDQ1OTM2NDEmYWs9RFM3a0NyTnpyZ0VNR3NWZ3pVeU9XMzhZd2ZSbk1BeTIzMjJpJmNyZWF0ZV90aW1lPTE1NzMwMzY2ODkmbm9uY2U9MTU3MzAzNjY4OTM1MTAw
+     * teamId : 614
+     * template : meeting
+     * updatedAt : 1573036689566
+     * uuid : 7087552f36624a599f25ef493fb85ffc
+     */
+
+    private int adminId;
+    private int    courseScheduleId;
+    private long   createdAt;
+    private int    limit;
+    private String mode;
+    private String name;
+    private String region;
+    private String roomToken;
+    private int    teamId;
+    private String template;
+    private long   updatedAt;
+    private String uuid;
+    private String randomNumeric20;
+    private String randomNumeric22;
+
+    public String getRandomNumeric() {
+        return randomNumeric20+","+randomNumeric22;
+    }
+
+    public int getAdminId() {
+        return adminId;
+    }
+
+    public void setAdminId(int adminId) {
+        this.adminId = adminId;
+    }
+
+    public int getCourseScheduleId() {
+        return courseScheduleId;
+    }
+
+    public void setCourseScheduleId(int courseScheduleId) {
+        this.courseScheduleId = courseScheduleId;
+    }
+
+    public long getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(long createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public int getLimit() {
+        return limit;
+    }
+
+    public void setLimit(int limit) {
+        this.limit = limit;
+    }
+
+    public String getMode() {
+        return mode;
+    }
+
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    public void setRegion(String region) {
+        this.region = region;
+    }
+
+    public String getRoomToken() {
+        return roomToken;
+    }
+
+    public void setRoomToken(String roomToken) {
+        this.roomToken = roomToken;
+    }
+
+    public int getTeamId() {
+        return teamId;
+    }
+
+    public void setTeamId(int teamId) {
+        this.teamId = teamId;
+    }
+
+    public String getTemplate() {
+        return template;
+    }
+
+    public void setTemplate(String template) {
+        this.template = template;
+    }
+
+    public long getUpdatedAt() {
+        return updatedAt;
+    }
+
+    public void setUpdatedAt(long updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+}

+ 33 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/bean/WhiteSdkRoomInfo.java

@@ -0,0 +1,33 @@
+package com.dayayuemeng.classroom.bean;
+
+import java.io.Serializable;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2019/11/3 11:34
+ */
+public class WhiteSdkRoomInfo implements Serializable {
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    private String uuid;
+
+    public String getRoomToken() {
+        return roomToken;
+    }
+
+    public void setRoomToken(String roomToken) {
+        this.roomToken = roomToken;
+    }
+
+    private String roomToken;
+
+}

+ 17 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/constants/ARouterSealClass.java

@@ -0,0 +1,17 @@
+package com.dayayuemeng.classroom.constants;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2016
+ * ARouter 注解路径标识
+ * Date       : 2019/7/18 0018 17:28
+ */
+public final class ARouterSealClass {
+    public static final String PATH = "path";
+    public static final String ACTIVITY_USER_LOGIN = "/sealclass/LoginActivity";
+    public static final String ACTIVITY_CLASS = "/sealclass/ClassActivity";
+    public static final String ACTIVITY_CLASS_ROOM = "/classroom/TeacherNetClassRoomActivity";
+    public static final String ACTIVITY_CLASS_ROOM_STU = "/classroom/StudentNetClassRoomActivity";
+
+    public static final String ACTIVITY_ACCOMPANIMENT_LIST  = "/classroom/AccompanimentListActivity";
+}

+ 37 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/constants/ClassRoomConstants.java

@@ -0,0 +1,37 @@
+package com.dayayuemeng.classroom.constants;
+
+/**
+ * Author by pq, Date on 2023/5/18.
+ */
+public class ClassRoomConstants {
+    //加入房间的信息 LoginResult
+    public static final String EXTRA_LOGIN_RESULT = "extra_login_result";
+    //是否开启相机
+    public static final String EXTRA_CLOSE_CAMERA = "extra_open_camera";
+    //教室ID
+    public static final String CLASS_ID = "class_id";
+    public static final String SUBJECT_ID = "subject_id";
+    public static final String CANCEL_MUTE_FLAG = "cancelMuteFlag";
+    public static final String IS_MUTE_ALL = "isMuteAll";
+
+    //是否显示弹幕消息
+    public static boolean isShowBarrageMessage = true;
+
+    public static boolean isCanCancelMute = true;//是否可以解除静音
+    public static boolean isCanCancelMuteFlag = true;//老师端记录是否可以解除静音
+    public static boolean isMuteAll = false;//是否全员静音模式
+
+
+    public static final String SUBJECT_ID_SAX = "5";//萨克斯
+    public static final String SUBJECT_ID_TENOR_HORN = "16";//次中音号
+    public static final String SUBJECT_ID_TRUMPET = "12";//小号
+    public static final String SUBJECT_ID_TROMBONE = "14";//长号
+
+    /**
+     * 是否可以解除静音模式
+     * @return
+     */
+    public static boolean isLimitCancelMute() {
+        return isMuteAll && !isCanCancelMute;
+    }
+}

+ 32 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/constants/DeviceType.java

@@ -0,0 +1,32 @@
+package com.dayayuemeng.classroom.constants;
+
+/**
+ * 设备类型
+ */
+public enum DeviceType {
+    Microphone(0),
+    Camera(1),
+    musicMode(2),
+    handUpOn(3),
+    ExamSong(4),
+    MusicScore(5),
+    MusicScoreAccompaniment(6),
+    UNKNOWN(-999);
+
+    private int type;
+
+    DeviceType(int type) {
+        this.type = type;
+    }
+
+    public static DeviceType getDeviceType(int type) {
+        DeviceType[] values = DeviceType.values();
+        for (DeviceType deviceType : values) {
+            if (deviceType.type == type) {
+                return deviceType;
+            }
+        }
+
+        return UNKNOWN;
+    }
+}

+ 35 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/constants/InviteAction.java

@@ -0,0 +1,35 @@
+package com.dayayuemeng.classroom.constants;
+
+/**
+ * 请求行为
+ */
+public enum InviteAction {
+    INVITE(1), // 邀请
+
+    REJECT(2), // 拒绝
+
+    APPROVE(3), // 同意
+
+    UNKNOWN(-999);
+
+    private int type;
+
+    InviteAction(int type) {
+        this.type = type;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public static InviteAction getAction(int type) {
+        InviteAction[] values = InviteAction.values();
+        for (InviteAction action : values) {
+            if (action.type == type) {
+                return action;
+            }
+        }
+
+        return UNKNOWN;
+    }
+}

+ 41 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/constants/RightOperate.java

@@ -0,0 +1,41 @@
+package com.dayayuemeng.classroom.constants;
+
+import com.dayayuemeng.classroom.ui.fragment.NewTopOperateControlFragment;
+
+/**
+ * Author by pq, Date on 2023/7/11.
+ */
+public enum RightOperate {
+    /**
+     * 弹幕消息
+     */
+    CHAT_BARRAGE(0),
+    /**
+     * 聊天
+     */
+    MESSAGE(1),
+    /**
+     * 学员管理
+     */
+    MEMBER(2);
+
+
+    private int value;
+
+    RightOperate(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public static RightOperate getType(int value) {
+        for (RightOperate type : RightOperate.values()) {
+            if (value == type.getValue()) {
+                return type;
+            }
+        }
+        return MEMBER;
+    }
+}

+ 80 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/constants/Role.java

@@ -0,0 +1,80 @@
+package com.dayayuemeng.classroom.constants;
+
+
+import com.dayayuemeng.classroom.permission.ClassExecutedPermission;
+import com.dayayuemeng.classroom.permission.ClassPermission;
+import com.dayayuemeng.classroom.permission.PermissionGroup;
+import com.dayayuemeng.classroom.permission.PermissionGroupFactory;
+import com.dayayuemeng.classroom.permission.PermissionGroupLevel;
+
+/**
+ * 权限组类型等级
+ */
+public enum Role {
+    /**
+     * 助教权限组
+     */
+    ASSISTANT(1, PermissionGroupLevel.GROUP_ASSISTANT),
+    /**
+     * 讲师权限组
+     */
+    LECTURER(2, PermissionGroupLevel.GROUP_LECTURER),
+
+    /**
+     * 学员权限组
+     */
+    STUDENT(3, PermissionGroupLevel.GROUP_STUDENT),
+    /**
+     * 旁听者权限组
+     */
+    LISTENER(4, PermissionGroupLevel.GROUP_LISTENER);
+
+
+
+    private PermissionGroup permGroup;
+
+    private PermissionGroupLevel level;
+
+    private int value;
+
+
+
+    Role(int value, PermissionGroupLevel level) {
+         this.value = value;
+         this.level = level;
+         permGroup = PermissionGroupFactory.getPermissionGroup(level);
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    /**
+     * 是否存在可执行的权限
+     * @param permission 可执行权限, 具体可查看{@link ClassPermission}
+     * @return true 存在; false 不存在
+     */
+    public boolean hasPermission(ClassPermission permission) {
+        return permGroup.hasPermission(permission);
+    }
+
+    /**
+     * 是否存在可被执行的权限
+     * @param permission 被执行权限, 具体可查看{@link ClassExecutedPermission}
+     * @return true 存在; false 不存在
+     */
+    public boolean hasExecutedPermission(ClassExecutedPermission permission) {
+        return permGroup.hasExecutedPermission(permission);
+    }
+
+    public static Role createRole(int value) {
+        Role[] roles = Role.values();
+        for (Role role : roles) {
+            if  (role.getValue() == value) {
+                return role;
+            }
+        }
+        return Role.LISTENER;
+    }
+
+}

+ 8 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/constants/TTMessageConstants.java

@@ -0,0 +1,8 @@
+package com.dayayuemeng.classroom.constants;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class TTMessageConstants {
+    public static final String TAG_MEMBER_CHANGE = "SC:RMCMsg"; //老师控制学生麦克风模式
+}

+ 12 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/contract/MainVideoFragmentContractView.java

@@ -0,0 +1,12 @@
+package com.dayayuemeng.classroom.contract;
+
+import com.cooleshow.base.presenter.view.BaseView;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public interface MainVideoFragmentContractView {
+    interface View extends BaseView {
+
+    }
+}

+ 22 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/contract/NewConversationView.java

@@ -0,0 +1,22 @@
+package com.dayayuemeng.classroom.contract;
+
+import com.cooleshow.base.presenter.view.BaseView;
+import com.daya.tclive.bean.TTMessage;
+import com.tencent.imsdk.v2.V2TIMMessage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Author by pq, Date on 2023/4/24.
+ */
+public interface NewConversationView {
+    interface View extends BaseView {
+
+
+        void getGroupHistoryMessageSuccess(ArrayList<TTMessage> v2TIMMessages);
+    }
+    interface Presenter {
+
+    }
+}

+ 60 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/contract/StudentNetClassRoomContract.java

@@ -0,0 +1,60 @@
+package com.dayayuemeng.classroom.contract;
+
+import com.cooleshow.base.presenter.view.BaseView;
+import com.daya.tclive.bean.TTMessage;
+import com.dayayuemeng.classroom.im.message.TTControlDeviceStateMessage;
+import com.dayayuemeng.classroom.im.message.TTDeviceStateChangedMessage;
+import com.dayayuemeng.classroom.im.message.TTDisplayMessage;
+import com.dayayuemeng.classroom.im.message.TTMemberChangedMessage;
+import com.dayayuemeng.classroom.im.message.TTMusicSyncMessage;
+import com.dayayuemeng.classroom.model.PlayMidi;
+import com.tencent.trtc.TRTCCloudDef;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+public interface StudentNetClassRoomContract {
+    interface View extends BaseView {
+
+        void enterLiveRoomSuccess();
+
+        void enterLiveRoomError();
+
+        void loginIMSuccess();
+
+        void connectIMError(int code, String desc);
+
+        void onStopPublishing();
+
+        void onPublishSuccess();
+
+        void onMemberChanged(TTMemberChangedMessage content);
+
+        void onDisPlayChangeMessage(TTDisplayMessage ttDisplayMessage);
+
+        void onDeviceStateChanged(TTDeviceStateChangedMessage stateChangedMessage);
+
+        void onControlDeviceState(TTControlDeviceStateMessage controlDeviceStateMessage);
+
+        void playBeatMessage(PlayMidi playBeatMessage);
+
+
+        void onMusicSyncMessage(TTMusicSyncMessage musicSyncMessage);
+
+        void onNetworkQuality(TRTCCloudDef.TRTCQuality localQuality, ArrayList<TRTCCloudDef.TRTCQuality> remoteQuality);
+
+        void receiveTextMessage(TTMessage message);
+
+        void onUserVoiceVolume(ArrayList<TRTCCloudDef.TRTCVolumeInfo> userVolumes, int totalVolume);
+
+        void getAllGroupAttributesSuccess(Object o);
+
+        void onGroupAttributeChanged(String groupID, Map<String, String> groupAttributeMap);
+
+    }
+
+    interface Presenter {
+
+    }
+
+}

+ 43 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/contract/TeacherNetClassRoomContract.java

@@ -0,0 +1,43 @@
+package com.dayayuemeng.classroom.contract;
+
+import com.cooleshow.base.presenter.view.BaseView;
+import com.daya.tclive.bean.TTMessage;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.dayayuemeng.classroom.im.message.TCClassRoomTextMessage;
+import com.dayayuemeng.classroom.im.message.TTDeviceStateChangedMessage;
+import com.dayayuemeng.classroom.im.message.TTMemberChangedMessage;
+import com.tencent.trtc.TRTCCloudDef;
+
+import java.util.ArrayList;
+
+public interface TeacherNetClassRoomContract {
+    interface View extends BaseView {
+
+        void enterLiveRoomSuccess();
+
+        void enterLiveRoomError();
+
+        void loginIMSuccess();
+
+        void connectIMError(int code, String desc);
+
+        void onStopPublishing();
+
+        void onPublishSuccess();
+
+        void onMemberChanged(TTMemberChangedMessage content);
+
+        void onDeviceStateChanged(TTDeviceStateChangedMessage stateChangedMessage);
+
+        void onNetworkQuality(TRTCCloudDef.TRTCQuality localQuality, ArrayList<TRTCCloudDef.TRTCQuality> remoteQuality);
+
+        void receiveTextMessage(TTMessage textMessage);
+
+        void onUserVoiceVolume(ArrayList<TRTCCloudDef.TRTCVolumeInfo> userVolumes, int totalVolume);
+    }
+
+    interface Presenter {
+
+    }
+
+}

+ 20 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/contract/TopOperateControlView.java

@@ -0,0 +1,20 @@
+package com.dayayuemeng.classroom.contract;
+
+import com.cooleshow.base.presenter.view.BaseView;
+
+/**
+ * Author by pq, Date on 2023/4/24.
+ */
+public interface TopOperateControlView {
+    interface View extends BaseView {
+
+        void deviceSyncMicResult(boolean microphoneOn,Boolean result);
+
+
+        void deviceSyncCameraResult(boolean cameraOn,Boolean result);
+
+    }
+    interface Presenter {
+
+    }
+}

+ 31 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/helper/ClassRoomEnterHelper.java

@@ -0,0 +1,31 @@
+package com.dayayuemeng.classroom.helper;
+
+import android.text.TextUtils;
+
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.cooleshow.base.common.BaseApplication;
+import com.dayayuemeng.classroom.bean.LoginResult;
+import com.dayayuemeng.classroom.constants.ARouterSealClass;
+import com.dayayuemeng.classroom.constants.ClassRoomConstants;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class ClassRoomEnterHelper {
+    public static boolean handleEnterAction(LoginResult loginResult, String classId, String subjectId) {
+        if (TextUtils.equals(loginResult.getServiceProvider(), "tencentCloud")) {
+            String path = ARouterSealClass.ACTIVITY_CLASS_ROOM_STU;
+            if (BaseApplication.Companion.isTeacherClient()) {
+                path = ARouterSealClass.ACTIVITY_CLASS_ROOM;
+            }
+            ARouter.getInstance().build(path)
+                    .withSerializable(ClassRoomConstants.EXTRA_LOGIN_RESULT, loginResult)
+                    .withBoolean(ClassRoomConstants.EXTRA_CLOSE_CAMERA, false)
+                    .withString(ClassRoomConstants.CLASS_ID, classId)
+                    .withString(ClassRoomConstants.SUBJECT_ID, subjectId)
+                    .navigation();
+            return true;
+        }
+        return false;
+    }
+}

+ 98 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/helper/OpenClassRoomHelper.java

@@ -0,0 +1,98 @@
+package com.dayayuemeng.classroom.helper;
+
+import android.Manifest;
+import android.app.Activity;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.cooleshow.base.common.BaseApplication;
+import com.cooleshow.base.router.RouterPath;
+import com.cooleshow.base.utils.PermissionUtils;
+import com.cooleshow.base.utils.ToastUtil;
+import com.cooleshow.base.utils.UiUtils;
+import com.cooleshow.base.widgets.dialog.CommonConfirmDialog;
+import com.cooleshow.usercenter.helper.UserHelper;
+import com.dayayuemeng.classroom.api.ResultCallback;
+import com.dayayuemeng.classroom.bean.LoginResult;
+import com.dayayuemeng.classroom.constants.ARouterSealClass;
+import com.dayayuemeng.classroom.repository.UserRepository;
+import com.tbruyelle.rxpermissions3.RxPermissions;
+
+import androidx.fragment.app.FragmentActivity;
+import io.reactivex.rxjava3.disposables.Disposable;
+
+/**
+ * Author by pq, Date on 2023/8/18.
+ */
+public class OpenClassRoomHelper {
+    public static final String SNARE_DRUM = "小军鼓";
+    public static final String FLUTE = "长笛";
+
+    public static void start(FragmentActivity activity, String sealClassId, String subjectName) {
+        if (UiUtils.isFastClick()) {
+            return;
+        }
+        checkPermission(activity, sealClassId, subjectName);
+    }
+
+    private static void checkPermission(FragmentActivity activity, String sealClassId, String subjectName) {
+        Disposable subscribe = new RxPermissions(activity)
+                .request(Manifest.permission.MODIFY_AUDIO_SETTINGS,
+                        Manifest.permission.RECORD_AUDIO,
+                        Manifest.permission.CAMERA)
+                .subscribe(isAllowPermission -> {
+                    if (isAllowPermission) {
+                        prepareOpenCourseRoom(activity, sealClassId, subjectName);
+                    } else {
+                        showTipDialog(activity);
+                    }
+                });
+    }
+
+    private static void prepareOpenCourseRoom(Activity activity, String sealClassId, String subjectName) {
+        UserRepository userRepository = new UserRepository(activity);
+        String userName = UserHelper.getUserName();
+        userRepository.login(sealClassId, false, userName, new ResultCallback<LoginResult>() {
+            @Override
+            public void onSuccess(LoginResult loginResult) {
+                String path = ARouterSealClass.ACTIVITY_CLASS_ROOM;
+                if(!BaseApplication.Companion.isTeacherClient()){
+                    path = ARouterSealClass.ACTIVITY_CLASS_ROOM_STU;
+                }
+                ARouter.getInstance().build(path)
+                        .withSerializable("extra_login_result", loginResult)
+                        .navigation();
+            }
+
+            @Override
+            public void onFail(int errorCode, String errorStr) {
+                if (activity != null) {
+                    activity.runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (!TextUtils.isEmpty(errorStr)) {
+                                ToastUtil.getInstance().show(activity, errorStr);
+                            } else {
+                                ToastUtil.getInstance().show(activity, "加入课堂失败,请重试;错误码:" + errorCode);
+                            }
+                        }
+                    });
+                }
+            }
+        });
+    }
+
+    private static void showTipDialog(Activity activity) {
+        CommonConfirmDialog confirmDialog = new CommonConfirmDialog(activity);
+        confirmDialog.show();
+        confirmDialog.setContent("加入课堂需要开启音视频相关权限");
+        confirmDialog.setConfirmText("去设置");
+        confirmDialog.setOnConfirmClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                PermissionUtils.toSelfSetting(activity);
+            }
+        });
+    }
+}

+ 103 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TCClassRoomTextMessage.java

@@ -0,0 +1,103 @@
+package com.dayayuemeng.classroom.im.message;
+
+import android.os.Parcel;
+import android.text.TextUtils;
+
+import com.daya.tclive.MessageTag;
+import com.daya.tclive.constants.MessageConstants;
+import com.daya.tclive.message.BaseTIMMessageContent;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Author by pq, Date on 2023/2/28.
+ */
+@MessageTag(value = "RC:Classroom:Text")
+public class TCClassRoomTextMessage extends BaseTIMMessageContent {
+    private String text;
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    public TCClassRoomTextMessage(byte[] data) {
+        String jsonStr = null;
+        try {
+            jsonStr = new String(data, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        try {
+            JSONObject jsonObject = new JSONObject(jsonStr);
+            if (jsonObject.has("sendUserInfo")) {
+                this.setBaseInfo(jsonObject.getJSONObject("sendUserInfo"));
+            }
+
+            if (jsonObject.has("text")) {
+                text = jsonObject.optString("text");
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public byte[] encode() {
+        JSONObject jsonObj = new JSONObject();
+        try {
+            // 消息携带用户信息时, 自定义消息需添加下面代码
+            addBaseInfo(jsonObj);
+            if (!TextUtils.isEmpty(text)) {
+                jsonObj.putOpt("text", text);
+            }
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+
+        try {
+            return jsonObj.toString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(this.text);
+        writeBase(dest, flags);
+    }
+
+
+    public TCClassRoomTextMessage() {
+    }
+
+    protected TCClassRoomTextMessage(Parcel in) {
+        this.text = in.readString();
+        readBase(in);
+    }
+
+    public static final Creator<TCClassRoomTextMessage> CREATOR = new Creator<TCClassRoomTextMessage>() {
+        @Override
+        public TCClassRoomTextMessage createFromParcel(Parcel source) {
+            return new TCClassRoomTextMessage(source);
+        }
+
+        @Override
+        public TCClassRoomTextMessage[] newArray(int size) {
+            return new TCClassRoomTextMessage[size];
+        }
+    };
+}

+ 149 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTControlDeviceStateMessage.java

@@ -0,0 +1,149 @@
+package com.dayayuemeng.classroom.im.message;
+
+import android.os.Parcel;
+
+import com.cooleshow.base.utils.LOG;
+import com.daya.tclive.MessageTag;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.dayayuemeng.classroom.constants.DeviceType;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * 设备状态控制消息
+ */
+@MessageTag(value = "SC:CDNMsg")
+public class TTControlDeviceStateMessage extends BaseTIMMessageContent {
+    private final static String TAG = TTControlDeviceStateMessage.class.getSimpleName();
+
+    private Boolean enable; // 开启状态
+    private int type; // 0 麦克风 1 摄像头 2 音乐模式 3 学生举手 4 曲目播放 5 原音 6 伴奏
+    private String targetId; // 目标学生id
+    private String targetName; // 目标学生name
+    private String songId; // songId
+    private int songVolume; // soundVolume
+
+
+    public TTControlDeviceStateMessage(byte[] data) {
+        String jsonStr = null;
+        try {
+            jsonStr = new String(data, "UTF-8");
+            LOG.e(jsonStr);
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            JSONObject jsonObject = new JSONObject(jsonStr);
+            if (jsonObject.has("sendUserInfo")) {
+                this.setBaseInfo(jsonObject.getJSONObject("sendUserInfo"));
+            }
+            enable = jsonObject.optBoolean("enable");
+            type = jsonObject.optInt("type");
+            targetId = jsonObject.optString("targetId");
+            targetName = jsonObject.optString("targetName");
+            songId = jsonObject.optString("songId");
+            songVolume = jsonObject.optInt("songVolume");
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+    }
+
+    public TTControlDeviceStateMessage(Parcel parcel) {
+        enable = parcel.readInt() != 0;
+        type = parcel.readInt();
+        targetId = parcel.readString();
+        targetName = parcel.readString();
+        songId = parcel.readString();
+        songVolume = parcel.readInt();
+        readBase(parcel);
+    }
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public DeviceType getType() {
+        return DeviceType.getDeviceType(type);
+    }
+
+    public String getTargetId() {
+        return targetId;
+    }
+
+    public String getTargetName() {
+        return targetName;
+    }
+
+    public int getSongId() {
+        return Integer.parseInt(songId);
+    }
+
+    public int getSoundVolume() {
+        return songVolume;
+    }
+
+    @Override
+    public byte[] encode() {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            addBaseInfo(jsonObject);
+            jsonObject.put("enable",enable);
+            jsonObject.put("type",type);
+            jsonObject.put("targetId",targetId);
+            jsonObject.put("targetName",targetName);
+            jsonObject.put("songId",songId);
+            jsonObject.put("songVolume",songVolume);
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            return jsonObject.toString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        return new byte[0];
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(enable ? 1 : 0);
+        dest.writeInt(type);
+        dest.writeString(targetId);
+        dest.writeString(targetName);
+        dest.writeString(songId);
+        dest.writeInt(songVolume);
+        writeBase(dest,flags);
+
+    }
+
+    public static final Creator<TTControlDeviceStateMessage> CREATOR = new Creator<TTControlDeviceStateMessage>() {
+        @Override
+        public TTControlDeviceStateMessage createFromParcel(Parcel source) {
+            return new TTControlDeviceStateMessage(source);
+        }
+
+        @Override
+        public TTControlDeviceStateMessage[] newArray(int size) {
+            return new TTControlDeviceStateMessage[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return "TTControlDeviceStateMessage{" +
+                "enable=" + enable +
+                ", type=" + type +
+                ", targetId='" + targetId + '\'' +
+                ", targetName='" + targetName + '\'' +
+                '}';
+    }
+}

+ 112 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTDeviceStateChangedMessage.java

@@ -0,0 +1,112 @@
+package com.dayayuemeng.classroom.im.message;
+
+import android.os.Parcel;
+
+import com.cooleshow.base.utils.LOG;
+import com.daya.tclive.MessageTag;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.dayayuemeng.classroom.constants.DeviceType;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * 设备状态同步消息
+ */
+@MessageTag(value = "SC:DRMsg")
+public class TTDeviceStateChangedMessage extends BaseTIMMessageContent {
+    private final static String TAG = TTDeviceStateChangedMessage.class.getSimpleName();
+
+    private Boolean enable; // 开启状态
+    private int type; // 设备类型:0.麦克风;1.摄像头 5 原生音量  6 伴奏音量
+
+
+    public TTDeviceStateChangedMessage(byte[] data) {
+        LOG.i("VOLEUM_TAG","musicScoreAccompanimentId");
+        String jsonStr = null;
+        try {
+            jsonStr = new String(data, "UTF-8");
+            LOG.e(jsonStr);
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            JSONObject jsonObject = new JSONObject(jsonStr);
+            if (jsonObject.has("sendUserInfo")) {
+                this.setBaseInfo(jsonObject.getJSONObject("sendUserInfo"));
+            }
+            enable = jsonObject.optBoolean("enable");
+            type = jsonObject.optInt("type");
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+    }
+
+    public TTDeviceStateChangedMessage(Parcel parcel) {
+        enable = parcel.readInt() != 0;
+        type = parcel.readInt();
+        readBase(parcel);
+    }
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public DeviceType getType() {
+        return DeviceType.getDeviceType(type);
+    }
+
+    @Override
+    public byte[] encode() {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            addBaseInfo(jsonObject);
+            jsonObject.put("enable",enable);
+            jsonObject.put("type",type);
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            return jsonObject.toString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        return new byte[0];
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(enable ? 1 : 0);
+        dest.writeInt(type);
+        writeBase(dest,flags);
+
+    }
+
+    public static final Creator<TTDeviceStateChangedMessage> CREATOR = new Creator<TTDeviceStateChangedMessage>() {
+        @Override
+        public TTDeviceStateChangedMessage createFromParcel(Parcel source) {
+            return new TTDeviceStateChangedMessage(source);
+        }
+
+        @Override
+        public TTDeviceStateChangedMessage[] newArray(int size) {
+            return new TTDeviceStateChangedMessage[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return "TTDeviceStateChangedMessage{" +
+                "enable=" + enable +
+                ", type=" + type +
+                '}';
+    }
+}

+ 96 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTDisplayMessage.java

@@ -0,0 +1,96 @@
+package com.dayayuemeng.classroom.im.message;
+
+import android.os.Parcel;
+
+import com.cooleshow.base.utils.LOG;
+import com.daya.tclive.MessageTag;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.dayayuemeng.classroom.model.ScreenDisplay;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * 切换显示消息
+ */
+@MessageTag(value = "SC:DisplayMsg")
+public class TTDisplayMessage extends BaseTIMMessageContent {
+    private final static String TAG = TTDisplayMessage.class.getSimpleName();
+    private String display;
+
+    public TTDisplayMessage(byte[] data) {
+        String jsonStr = null;
+        try {
+            jsonStr = new String(data, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            JSONObject jsonObject = new JSONObject(jsonStr);
+            if (jsonObject.has("sendUserInfo")) {
+                this.setBaseInfo(jsonObject.getJSONObject("sendUserInfo"));
+            }
+            display = jsonObject.optString("display");
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+    }
+
+    public TTDisplayMessage(Parcel parcel) {
+        display = parcel.readString();
+        readBase(parcel);
+    }
+
+    public ScreenDisplay getDisplay() {
+        return ScreenDisplay.createScreenDisplay(display);
+    }
+
+    @Override
+    public byte[] encode() {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            addBaseInfo(jsonObject);
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            return jsonObject.toString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        return new byte[0];
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        writeBase(dest,flags);
+        dest.writeString(display);
+    }
+
+    public static final Creator<TTDisplayMessage> CREATOR = new Creator<TTDisplayMessage>() {
+        @Override
+        public TTDisplayMessage createFromParcel(Parcel source) {
+            return new TTDisplayMessage(source);
+        }
+
+        @Override
+        public TTDisplayMessage[] newArray(int size) {
+            return new TTDisplayMessage[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return "TTDisplayMessage{" +
+                "display='" + display + '\'' +
+                '}';
+    }
+}

+ 176 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTMemberChangedMessage.java

@@ -0,0 +1,176 @@
+package com.dayayuemeng.classroom.im.message;
+
+import android.os.Parcel;
+
+import com.cooleshow.base.utils.LOG;
+import com.daya.tclive.MessageTag;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.dayayuemeng.classroom.constants.Role;
+import com.dayayuemeng.classroom.constants.TTMessageConstants;
+import com.dayayuemeng.classroom.model.ClassMemberChangedAction;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * 课堂内用户进出消息
+ */
+@MessageTag(value = TTMessageConstants.TAG_MEMBER_CHANGE)
+public class TTMemberChangedMessage extends BaseTIMMessageContent {
+    private final static String  TAG = TTMemberChangedMessage.class.getSimpleName();
+    private              int     action;     // 用户行为:1.加入;2.离开;3.踢出
+    private              int     role;       // 用户角色
+    private              long    timestamp;
+    private              boolean microphone;
+    private              boolean handUpOn;
+    private              boolean camera;
+
+    public TTMemberChangedMessage(byte[] data) {
+        String jsonStr = null;
+        try {
+            jsonStr = new String(data, "UTF-8");
+            LOG.e(jsonStr);
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            JSONObject jsonObject = new JSONObject(jsonStr);
+            if (jsonObject.has("sendUserInfo")) {
+                this.setBaseInfo(jsonObject.getJSONObject("sendUserInfo"));
+            }
+            action = jsonObject.optInt("action");
+            role = jsonObject.optInt("role");
+            timestamp = jsonObject.optLong("timestamp");
+            microphone = jsonObject.optBoolean("microphone");
+            handUpOn = jsonObject.optBoolean("handUpOn");
+            camera = jsonObject.optBoolean("camera");
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+    }
+
+    public TTMemberChangedMessage(Parcel in) {
+        action = in.readInt();
+        role = in.readInt();
+        timestamp = in.readLong();
+        microphone = in.readByte() == 1;
+        handUpOn = in.readByte() == 1;
+        camera = in.readByte() == 1;
+        readBase(in);
+    }
+
+    public ClassMemberChangedAction getAction() {
+        return ClassMemberChangedAction.getAction(action);
+    }
+
+
+    public boolean isMicrophone() {
+        return microphone;
+    }
+
+    public void setMicrophone(boolean microphone) {
+        this.microphone = microphone;
+    }
+
+    public boolean isHandUpOn() {
+        return handUpOn;
+    }
+
+    public void setHandUpOn(boolean handUpOn) {
+        this.handUpOn = handUpOn;
+    }
+
+    public boolean isCamera() {
+        return camera;
+    }
+
+    public void setCamera(boolean camera) {
+        this.camera = camera;
+    }
+
+    public String getUserId() {
+        if (getSendUserInfo() != null) {
+            return getSendUserInfo().getSendUserId();
+        }
+        return "";
+    }
+
+    public String getUserName() {
+        if (getSendUserInfo() != null) {
+            return getSendUserInfo().getSendUserName();
+        }
+        return "";
+    }
+
+    public Role getRole() {
+        return Role.createRole(role);
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+
+    @Override
+    public byte[] encode() {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            addBaseInfo(jsonObject);
+            jsonObject.put("action", action);
+            jsonObject.put("role", role);
+            jsonObject.put("timestamp", timestamp);
+            jsonObject.put("microphone", microphone);
+            jsonObject.put("handUpOn", handUpOn);
+            jsonObject.put("camera", camera);
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+
+        try {
+            return jsonObject.toString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        return new byte[0];
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(action);
+        dest.writeInt(role);
+        dest.writeLong(timestamp);
+        dest.writeByte((byte) (microphone ? 1 : 0));
+        dest.writeByte((byte) (handUpOn ? 1 : 0));
+        dest.writeByte((byte) (camera ? 1 : 0));
+        writeBase(dest, flags);
+    }
+
+    public static final Creator<TTMemberChangedMessage> CREATOR = new Creator<TTMemberChangedMessage>() {
+        @Override
+        public TTMemberChangedMessage createFromParcel(Parcel source) {
+            return new TTMemberChangedMessage(source);
+        }
+
+        @Override
+        public TTMemberChangedMessage[] newArray(int size) {
+            return new TTMemberChangedMessage[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return "TTMemberChangedMessage{" +
+                "action=" + action +
+                ", role=" + role +
+                ", timestamp=" + timestamp +
+                ", handUpOn=" + handUpOn +
+                '}';
+    }
+}

+ 146 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTMusicSyncMessage.java

@@ -0,0 +1,146 @@
+package com.dayayuemeng.classroom.im.message;
+
+import android.os.Parcel;
+
+import com.cooleshow.base.utils.LOG;
+import com.daya.tclive.MessageTag;
+import com.daya.tclive.message.BaseTIMMessageContent;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * 设备状态控制消息
+ */
+@MessageTag(value = "DY:musicScoreMessage")
+public class TTMusicSyncMessage extends BaseTIMMessageContent {
+    private final static String TAG = TTMusicSyncMessage.class.getSimpleName();
+
+    private String url; // 曲谱url
+    private String mp3Url; // 曲谱url
+    private int songId; // songId
+    private int speed; // speed
+
+
+    public TTMusicSyncMessage(byte[] data) {
+        String jsonStr = null;
+        try {
+            jsonStr = new String(data, "UTF-8");
+            LOG.e(jsonStr);
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            JSONObject jsonObject = new JSONObject(jsonStr);
+            if (jsonObject.has("sendUserInfo")) {
+                this.setBaseInfo(jsonObject.getJSONObject("sendUserInfo"));
+            }
+            url = jsonObject.optString("url");
+            mp3Url = jsonObject.optString("mp3Url");
+            songId = jsonObject.optInt("songId");
+            speed = jsonObject.optInt("speed");
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getMp3Url() {
+        return mp3Url;
+    }
+
+    public void setMp3Url(String mp3Url) {
+        this.mp3Url = mp3Url;
+    }
+
+    public int getSongId() {
+        return songId;
+    }
+
+    public void setSongId(int songId) {
+        this.songId = songId;
+    }
+
+    public int getSpeed() {
+        return speed;
+    }
+
+    public void setSpeed(int speed) {
+        this.speed = speed;
+    }
+
+    public TTMusicSyncMessage(Parcel parcel) {
+        url = parcel.readString();
+        mp3Url = parcel.readString();
+        songId = parcel.readInt();
+        speed = parcel.readInt();
+        readBase(parcel);
+    }
+
+    @Override
+    public byte[] encode() {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            addBaseInfo(jsonObject);
+            jsonObject.put("url",url);
+            jsonObject.put("mp3Url",mp3Url);
+            jsonObject.put("songId",songId);
+            jsonObject.put("speed",speed);
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            return jsonObject.toString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        return new byte[0];
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(url);
+        dest.writeString(mp3Url);
+        dest.writeInt(songId);
+        dest.writeInt(speed);
+        writeBase(dest,flags);
+
+    }
+
+    public static final Creator<TTMusicSyncMessage> CREATOR = new Creator<TTMusicSyncMessage>() {
+        @Override
+        public TTMusicSyncMessage createFromParcel(Parcel source) {
+            return new TTMusicSyncMessage(source);
+        }
+
+        @Override
+        public TTMusicSyncMessage[] newArray(int size) {
+            return new TTMusicSyncMessage[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return "TTMusicSyncMessage{" +
+                "url='" + url + '\'' +
+                ", mp3Url='" + mp3Url + '\'' +
+                ", songId='" + songId + '\'' +
+                ", speed=" + speed +
+                '}';
+    }
+}

+ 151 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/im/message/TTPlayBeatMessage.java

@@ -0,0 +1,151 @@
+package com.dayayuemeng.classroom.im.message;
+
+import android.os.Parcel;
+
+import com.cooleshow.base.utils.LOG;
+import com.daya.tclive.MessageTag;
+import com.daya.tclive.message.BaseTIMMessageContent;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * 播放节拍器
+ */
+@MessageTag(value = "DY:PlayMidiMessage")
+public class TTPlayBeatMessage extends BaseTIMMessageContent {
+    private final static String TAG = TTPlayBeatMessage.class.getSimpleName();
+    private Boolean enable;
+    private int rate;
+    private int customType;
+    private String userId;
+    private int playVolume;
+
+    public TTPlayBeatMessage(byte[] data) {
+        String jsonStr = null;
+        try {
+            jsonStr = new String(data, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            JSONObject jsonObject = new JSONObject(jsonStr);
+            if (jsonObject.has("sendUserInfo")) {
+                this.setBaseInfo(jsonObject.getJSONObject("sendUserInfo"));
+            }
+            enable = jsonObject.optBoolean("enable");
+            rate = jsonObject.optInt("rate");
+            customType = jsonObject.optInt("customType");
+            userId = jsonObject.optString("userId");
+            playVolume = jsonObject.optInt("playVolume");
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+    }
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
+    }
+
+    public int getRate() {
+        return rate;
+    }
+
+    public void setRate(int rate) {
+        this.rate = rate;
+    }
+
+    public int getCustomType() {
+        return customType;
+    }
+
+    public void setCustomType(int customType) {
+        this.customType = customType;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public int getPlayVolume() {
+        return playVolume;
+    }
+
+    public void setPlayVolume(int playVolume) {
+        this.playVolume = playVolume;
+    }
+
+    public TTPlayBeatMessage(Parcel parcel) {
+        enable = parcel.readInt() != 0;
+        rate = parcel.readInt();
+        customType = parcel.readInt();
+        userId = parcel.readString();
+        playVolume = parcel.readInt();
+        readBase(parcel);
+    }
+
+    @Override
+    public byte[] encode() {
+        JSONObject jsonObject = new JSONObject();
+        try {
+            addBaseInfo(jsonObject);
+        } catch (JSONException e) {
+            LOG.e(TAG, e.toString());
+        }
+        try {
+            return jsonObject.toString().getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            LOG.e(TAG, e.toString());
+        }
+        return new byte[0];
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        writeBase(dest,flags);
+        dest.writeInt(enable ? 1 : 0);
+        dest.writeInt(rate);
+        dest.writeInt(customType);
+        dest.writeString(userId);
+        dest.writeInt(playVolume);
+    }
+
+    public static final Creator<TTPlayBeatMessage> CREATOR = new Creator<TTPlayBeatMessage>() {
+        @Override
+        public TTPlayBeatMessage createFromParcel(Parcel source) {
+            return new TTPlayBeatMessage(source);
+        }
+
+        @Override
+        public TTPlayBeatMessage[] newArray(int size) {
+            return new TTPlayBeatMessage[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return "TTPlayBeatMessage{" +
+                "enable=" + enable +
+                ", rate=" + rate +
+                ", customType=" + customType +
+                ", userId='" + userId + '\'' +
+                ", playVolume=" + playVolume +
+                '}';
+    }
+}

+ 21 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/listener/OnWhiteBoardListener.java

@@ -0,0 +1,21 @@
+package com.dayayuemeng.classroom.listener;
+
+
+import com.dayayuemeng.classroom.bean.WhiteBoard;
+
+import java.util.List;
+
+/**
+ * Author by pq, Date on 2022/8/23.
+ */
+public interface OnWhiteBoardListener {
+    /**
+     * 点击事件
+     */
+    void onClick();
+
+    /**
+     * 白板列表
+     */
+    void onWhiteBoardList(List<WhiteBoard> reverseList);
+}

+ 32 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/ClassMemberChangedAction.java

@@ -0,0 +1,32 @@
+package com.dayayuemeng.classroom.model;
+
+/**
+ * 描述用户进出课堂的行为
+ */
+public enum ClassMemberChangedAction {
+    JOIN(1),
+    LEAVE(2),
+    KICK(3),
+    UNKNOWN(-999);
+
+    private int value;
+
+    ClassMemberChangedAction(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+
+    public static ClassMemberChangedAction getAction(int value) {
+        ClassMemberChangedAction[] values = ClassMemberChangedAction.values();
+        for (ClassMemberChangedAction action : values) {
+            if (action.value == value) {
+                return action;
+            }
+        }
+
+        return UNKNOWN;
+    }
+}

+ 23 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/DeviceChange.java

@@ -0,0 +1,23 @@
+package com.dayayuemeng.classroom.model;
+
+import com.dayayuemeng.classroom.constants.DeviceType;
+
+public class DeviceChange {
+    public String userId;
+    public DeviceType deviceType;
+    public boolean isEnable;
+    public DeviceChange(String userId, DeviceType deviceType, boolean isEnable) {
+        this.userId = userId;
+        this.deviceType = deviceType;
+        this.isEnable = isEnable;
+    }
+
+    @Override
+    public String toString() {
+        return "DeviceChange{" +
+                "userId='" + userId + '\'' +
+                ", deviceType=" + deviceType +
+                ", isEnable=" + isEnable +
+                '}';
+    }
+}

+ 16 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/DeviceChangeToast.java

@@ -0,0 +1,16 @@
+package com.dayayuemeng.classroom.model;
+
+import com.dayayuemeng.classroom.constants.DeviceType;
+
+public class DeviceChangeToast {
+    public String senderUserId;
+    public String userId;
+    public DeviceType deviceType;
+    public boolean isEnable;
+    public DeviceChangeToast(String senderUserId, String userId, DeviceType deviceType, boolean isEnable) {
+        this.senderUserId = senderUserId;
+        this.userId = userId;
+        this.deviceType = deviceType;
+        this.isEnable = isEnable;
+    }
+}

+ 55 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/DeviceControlInvite.java

@@ -0,0 +1,55 @@
+package com.dayayuemeng.classroom.model;
+
+import com.dayayuemeng.classroom.constants.DeviceType;
+import com.dayayuemeng.classroom.constants.InviteAction;
+
+/**
+ * 邀请设备开启控制
+ */
+public class DeviceControlInvite {
+    private String ticket;  // 请求凭证 Id
+    private String opUserId; // 操作人 用户id
+    private String opUserName; // 操作人用户名称
+    private InviteAction action; // 操作行为
+    private DeviceType deviceType; // 操作设备
+
+    public String getOpUserId() {
+        return opUserId;
+    }
+
+    public void setOpUserId(String opUserId) {
+        this.opUserId = opUserId;
+    }
+
+    public String getOpUserName() {
+        return opUserName;
+    }
+
+    public void setOpUserName(String opUserName) {
+        this.opUserName = opUserName;
+    }
+
+    public InviteAction getAction() {
+        return action;
+    }
+
+    public void setAction(InviteAction action) {
+        this.action = action;
+    }
+
+    public String getTicket() {
+        return ticket;
+    }
+
+    public void setTicket(String ticket) {
+        this.ticket = ticket;
+    }
+
+    public DeviceType getDeviceType() {
+        return deviceType;
+    }
+
+    public void setDeviceType(DeviceType deviceType) {
+        this.deviceType = deviceType;
+    }
+}

+ 14 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/DeviceSoudValum.java

@@ -0,0 +1,14 @@
+package com.dayayuemeng.classroom.model;
+
+import com.dayayuemeng.classroom.constants.DeviceType;
+
+public class DeviceSoudValum {
+    public Integer soundValue;
+    public String musicScoreAccompanimentId;
+    public DeviceType deviceType;
+    public DeviceSoudValum(Integer soundValue, DeviceType deviceType, String musicScoreAccompanimentId) {
+        this.soundValue = soundValue;
+        this.deviceType = deviceType;
+        this.musicScoreAccompanimentId = musicScoreAccompanimentId;
+    }
+}

+ 52 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/DownLoadSong.java

@@ -0,0 +1,52 @@
+package com.dayayuemeng.classroom.model;
+
+/**
+ * 下载伴奏
+ */
+public class DownLoadSong {
+    private String examSongName;
+    private String musicScoreAccompanimentId;
+    private String url;
+    private String mp3Url;
+
+    public DownLoadSong() {
+    }
+
+    public DownLoadSong(String musicScoreAccompanimentId, String url, String mp3Url) {
+        this.musicScoreAccompanimentId = musicScoreAccompanimentId;
+        this.url = url;
+        this.mp3Url = mp3Url;
+    }
+
+    public String getMp3Url() {
+        return mp3Url;
+    }
+
+    public void setMp3Url(String mp3Url) {
+        this.mp3Url = mp3Url;
+    }
+
+    public String getExamSongName() {
+        return examSongName;
+    }
+
+    public void setExamSongName(String examSongName) {
+        this.examSongName = examSongName;
+    }
+
+    public String getMusicScoreAccompanimentId() {
+        return musicScoreAccompanimentId;
+    }
+
+    public void setMusicScoreAccompanimentId(String musicScoreAccompanimentId) {
+        this.musicScoreAccompanimentId = musicScoreAccompanimentId;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+}

+ 143 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/DownLoadSongStatus.java

@@ -0,0 +1,143 @@
+package com.dayayuemeng.classroom.model;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * 下载伴奏
+ */
+public class DownLoadSongStatus implements Parcelable {
+
+    private String musicScoreAccompanimentId;
+    private int downStatus;
+    private int playStatus;
+    private int accompanimentPlayStatus;
+    private int speed;
+    private String url;
+    private String mp3Url;
+    private String musicScoreName;
+
+    public DownLoadSongStatus() {
+    }
+
+    public DownLoadSongStatus(String musicScoreAccompanimentId, int downStatus, int playStatus, int accompanimentPlayStatus, int speed, String url, String mp3Url, String musicScoreName) {
+        this.musicScoreAccompanimentId = musicScoreAccompanimentId;
+        this.downStatus = downStatus;
+        this.playStatus = playStatus;
+        this.accompanimentPlayStatus = accompanimentPlayStatus;
+        this.speed = speed;
+        this.url = url;
+        this.mp3Url = mp3Url;
+        this.musicScoreName = musicScoreName;
+    }
+
+    protected DownLoadSongStatus(Parcel in) {
+        musicScoreAccompanimentId = in.readString();
+        downStatus = in.readInt();
+        playStatus = in.readInt();
+        accompanimentPlayStatus = in.readInt();
+        speed = in.readInt();
+        url = in.readString();
+        mp3Url = in.readString();
+        musicScoreName = in.readString();
+    }
+
+    public int getDownStatus() {
+        return downStatus;
+    }
+
+    public void setDownStatus(int downStatus) {
+        this.downStatus = downStatus;
+    }
+
+    public int getPlayStatus() {
+        return playStatus;
+    }
+
+    public void setPlayStatus(int playStatus) {
+        this.playStatus = playStatus;
+    }
+
+    public int getAccompanimentPlayStatus() {
+        return accompanimentPlayStatus;
+    }
+
+    public void setAccompanimentPlayStatus(int accompanimentPlayStatus) {
+        this.accompanimentPlayStatus = accompanimentPlayStatus;
+    }
+
+    public int getSpeed() {
+        return speed;
+    }
+
+    public void setSpeed(int speed) {
+        this.speed = speed;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getMp3Url() {
+        return mp3Url;
+    }
+
+    public void setMp3Url(String mp3Url) {
+        this.mp3Url = mp3Url;
+    }
+
+    public String getMusicScoreName() {
+        return musicScoreName;
+    }
+
+    public void setMusicScoreName(String musicScoreName) {
+        this.musicScoreName = musicScoreName;
+    }
+
+
+    public static final Creator<DownLoadSongStatus> CREATOR = new Creator<DownLoadSongStatus>() {
+        @Override
+        public DownLoadSongStatus createFromParcel(Parcel in) {
+            return new DownLoadSongStatus(in);
+        }
+
+        @Override
+        public DownLoadSongStatus[] newArray(int size) {
+            return new DownLoadSongStatus[size];
+        }
+    };
+
+
+    public String getMusicScoreAccompanimentId() {
+        return musicScoreAccompanimentId;
+    }
+
+    public void setMusicScoreAccompanimentId(String musicScoreAccompanimentId) {
+        this.musicScoreAccompanimentId = musicScoreAccompanimentId;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+
+            dest.writeString(musicScoreAccompanimentId);
+            dest.writeInt(downStatus);
+            dest.writeInt(playStatus);
+            dest.writeInt(accompanimentPlayStatus);
+            dest.writeInt(speed);
+            dest.writeString(url);
+            dest.writeString(mp3Url);
+            dest.writeString(musicScoreName);
+
+        }
+
+
+}

+ 40 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/InsertImageBean.java

@@ -0,0 +1,40 @@
+package com.dayayuemeng.classroom.model;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2019/11/12 13:55
+ */
+public class InsertImageBean {
+
+    private String fileUrl;
+
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+
+    public double getImageWidt() {
+        return imageWidt;
+    }
+
+    public void setImageWidt(double imageWidt) {
+        this.imageWidt = imageWidt;
+    }
+
+    public double getImageHidtht() {
+        return imageHidtht;
+    }
+
+    public void setImageHidtht(double imageHidtht) {
+        this.imageHidtht = imageHidtht;
+    }
+
+    private double imageWidt;
+    private double imageHidtht;
+}

+ 44 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/MetronomeInfo.java

@@ -0,0 +1,44 @@
+package com.dayayuemeng.classroom.model;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2020/6/22 11:45
+ */
+public class MetronomeInfo {
+    private int rate;
+    private int customType;
+    private int volume;
+
+    public MetronomeInfo(int rate, int customType, int volume) {
+        this.rate = rate;
+        this.customType = customType;
+        this.volume = volume;
+    }
+
+    public int getCustomType() {
+        return customType;
+    }
+
+    public void setCustomType(int customType) {
+        this.customType = customType;
+    }
+
+    public int getRate() {
+        return rate;
+    }
+
+    public void setRate(int rate) {
+        this.rate = rate;
+    }
+
+    public int getVolume() {
+        return volume;
+    }
+
+    public void setVolume(int volume) {
+        this.volume = volume;
+    }
+}

+ 29 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/PassedTime.java

@@ -0,0 +1,29 @@
+package com.dayayuemeng.classroom.model;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2020/5/25 16:13
+ */
+public class PassedTime {
+    private String passedTime;
+    private boolean isTwinkle;
+
+    public boolean isTwinkle() {
+        return isTwinkle;
+    }
+
+    public void setTwinkle(boolean twinkle) {
+        isTwinkle = twinkle;
+    }
+
+    public String getPassedTime() {
+        return passedTime;
+    }
+
+    public void setPassedTime(String passedTime) {
+        this.passedTime = passedTime;
+    }
+}

+ 69 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/PlayMidi.java

@@ -0,0 +1,69 @@
+package com.dayayuemeng.classroom.model;
+
+/**
+ * Description:
+ * Copyright  : Copyright (c) 2019
+ * Company    : 大雅乐盟
+ * Author     : r
+ * Date       : 2020/5/14 15:50
+ */
+public class PlayMidi {
+
+    private String  userId;
+    private boolean enable;
+    private int     rate;
+    private int     customType;
+    private int     playVolume;
+
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public boolean isEnable() {
+        return enable;
+    }
+
+    public void setEnable(boolean enable) {
+        this.enable = enable;
+    }
+
+    public int getRate() {
+        return rate;
+    }
+
+    public void setRate(int rate) {
+        this.rate = rate;
+    }
+
+    public int getCustomType() {
+        return customType;
+    }
+
+    public void setCustomType(int customType) {
+        this.customType = customType;
+    }
+
+    public int getPlayVolume() {
+        return playVolume;
+    }
+
+    public void setPlayVolume(int playVolume) {
+        this.playVolume = playVolume;
+    }
+
+    public PlayMidi(boolean enable, int rate, int customType, int playVolume) {
+        this.enable = enable;
+        this.rate = rate;
+        this.customType = customType;
+        this.playVolume = playVolume;
+    }
+
+    public PlayMidi() {
+
+    }
+}

+ 131 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/ScreenDisplay.java

@@ -0,0 +1,131 @@
+package com.dayayuemeng.classroom.model;
+
+import android.text.TextUtils;
+
+import com.cooleshow.base.utils.LOG;
+import com.dayayuemeng.classroom.bean.ClassMember;
+
+
+/**
+ * 屏幕显示
+ */
+public class ScreenDisplay {
+    private final static String DISPLAY_PREFIX  = "display://";
+    private final static String DISPLAY_TYPE    = "type";
+    private final static String DISPLAY_URI     = "uri";
+    private final static String DISPLAY_USER_ID = "userId";
+
+    private String      userId;
+    private String      whiteBoardUri;
+    private Display     type;
+    private ClassMember classMember;
+
+    public static ScreenDisplay createScreenDisplay(String display) {
+        ScreenDisplay screenDisplay = new ScreenDisplay();
+        if (TextUtils.isEmpty(display) || !display.startsWith(DISPLAY_PREFIX)) {
+            screenDisplay.setType(Display.NONE);
+            return screenDisplay;
+        }
+        String params = display.substring(DISPLAY_PREFIX.length());
+        LOG.i("白板问题==createScreenDisplay  = " + params);
+        try {
+            String[] paramArray = params.split("\\?");
+            for (String param : paramArray) {
+                String[] keyAndValue = param.split("=");
+
+                // 当没有 key 和 value 两个值时不进行处理
+                if (keyAndValue.length < 2) {
+                    continue;
+                }
+
+                String key = keyAndValue[0];
+                String value = keyAndValue[1];
+
+                if (DISPLAY_TYPE.equals(key)) { // 显示类型
+                    screenDisplay.setType(Display.getDisplay(Integer.valueOf(value)));
+                } else if (DISPLAY_URI.equals(key)) {   // 白板地址
+                    screenDisplay.setWhiteBoardUri(value);
+                } else if (DISPLAY_USER_ID.equals(key)) {   // 若显示为用户类型时,用户 id
+                    screenDisplay.setUserId(value);
+                } else if (screenDisplay.getWhiteBoardUri() != null) { //若已存在白板信息,则后续参数为白板的参数
+                    String oriUrl = screenDisplay.getWhiteBoardUri();
+                    screenDisplay.setWhiteBoardUri(oriUrl + "?" + param);
+                }
+            }
+        } catch (Exception e) {
+        }
+
+        return screenDisplay;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getWhiteBoardUri() {
+        return whiteBoardUri;
+    }
+
+    public void setWhiteBoardUri(String whiteBoardUri) {
+        this.whiteBoardUri = whiteBoardUri;
+    }
+
+    public Display getType() {
+        return type;
+    }
+
+    public void setType(Display type) {
+        this.type = type;
+    }
+
+    public ClassMember getClassMember() {
+        return classMember;
+    }
+
+    public void setClassMember(ClassMember classMember) {
+        this.classMember = classMember;
+    }
+
+    public enum Display {
+        ASSISTANT(0),   //0 助教
+        LECTURER(1),    //1 讲师
+        WHITEBOARD(2),  //2 白板
+        SCREEN(3),      //3 屏幕
+        NONE(4),       //4清空 display
+        STUDENT(5);     //5学生
+        private int type;
+
+        Display(int type) {
+            this.type = type;
+        }
+
+        public static Display getDisplay(int type) {
+            Display[] values = Display.values();
+            for (Display display : values) {
+                if (display.type == type) {
+                    return display;
+                }
+            }
+
+            return NONE;
+        }
+
+        public int getType() {
+            return type;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ScreenDisplay{" +
+                "userId='" + userId + '\'' +
+                ", whiteBoardUri='" + whiteBoardUri + '\'' +
+                ", type=" + type +
+                ", classMember=" + classMember +
+                '}';
+    }
+}

+ 44 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/model/VideoClassMemberData.java

@@ -0,0 +1,44 @@
+package com.dayayuemeng.classroom.model;
+
+import com.dayayuemeng.classroom.bean.ClassMember;
+
+import java.util.List;
+
+public class VideoClassMemberData {
+    private List<ClassMember> member;
+    private boolean isNoUpdate = false;
+    private boolean isRefreshData = false;
+    private boolean isRefreshExamSongList = false;
+
+    public boolean isRefreshExamSongList() {
+        return isRefreshExamSongList;
+    }
+
+    public void setRefreshExamSongList(boolean refreshExamSongList) {
+        isRefreshExamSongList = refreshExamSongList;
+    }
+
+    public boolean isRefreshData() {
+        return isRefreshData;
+    }
+
+    public void setRefreshData(boolean refreshData) {
+        isRefreshData = refreshData;
+    }
+
+    public List<ClassMember> getMember() {
+        return member;
+    }
+
+    public void setMember(List<ClassMember> member) {
+        this.member = member;
+    }
+
+    public boolean isNoUpdate() {
+        return isNoUpdate;
+    }
+
+    public void setNoUpdate(boolean noUpdate) {
+        isNoUpdate = noUpdate;
+    }
+}

+ 28 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/AssistantPermissionGroup.java

@@ -0,0 +1,28 @@
+package com.dayayuemeng.classroom.permission;
+
+import java.util.List;
+
+class AssistantPermissionGroup extends LecturerPermissionGroup {
+    @Override
+    public PermissionGroupLevel permissionGroupRole() {
+        return PermissionGroupLevel.GROUP_ASSISTANT;
+    }
+
+    @Override
+    protected List<ClassExecutedPermission> onInitExecutedPermissions() {
+        return null;
+    }
+
+    @Override
+    protected List<ClassPermission> onInitPermissions() {
+        List<ClassPermission> classPermissions = super.onInitPermissions();
+        classPermissions.add(ClassPermission.TRANSFER_ROLE);
+        classPermissions.add(ClassPermission.CONTROL_MEMBER_MIC);
+        classPermissions.add(ClassPermission.CONTROL_MEMBER_CAMERA);
+        classPermissions.add(ClassPermission.UPGRADE_MEMBER);
+        classPermissions.add(ClassPermission.DOWNGRADE_MEMBER);
+        classPermissions.add(ClassPermission.KICK_OFF_MEMBER);
+        classPermissions.remove(ClassPermission.LECTURE);
+        return classPermissions;
+    }
+}

+ 32 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/ClassExecutedPermission.java

@@ -0,0 +1,32 @@
+package com.dayayuemeng.classroom.permission;
+
+/**
+ * 所有可被操作权限。
+ * 当拥有此权限则代码允许自己被他人执行某种操作。
+ */
+public enum ClassExecutedPermission {
+    /**
+     * 可被升级
+     */
+    UPGRADE,
+    /**
+     * 可被降级
+     */
+    DOWNGRADE,
+    /**
+     * 可被控制摄像头
+     */
+    CONTROL_VIDEO,
+    /**
+     * 可被控制语音
+     */
+    CONTROL_MIC,
+    /**
+     * 可被踢
+     */
+    KICK_OFF,
+    /**
+     * 可接收转移身份
+     */
+    ACCEPT_TRANSFER_ROLE
+}

+ 86 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/ClassPermission.java

@@ -0,0 +1,86 @@
+package com.dayayuemeng.classroom.permission;
+
+/**
+ * 所有可操作权限。
+ * 当拥有对应的权限即可去进行操作权限所对应的处理操作。
+ */
+public enum ClassPermission {
+
+    //本地个人功能权限
+
+    /**
+     * 创建白板
+     */
+    CREATE_WHITE_BOARD,
+    /**
+     * 使用白板
+     */
+    USE_WHITE_BOARD,
+    /**
+     * 使用资源库
+     */
+    RESOURCE_LIBARAY,
+    /**
+     * 查看用户列表
+     */
+    LOOK_MEMBER_LIST,
+    /**
+     * 查看成员视频列表
+     */
+    LOOK_MEMBER_VIDEO_LIST,
+    /**
+     * IM 聊天
+     */
+    IM_CHAT,
+
+    /**
+     * 视频聊天
+     */
+    VIDEO_CHAT,
+    /**
+     * 语音聊天
+     */
+    AUDIO_CHAT,
+    /**
+     * 控制声音外放
+     */
+    CONTROL_SOUND,
+
+
+    /**
+     * 申请发言
+     */
+    APPLY_SPEECH,
+
+    /**
+     * 讲课权限
+     */
+    LECTURE,
+
+    /**
+     * 转移身份
+     */
+    TRANSFER_ROLE,
+    /**
+     * 控制成员的语音
+     */
+    CONTROL_MEMBER_MIC,
+    /**
+     * 控制成员的摄像头
+     */
+    CONTROL_MEMBER_CAMERA,
+
+    /**
+     * 升级成员等级
+     */
+    UPGRADE_MEMBER,
+    /**
+     * 降低成员等级
+     */
+    DOWNGRADE_MEMBER,
+    /**
+     * 踢成员
+     */
+    KICK_OFF_MEMBER;
+
+}

+ 27 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/LecturerPermissionGroup.java

@@ -0,0 +1,27 @@
+package com.dayayuemeng.classroom.permission;
+
+import java.util.List;
+
+public class LecturerPermissionGroup extends StudentPermissionGroup {
+    @Override
+    public PermissionGroupLevel permissionGroupRole() {
+        return PermissionGroupLevel.GROUP_LECTURER;
+    }
+
+    @Override
+    protected List<ClassExecutedPermission> onInitExecutedPermissions() {
+        List<ClassExecutedPermission> classExecutedPermissions = super.onInitExecutedPermissions();
+        classExecutedPermissions.remove(ClassExecutedPermission.UPGRADE);
+        return classExecutedPermissions;
+    }
+
+    @Override
+    protected List<ClassPermission> onInitPermissions() {
+        List<ClassPermission> classPermissions = super.onInitPermissions();
+        classPermissions.add(ClassPermission.LECTURE);
+        classPermissions.add(ClassPermission.CREATE_WHITE_BOARD);
+        classPermissions.add(ClassPermission.RESOURCE_LIBARAY);
+
+        return classPermissions;
+    }
+}

+ 33 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/ListenerPermissionGroup.java

@@ -0,0 +1,33 @@
+package com.dayayuemeng.classroom.permission;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class ListenerPermissionGroup extends RolePermissionGroup {
+
+    @Override
+    public PermissionGroupLevel permissionGroupRole() {
+        return PermissionGroupLevel.GROUP_LISTENER;
+    }
+
+    @Override
+    protected List<ClassPermission> onInitPermissions() {
+        List<ClassPermission> permissions = new ArrayList<>();
+        permissions.add(ClassPermission.LOOK_MEMBER_LIST);
+        permissions.add(ClassPermission.LOOK_MEMBER_VIDEO_LIST);
+        permissions.add(ClassPermission.IM_CHAT);
+        permissions.add(ClassPermission.CONTROL_SOUND);
+        permissions.add(ClassPermission.APPLY_SPEECH);
+        return permissions;
+    }
+
+    @Override
+    protected List<ClassExecutedPermission> onInitExecutedPermissions() {
+        List<ClassExecutedPermission> permissions = new ArrayList<>();
+        permissions.add(ClassExecutedPermission.UPGRADE);
+        permissions.add(ClassExecutedPermission.KICK_OFF);
+        return permissions;
+    }
+
+
+}

+ 27 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/PermissionGroup.java

@@ -0,0 +1,27 @@
+package com.dayayuemeng.classroom.permission;
+
+
+/**
+ * 权限集操作接口。可以通过此接口查询权限集的等级,可执行的权限是否存在 和 被执行的权限是否存在
+ */
+public interface PermissionGroup {
+    /**
+     * 权限集的角色
+     * @return 权限等级 {@link PermissionGroupLevel}
+     */
+    PermissionGroupLevel permissionGroupRole();
+
+    /**
+     * 是否存在可执行的权限
+     * @param permission 可执行权限, 具体可查看{@link ClassPermission}
+     * @return true 存在; false 不存在
+     */
+    boolean hasPermission(ClassPermission permission);
+
+    /**
+     * 是否存在可被执行的权限
+     * @param permission 被执行权限, 具体可查看{@link ClassExecutedPermission}
+     * @return true 存在; false 不存在
+     */
+    boolean hasExecutedPermission(ClassExecutedPermission permission);
+}

+ 29 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/PermissionGroupFactory.java

@@ -0,0 +1,29 @@
+package com.dayayuemeng.classroom.permission;
+
+
+/**
+ * 权限组工厂类。可更具不同的权限等级生产对应的权限对象。
+ */
+public class PermissionGroupFactory {
+    public static PermissionGroup getPermissionGroup(PermissionGroupLevel role) {
+        PermissionGroup permissionGroup =  null;
+        switch (role) {
+            case GROUP_LISTENER:
+                permissionGroup = new ListenerPermissionGroup();
+                break;
+            case GROUP_STUDENT:
+                permissionGroup = new StudentPermissionGroup();
+                break;
+            case GROUP_LECTURER:
+                permissionGroup = new LecturerPermissionGroup();
+                break;
+            case GROUP_ASSISTANT:
+                permissionGroup = new AssistantPermissionGroup();
+                break;
+            default:
+                permissionGroup = new ListenerPermissionGroup();
+                break;
+        }
+        return permissionGroup;
+    }
+}

+ 37 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/PermissionGroupLevel.java

@@ -0,0 +1,37 @@
+package com.dayayuemeng.classroom.permission;
+
+
+/**
+ * 权限组类型等级
+ */
+public enum PermissionGroupLevel {
+
+    /**
+     * 旁听者权限组
+     */
+    GROUP_LISTENER(0),
+    /**
+     * 学员权限组
+     */
+    GROUP_STUDENT(1),
+    /**
+     * 讲师权限组
+     */
+    GROUP_LECTURER(2),
+    /**
+     * 助教权限组
+     */
+    GROUP_ASSISTANT(3);
+
+
+    private int level;
+    PermissionGroupLevel(int level) {
+         this.level = level;
+    }
+
+    public int getLevel() {
+        return level;
+    }
+
+
+}

+ 36 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/RolePermissionGroup.java

@@ -0,0 +1,36 @@
+package com.dayayuemeng.classroom.permission;
+
+import java.util.List;
+
+abstract class RolePermissionGroup implements PermissionGroup{
+
+    List<ClassExecutedPermission> executedPermissionList;
+    List<ClassPermission> hasPermissionsList;
+
+    public RolePermissionGroup () {
+        hasPermissionsList = onInitPermissions();
+        executedPermissionList = onInitExecutedPermissions();
+    }
+
+
+    @Override
+    public boolean hasExecutedPermission(ClassExecutedPermission permission) {
+        if (executedPermissionList == null || executedPermissionList.size() <= 0) {
+            return false;
+        }
+        return executedPermissionList.contains(permission);
+    }
+
+
+    @Override
+    public boolean hasPermission(ClassPermission permission) {
+        if (hasPermissionsList == null || hasPermissionsList.size() <= 0) {
+            return false;
+        }
+        return hasPermissionsList.contains(permission);
+    }
+
+    protected abstract List<ClassPermission> onInitPermissions();
+
+    protected abstract List<ClassExecutedPermission> onInitExecutedPermissions();
+}

+ 32 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/permission/StudentPermissionGroup.java

@@ -0,0 +1,32 @@
+package com.dayayuemeng.classroom.permission;
+
+import java.util.List;
+
+class StudentPermissionGroup extends ListenerPermissionGroup{
+
+    @Override
+    public PermissionGroupLevel permissionGroupRole() {
+        return PermissionGroupLevel.GROUP_STUDENT;
+    }
+
+
+    @Override
+    protected List<ClassPermission> onInitPermissions() {
+        List<ClassPermission> classPermissions = super.onInitPermissions();
+        classPermissions.remove(ClassPermission.APPLY_SPEECH);
+        classPermissions.add(ClassPermission.VIDEO_CHAT);
+        classPermissions.add(ClassPermission.AUDIO_CHAT);
+        classPermissions.add(ClassPermission.USE_WHITE_BOARD);
+        return classPermissions;
+    }
+
+    @Override
+    protected List<ClassExecutedPermission> onInitExecutedPermissions() {
+        List<ClassExecutedPermission> classExecutedPermissions = super.onInitExecutedPermissions();
+        classExecutedPermissions.add(ClassExecutedPermission.DOWNGRADE);
+        classExecutedPermissions.add(ClassExecutedPermission.CONTROL_VIDEO);
+        classExecutedPermissions.add(ClassExecutedPermission.CONTROL_MIC);
+        classExecutedPermissions.add(ClassExecutedPermission.ACCEPT_TRANSFER_ROLE);
+        return classExecutedPermissions;
+    }
+}

+ 48 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/MainVideoFragmentPresenter.java

@@ -0,0 +1,48 @@
+package com.dayayuemeng.classroom.presenter;
+
+import com.cooleshow.base.presenter.BasePresenter;
+import com.daya.tclive.constants.TTLiveConfig;
+import com.daya.tclive.manager.TRTCSdkManager;
+import com.dayayuemeng.classroom.contract.MainVideoFragmentContractView;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+import com.tencent.trtc.TRTCCloudDef;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class MainVideoFragmentPresenter extends BasePresenter<MainVideoFragmentContractView.View> {
+    public void startLocalPreview(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startLocalPreview(txCloudVideoView);
+        TRTCSdkManager.getInstance().startLocalAudio();
+    }
+
+    public void stopLocalPreview(){
+//        TRTCSdkManager.getInstance().stopLocalPreview();
+    }
+
+    public void startRemoteView(String targetUserId, TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, txCloudVideoView);
+        setRemoteRenderParams(targetUserId);
+    }
+
+    public void setRemoteRenderParams(String speakerId) {
+        TRTCSdkManager.getInstance().setRemoteRenderParams(speakerId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG,TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL, TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_DISABLE);
+    }
+
+    public void stopRemoteView(String targetUserId) {
+        TRTCSdkManager.getInstance().stopRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
+    }
+
+    public void updateLocalView(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().updateLocalView(txCloudVideoView);
+    }
+
+    public void changeMicPhone(boolean microphoneOn) {
+        TRTCSdkManager.getInstance().setMicPhoneDisable(microphoneOn);
+    }
+
+    public void changeCameraEnable(boolean cameraDisable) {
+        TRTCSdkManager.getInstance().setCameraDisable(cameraDisable);
+    }
+
+}

+ 21 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/NewAccompanimentListPresenter.java

@@ -0,0 +1,21 @@
+package com.dayayuemeng.classroom.presenter;
+
+import com.cooleshow.base.presenter.BasePresenter;
+import com.daya.tclive.manager.TRTCSdkManager;
+
+/**
+ * Author by pq, Date on 2023/4/25.
+ */
+public class NewAccompanimentListPresenter extends BasePresenter {
+    public void startPlay(int id, String path) {
+        TRTCSdkManager.getInstance().playBgMusic(id, path);
+    }
+
+    public void stopPlay(int id) {
+        TRTCSdkManager.getInstance().stopBgMusic(id);
+    }
+
+    public void changePlayVolume(int volumeValue) {
+        TRTCSdkManager.getInstance().setAllMusicVolume(volumeValue);
+    }
+}

+ 112 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/NewConversationPresenter.java

@@ -0,0 +1,112 @@
+package com.dayayuemeng.classroom.presenter;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.cooleshow.base.presenter.BasePresenter;
+import com.daya.tclive.bean.TTMessage;
+import com.daya.tclive.manager.MessageManager;
+import com.daya.tclive.manager.TCIMSdkManager;
+import com.daya.tclive.message.TCTextMessage;
+import com.dayayuemeng.classroom.contract.NewConversationView;
+import com.dayayuemeng.classroom.im.message.TCClassRoomTextMessage;
+import com.tencent.imsdk.v2.V2TIMMessage;
+import com.tencent.imsdk.v2.V2TIMValueCallback;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.core.ObservableEmitter;
+import io.reactivex.rxjava3.core.ObservableOnSubscribe;
+import io.reactivex.rxjava3.core.Observer;
+import io.reactivex.rxjava3.disposables.Disposable;
+import io.reactivex.rxjava3.schedulers.Schedulers;
+
+
+/**
+ * Author by pq, Date on 2023/5/12.
+ */
+public class NewConversationPresenter extends BasePresenter<NewConversationView.View> {
+    private V2TIMMessage lastMsg;
+    public static final String textMsgObjectName = "RC:Classroom:Text";
+
+    public void sendTextMessage(String targetId, String message) {
+        if (!TextUtils.isEmpty(targetId)) {
+            TCClassRoomTextMessage tcTextMessage = new TCClassRoomTextMessage();
+            tcTextMessage.setText(message);
+            MessageManager.getInstance().sendMessage(targetId, true, tcTextMessage);
+        }
+    }
+
+    public void getHistoryMessage(String roomId) {
+//        new V2TIMValueCallback<List<V2TIMMessage>>() {
+//            @Override
+//            public void onError(int code, String desc) {
+//                Log.i("imsdk", "fail, " + code + ", " + desc);
+//            }
+//
+//
+//            @Override
+//            public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
+//                // 记录下次拉取的 lastMsg,用于下次拉取
+//                V2TIMMessage lastMsg = v2TIMMessages.get(v2TIMMessages.size() - 1);
+//                Log.i("imsdk", "success");
+//            }
+//        }
+        TCIMSdkManager.getInstance().getGroupHistoryMessage(roomId, lastMsg, new V2TIMValueCallback<List<V2TIMMessage>>() {
+            @Override
+            public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
+                Log.i("imsdk", "success:" + (v2TIMMessages != null ? v2TIMMessages.size() : "0"));
+                if (v2TIMMessages == null) {
+                    return;
+                }
+                // 记录下次拉取的 lastMsg,用于下次拉取
+                if (v2TIMMessages.size() > 0) {
+                    lastMsg = v2TIMMessages.get(v2TIMMessages.size() - 1);
+                }
+                convertMessage(v2TIMMessages);
+            }
+
+            @Override
+            public void onError(int i, String s) {
+                Log.i("imsdk", "errorCode:" + i + "-reson:" + s);
+            }
+        });
+    }
+
+    private void convertMessage(final List<V2TIMMessage> v2TIMMessages) {
+        Observable.create(new ObservableOnSubscribe<ArrayList<TTMessage>>() {
+            @Override
+            public void subscribe(ObservableEmitter<ArrayList<TTMessage>> emitter) throws Exception {
+                ArrayList<TTMessage> ttMessages = MessageManager.getInstance().convertMessage(v2TIMMessages, textMsgObjectName);
+                emitter.onNext(ttMessages);
+            }
+        }).subscribeOn(Schedulers.newThread())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new Observer<ArrayList<TTMessage>>() {
+                    @Override
+                    public void onSubscribe(Disposable d) {
+
+                    }
+
+                    @Override
+                    public void onNext(ArrayList<TTMessage> result) {
+                        if (getView() != null) {
+                            getView().getGroupHistoryMessageSuccess(result);
+                        }
+                    }
+
+                    @Override
+                    public void onError(Throwable e) {
+
+                    }
+
+                    @Override
+                    public void onComplete() {
+
+                    }
+                });
+    }
+}

+ 37 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/NewGongGeFragmentPresenter.java

@@ -0,0 +1,37 @@
+package com.dayayuemeng.classroom.presenter;
+
+import com.cooleshow.base.presenter.BasePresenter;
+import com.cooleshow.base.presenter.view.BaseView;
+import com.daya.tclive.manager.TRTCSdkManager;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+import com.tencent.trtc.TRTCCloudDef;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class NewGongGeFragmentPresenter extends BasePresenter<BaseView> {
+    public void startLocalPreview(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startLocalPreview(txCloudVideoView);
+        TRTCSdkManager.getInstance().startLocalAudio();
+    }
+
+    public void startRemoteView(String targetUserId, TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, txCloudVideoView);
+    }
+
+    public void stopRemoteView(String targetUserId) {
+        TRTCSdkManager.getInstance().stopRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
+    }
+
+    public void updateLocalView(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().updateLocalView(txCloudVideoView);
+    }
+
+    public void changeMicPhone(boolean microphoneOn) {
+        TRTCSdkManager.getInstance().setMicPhoneDisable(microphoneOn);
+    }
+
+    public void changeCameraEnable(boolean cameraDisable) {
+        TRTCSdkManager.getInstance().setCameraDisable(cameraDisable);
+    }
+}

+ 400 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/StudentNetClassRoomPresenter.java

@@ -0,0 +1,400 @@
+package com.dayayuemeng.classroom.presenter;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.cooleshow.base.presenter.BasePresenter;
+import com.cooleshow.base.utils.LOG;
+import com.daya.tclive.bean.TTMessage;
+import com.daya.tclive.callback.ResultCallback;
+import com.daya.tclive.constants.TTLiveConfig;
+import com.daya.tclive.manager.MessageManager;
+import com.daya.tclive.manager.TCIMSdkManager;
+import com.daya.tclive.manager.TRTCSdkManager;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.dayayuemeng.classroom.bean.ClassMember;
+import com.dayayuemeng.classroom.constants.ClassRoomConstants;
+import com.dayayuemeng.classroom.constants.Role;
+import com.dayayuemeng.classroom.contract.StudentNetClassRoomContract;
+import com.dayayuemeng.classroom.contract.TeacherNetClassRoomContract;
+import com.dayayuemeng.classroom.im.message.TCClassRoomTextMessage;
+import com.dayayuemeng.classroom.im.message.TTControlDeviceStateMessage;
+import com.dayayuemeng.classroom.im.message.TTDeviceStateChangedMessage;
+import com.dayayuemeng.classroom.im.message.TTDisplayMessage;
+import com.dayayuemeng.classroom.im.message.TTMemberChangedMessage;
+import com.dayayuemeng.classroom.im.message.TTMusicSyncMessage;
+import com.dayayuemeng.classroom.im.message.TTPlayBeatMessage;
+import com.dayayuemeng.classroom.model.PlayMidi;
+import com.tencent.imsdk.v2.V2TIMCallback;
+import com.tencent.imsdk.v2.V2TIMGroupListener;
+import com.tencent.imsdk.v2.V2TIMGroupMemberInfo;
+import com.tencent.imsdk.v2.V2TIMManager;
+import com.tencent.imsdk.v2.V2TIMValueCallback;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+import com.tencent.trtc.TRTCCloudDef;
+import com.tencent.trtc.TRTCCloudListener;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import io.reactivex.rxjava3.core.Observer;
+import io.reactivex.rxjava3.disposables.Disposable;
+
+import static com.tencent.imsdk.v2.V2TIMManager.V2TIM_STATUS_LOGINED;
+import static com.tencent.imsdk.v2.V2TIMManager.V2TIM_STATUS_LOGINING;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class StudentNetClassRoomPresenter extends BasePresenter<StudentNetClassRoomContract.View> implements StudentNetClassRoomContract.Presenter {
+    public static final String TAG = "TNCRPresenter";
+    private List<Disposable> disposablesManager = new ArrayList<>();//监听管理器
+    private String cRoomId = "";
+
+    private TRTCCloudListener mCloudListener = new TRTCCloudListener() {
+        @Override
+        public void onEnterRoom(long result) {
+            if (result > 0) {
+                Log.d(TAG, "Enter room succeed");
+                if (getView() != null) {
+                    getView().enterLiveRoomSuccess();
+                }
+            } else {
+                Log.d(TAG, "Enter room failed");
+                if (getView() != null) {
+                    getView().enterLiveRoomError();
+                }
+            }
+        }
+
+        @Override
+        public void onStopPublishing(int err, String errMsg) {
+            super.onStopPublishing(err, errMsg);
+            Log.i(TAG, "onStopPublishing:" + err + "--errMsg:" + errMsg);
+            if (getView() != null) {
+                getView().onStopPublishing();
+            }
+        }
+
+        @Override
+        public void onStartPublishing(int err, String errMsg) {
+            Log.i(TAG, "onStartPublishing:" + err + "--errMsg:" + errMsg);
+            if (getView() != null) {
+                getView().onPublishSuccess();
+            }
+        }
+
+        @Override
+        public void onRemoteUserEnterRoom(String userId) {
+        }
+
+        @Override
+        public void onRemoteUserLeaveRoom(String userId, int reason) {
+        }
+
+        @Override
+        public void onNetworkQuality(TRTCCloudDef.TRTCQuality localQuality, ArrayList<TRTCCloudDef.TRTCQuality> remoteQuality) {
+            if (getView() != null) {
+                getView().onNetworkQuality(localQuality, remoteQuality);
+            }
+        }
+
+        @Override
+        public void onUserVoiceVolume(ArrayList<TRTCCloudDef.TRTCVolumeInfo> userVolumes, int totalVolume) {
+            if (getView() != null) {
+                getView().onUserVoiceVolume(userVolumes, totalVolume);
+            }
+        }
+    };
+
+    private V2TIMGroupListener mGroupListener = new V2TIMGroupListener() {
+        @Override
+        public void onGroupAttributeChanged(String groupID, Map<String, String> groupAttributeMap) {
+            if (getView() != null) {
+                LOG.i("pq", "onGroupAttributeChanged");
+                getView().onGroupAttributeChanged(groupID, groupAttributeMap);
+            }
+        }
+    };
+
+    public void initPublishConfig(Context context, int imSdkAppId) {
+        //初始化直播SDK
+        TRTCSdkManager.getInstance().init(context, mCloudListener);
+        //开启音量大小提示,SDK 会在 TRTCCloudListener 中的 onUserVoiceVolume 回调中反馈本地或远端用户的音频音量评估信息,包括音量大小、人声检测、音频频谱等。
+        TRTCSdkManager.getInstance().enableAudioVolumeEvaluation();
+        //初始化IM
+        TCIMSdkManager.getInstance().init(context.getApplicationContext(), imSdkAppId);
+    }
+
+    public void initDefaultBitmap(Bitmap bitmap) {
+        TRTCSdkManager.getInstance().setVideoMuteImage(bitmap);
+    }
+
+    public void enterRoom(int sdkAppId, String userId, String roomId, String userSig) {
+        TRTCSdkManager.getInstance().enterRoom(sdkAppId, userId, roomId, userSig, TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_LANDSCAPE);
+    }
+
+
+    public void connectIM(String roomId, String userId, String userSig) {
+        int loginStatus = V2TIMManager.getInstance().getLoginStatus();
+        if (loginStatus != V2TIM_STATUS_LOGINED && loginStatus != V2TIM_STATUS_LOGINING) {
+            //既不是已登录和登录中状态,则登录
+            this.cRoomId = roomId;
+            getView().showLoading();
+            V2TIMManager.getInstance().login(userId, userSig, new V2TIMCallback() {
+                @Override
+                public void onSuccess() {
+                    Log.i("TTLiveRoomActivity", "login IM success");
+                    if (getView() != null) {
+                        getView().loginIMSuccess();
+                    }
+                    registerListener(roomId);
+                }
+
+                @Override
+                public void onError(int code, String desc) {
+                    // 如果返回以下错误码,表示使用 UserSig 已过期,请您使用新签发的 UserSig 进行再次登录。
+                    // 1. ERR_USER_SIG_EXPIRED(6206)
+                    // 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED(70001)
+                    // 注意:其他的错误码,请不要在这里调用登录接口,避免 IM SDK 登录进入死循环。
+                    Log.i("TTLiveRoomActivity", "connectIM failure, code:" + code + ", desc:" + desc);
+                    if (getView() != null) {
+                        getView().connectIMError(code, desc);
+                    }
+                }
+            });
+        }
+    }
+
+    private void registerListener(String roomId) {
+        setObMessageListener(roomId);
+        bindGroupListener();
+        MessageManager.getInstance().register();
+        MessageManager.getInstance().registerMessageType(TTMemberChangedMessage.class);
+        MessageManager.getInstance().registerMessageType(TTDisplayMessage.class);
+        MessageManager.getInstance().registerMessageType(TTDeviceStateChangedMessage.class);
+        MessageManager.getInstance().registerMessageType(TTControlDeviceStateMessage.class);
+        MessageManager.getInstance().registerMessageType(TTPlayBeatMessage.class);
+        MessageManager.getInstance().registerMessageType(TTMusicSyncMessage.class);
+        MessageManager.getInstance().registerMessageType(TCClassRoomTextMessage.class);
+    }
+
+    public void setObMessageListener(String roomId) {
+        MessageManager.getInstance()
+                .obMessageReceiveByRoomId(roomId)
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new Observer<TTMessage>() {
+                    @Override
+                    public void onSubscribe(Disposable d) {
+                    }
+
+                    @Override
+                    public void onNext(TTMessage ttMessage) {
+                        handleMessage(ttMessage);
+                    }
+
+                    @Override
+                    public void onError(Throwable e) {
+                        e.printStackTrace();
+                    }
+
+                    @Override
+                    public void onComplete() {
+
+                    }
+                });
+
+    }
+
+    private void handleMessage(TTMessage message) {
+        BaseTIMMessageContent content = message.getContent();
+        if (content instanceof TCClassRoomTextMessage) {
+            if (getView() != null) {
+                getView().receiveTextMessage(message);
+            }
+            return;
+        }
+
+        //将消息显示到列表上
+        if (content instanceof TTMemberChangedMessage) {
+            TTMemberChangedMessage changedMessage = (TTMemberChangedMessage) content;
+            if (getView() != null) {
+                getView().onMemberChanged(changedMessage);
+            }
+            return;
+        }
+
+        if (content instanceof TTDisplayMessage) {
+            TTDisplayMessage ttDisplayMessage = (TTDisplayMessage) content;
+            if (getView() != null) {
+                getView().onDisPlayChangeMessage(ttDisplayMessage);
+            }
+            return;
+        }
+
+        if (content instanceof TTDeviceStateChangedMessage) {
+            TTDeviceStateChangedMessage stateChangedMessage = (TTDeviceStateChangedMessage) content;
+            if (getView() != null) {
+                getView().onDeviceStateChanged(stateChangedMessage);
+            }
+            return;
+        }
+
+        if (content instanceof TTControlDeviceStateMessage) {
+            TTControlDeviceStateMessage controlDeviceStateMessage = (TTControlDeviceStateMessage) content;
+            if (getView() != null) {
+                getView().onControlDeviceState(controlDeviceStateMessage);
+            }
+            return;
+        }
+
+        if (content instanceof TTPlayBeatMessage) {
+            TTPlayBeatMessage playBeatMessage = (TTPlayBeatMessage) content;
+            if (getView() != null) {
+                getView().playBeatMessage(createPlayMidiBean(playBeatMessage));
+            }
+            return;
+        }
+
+        if (content instanceof TTMusicSyncMessage) {
+            TTMusicSyncMessage musicSyncMessage = (TTMusicSyncMessage) content;
+            if (getView() != null) {
+                getView().onMusicSyncMessage(musicSyncMessage);
+            }
+            return;
+        }
+    }
+
+    private PlayMidi createPlayMidiBean(TTPlayBeatMessage playMidiMessage) {
+        PlayMidi playMidi = new PlayMidi();
+        playMidi.setUserId(playMidiMessage.getUserId());
+        playMidi.setEnable(playMidiMessage.getEnable());
+        playMidi.setCustomType(playMidiMessage.getCustomType());
+        playMidi.setRate(playMidiMessage.getRate());
+        playMidi.setPlayVolume(playMidiMessage.getPlayVolume());
+        return playMidi;
+    }
+
+    public void startRemoteView(String targetUserId, TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, txCloudVideoView);
+    }
+
+    public void stopRemoteView(String targetUserId) {
+        TRTCSdkManager.getInstance().stopRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
+    }
+
+
+    public void startLocalPreview(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startLocalPreview(txCloudVideoView);
+        TRTCSdkManager.getInstance().startLocalAudio();
+    }
+
+    public void startPublish(String roomId, String userId) {
+        TRTCSdkManager.getInstance().startPublish(TTLiveConfig.getStreamId(roomId, userId));
+    }
+
+    public void startPlay(int id, String path) {
+        TRTCSdkManager.getInstance().playBgMusic(id, path);
+    }
+
+    public void changeCameraEnable(boolean cameraDisable) {
+        TRTCSdkManager.getInstance().setCameraDisable(cameraDisable);
+    }
+
+
+    public void stopPlay(int id) {
+        TRTCSdkManager.getInstance().stopBgMusic(id);
+    }
+
+    public void changePlayVolume(int volumeValue) {
+        TRTCSdkManager.getInstance().setAllMusicVolume(volumeValue);
+    }
+
+    public void changeRemoteAudioVolume(String targetId, List<ClassMember> memberList, boolean isEnable) {
+        if (memberList == null) {
+            return;
+        }
+        for (int i = 0; i < memberList.size(); i++) {
+            ClassMember classMember = memberList.get(i);
+            if (classMember.getRole() == Role.LECTURER) {
+                continue;
+            }
+            String userId = classMember.getUserId();
+            if (TextUtils.equals(classMember.getUserId(), targetId)) {
+                continue;
+            }
+
+            Log.i("pq", "设置" + userId + "音量:" + (isEnable ? 100 : 0));
+            TRTCSdkManager.getInstance().setRemoteAudioVolume(userId, isEnable ? 100 : 0);
+        }
+    }
+
+    public void changeRemoteAudioVolume(String targetId, boolean isEnable) {
+        TRTCSdkManager.getInstance().setRemoteAudioVolume(targetId, isEnable ? 100 : 0);
+    }
+
+    public void config3AParamsFromSubject(String subjectId) {
+        if (TextUtils.equals(subjectId, ClassRoomConstants.SUBJECT_ID_SAX)) {
+            //萨克斯
+            TRTCSdkManager.getInstance().config3AParams(45, 100, 0);
+            return;
+        }
+
+        if (TextUtils.equals(subjectId, ClassRoomConstants.SUBJECT_ID_TROMBONE)) {
+            //长号
+            TRTCSdkManager.getInstance().config3AParams(45, 100, 0);
+            return;
+        }
+
+        if (TextUtils.equals(subjectId, ClassRoomConstants.SUBJECT_ID_TENOR_HORN)) {
+            //次中音号
+            TRTCSdkManager.getInstance().config3AParams(80, 100, 0);
+            return;
+        }
+
+        if (TextUtils.equals(subjectId, ClassRoomConstants.SUBJECT_ID_TRUMPET)) {
+            //小号
+            TRTCSdkManager.getInstance().config3AParams(50, 100, 0);
+            return;
+        }
+    }
+
+    public void sendTextMessage(String targetId, String message) {
+        if (!TextUtils.isEmpty(targetId)) {
+            TCClassRoomTextMessage tcTextMessage = new TCClassRoomTextMessage();
+            tcTextMessage.setText(message);
+            MessageManager.getInstance().sendMessage(targetId, true, tcTextMessage);
+        }
+    }
+
+    public void bindGroupListener() {
+        TCIMSdkManager.getInstance().addGroupListener(mGroupListener);
+    }
+
+    public void release() {
+        if (mGroupListener != null) {
+            TCIMSdkManager.getInstance().removeGroupListener(mGroupListener);
+        }
+    }
+
+    public void getAllGroupAttributes(String groupId) {
+        TCIMSdkManager.getInstance().getGroupAttributes(groupId, new V2TIMValueCallback() {
+            @Override
+            public void onSuccess(Object o) {
+                if (getView() != null) {
+                    getView().getAllGroupAttributesSuccess(o);
+                }
+            }
+
+            @Override
+            public void onError(int i, String s) {
+
+            }
+        });
+    }
+}

+ 30 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/StudentPreviewBigFragmentPresenter.java

@@ -0,0 +1,30 @@
+package com.dayayuemeng.classroom.presenter;
+
+import com.cooleshow.base.presenter.BasePresenter;
+import com.daya.tclive.manager.TRTCSdkManager;
+import com.dayayuemeng.classroom.contract.MainVideoFragmentContractView;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+import com.tencent.trtc.TRTCCloudDef;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class StudentPreviewBigFragmentPresenter extends BasePresenter<MainVideoFragmentContractView.View> {
+    public void startLocalPreview(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startLocalPreview(txCloudVideoView);
+        TRTCSdkManager.getInstance().startLocalAudio();
+    }
+
+    public void startRemoteView(String targetUserId, TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, txCloudVideoView);
+    }
+
+    public void stopRemoteView(String targetUserId) {
+        TRTCSdkManager.getInstance().stopRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
+    }
+
+    public void updateLocalView(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().updateLocalView(txCloudVideoView);
+    }
+
+}

+ 296 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/TeacherNetClassRoomPresenter.java

@@ -0,0 +1,296 @@
+package com.dayayuemeng.classroom.presenter;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.cooleshow.base.presenter.BasePresenter;
+import com.daya.tclive.bean.TTMessage;
+import com.daya.tclive.callback.ResultCallback;
+import com.daya.tclive.constants.MessageConstants;
+import com.daya.tclive.constants.TTLiveConfig;
+import com.daya.tclive.helper.TTLiveHelper;
+import com.daya.tclive.manager.MessageManager;
+import com.daya.tclive.manager.TCIMSdkManager;
+import com.daya.tclive.manager.TRTCSdkManager;
+import com.daya.tclive.message.BaseTIMMessageContent;
+import com.daya.tclive.message.TCAddLikeMessage;
+import com.daya.tclive.message.TCLiveRoomMemberNumMessage;
+import com.daya.tclive.message.TCUserEnterMessage;
+import com.daya.tclive.message.TCUserLeaveMessage;
+import com.daya.tclive.message.TCUserLogOutUnNormalMessage;
+import com.daya.tclive.message.TCUserMicStatusChangeMessage;
+import com.daya.tclive.message.TCUserSeatApplyMessage;
+import com.daya.tclive.message.TCUserSnappingUpMessage;
+import com.dayayuemeng.classroom.bean.ClassMember;
+import com.dayayuemeng.classroom.constants.ClassRoomConstants;
+import com.dayayuemeng.classroom.constants.Role;
+import com.dayayuemeng.classroom.contract.TeacherNetClassRoomContract;
+import com.dayayuemeng.classroom.im.message.TCClassRoomTextMessage;
+import com.dayayuemeng.classroom.im.message.TTDeviceStateChangedMessage;
+import com.dayayuemeng.classroom.im.message.TTDisplayMessage;
+import com.dayayuemeng.classroom.im.message.TTMemberChangedMessage;
+import com.tencent.imsdk.v2.V2TIMCallback;
+import com.tencent.imsdk.v2.V2TIMManager;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+import com.tencent.trtc.TRTCCloudDef;
+import com.tencent.trtc.TRTCCloudListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import io.reactivex.rxjava3.disposables.Disposable;
+import io.reactivex.rxjava3.functions.Consumer;
+
+import static com.tencent.imsdk.v2.V2TIMManager.V2TIM_STATUS_LOGINED;
+import static com.tencent.imsdk.v2.V2TIMManager.V2TIM_STATUS_LOGINING;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class TeacherNetClassRoomPresenter extends BasePresenter<TeacherNetClassRoomContract.View> implements TeacherNetClassRoomContract.Presenter {
+    public static final String TAG = "TNCRPresenter";
+    private List<Disposable> disposablesManager = new ArrayList<>();//监听管理器
+    private String cRoomId = "";
+
+    private TRTCCloudListener mCloudListener = new TRTCCloudListener() {
+        @Override
+        public void onEnterRoom(long result) {
+            if (result > 0) {
+                Log.d(TAG, "Enter room succeed");
+                if (getView() != null) {
+                    getView().enterLiveRoomSuccess();
+                }
+            } else {
+                Log.d(TAG, "Enter room failed");
+                if (getView() != null) {
+                    getView().enterLiveRoomError();
+                }
+            }
+        }
+
+        @Override
+        public void onStopPublishing(int err, String errMsg) {
+            super.onStopPublishing(err, errMsg);
+            Log.i(TAG, "onStopPublishing:" + err + "--errMsg:" + errMsg);
+            if (getView() != null) {
+                getView().onStopPublishing();
+            }
+        }
+
+        @Override
+        public void onStartPublishing(int err, String errMsg) {
+            Log.i(TAG, "onStartPublishing:" + err + "--errMsg:" + errMsg);
+            if (getView() != null) {
+                getView().onPublishSuccess();
+            }
+        }
+
+        @Override
+        public void onRemoteUserEnterRoom(String userId) {
+        }
+
+        @Override
+        public void onRemoteUserLeaveRoom(String userId, int reason) {
+        }
+
+        @Override
+        public void onNetworkQuality(TRTCCloudDef.TRTCQuality localQuality, ArrayList<TRTCCloudDef.TRTCQuality> remoteQuality) {
+            super.onNetworkQuality(localQuality, remoteQuality);
+            if (getView() != null) {
+                getView().onNetworkQuality(localQuality, remoteQuality);
+            }
+        }
+
+        @Override
+        public void onUserVoiceVolume(ArrayList<TRTCCloudDef.TRTCVolumeInfo> userVolumes, int totalVolume) {
+            if (getView() != null) {
+                getView().onUserVoiceVolume(userVolumes, totalVolume);
+            }
+        }
+    };
+
+    public void initPublishConfig(Context context, int imSdkAppId) {
+        //初始化直播SDK
+        TRTCSdkManager.getInstance().init(context, mCloudListener);
+        //开启音量大小提示,SDK 会在 TRTCCloudListener 中的 onUserVoiceVolume 回调中反馈本地或远端用户的音频音量评估信息,包括音量大小、人声检测、音频频谱等。
+        TRTCSdkManager.getInstance().enableAudioVolumeEvaluation();
+        //初始化IM
+        TCIMSdkManager.getInstance().init(context.getApplicationContext(), imSdkAppId);
+    }
+
+    public void initDefaultBitmap(Bitmap bitmap) {
+        TRTCSdkManager.getInstance().setVideoMuteImage(bitmap);
+    }
+
+    public void enterRoom(int sdkAppId, String userId, String roomId, String userSig) {
+        TRTCSdkManager.getInstance().enterRoom(sdkAppId, userId, roomId, userSig, TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_LANDSCAPE);
+    }
+
+    public void config3AParamsFromSubject(String subjectId){
+        if(TextUtils.equals(subjectId, ClassRoomConstants.SUBJECT_ID_SAX)){
+            //萨克斯
+            TRTCSdkManager.getInstance().config3AParams(45,100,0);
+            return;
+        }
+
+        if(TextUtils.equals(subjectId,ClassRoomConstants.SUBJECT_ID_TROMBONE)){
+            //长号
+            TRTCSdkManager.getInstance().config3AParams(45,100,0);
+            return;
+        }
+
+        if(TextUtils.equals(subjectId, ClassRoomConstants.SUBJECT_ID_TENOR_HORN)){
+            //次中音号
+            TRTCSdkManager.getInstance().config3AParams(80,100,0);
+            return;
+        }
+
+        if(TextUtils.equals(subjectId, ClassRoomConstants.SUBJECT_ID_TRUMPET)){
+            //小号
+            TRTCSdkManager.getInstance().config3AParams(50,100,0);
+            return;
+        }
+    }
+
+    public void connectIM(String roomId, String userId, String userSig) {
+        int loginStatus = V2TIMManager.getInstance().getLoginStatus();
+        if (loginStatus != V2TIM_STATUS_LOGINED && loginStatus != V2TIM_STATUS_LOGINING) {
+            //既不是已登录和登录中状态,则登录
+            this.cRoomId = roomId;
+            getView().showLoading();
+            V2TIMManager.getInstance().login(userId, userSig, new V2TIMCallback() {
+                @Override
+                public void onSuccess() {
+                    Log.i("TTLiveRoomActivity", "login IM success");
+                    if (getView() != null) {
+                        getView().loginIMSuccess();
+                    }
+                    registerListener(roomId);
+                }
+
+                @Override
+                public void onError(int code, String desc) {
+                    // 如果返回以下错误码,表示使用 UserSig 已过期,请您使用新签发的 UserSig 进行再次登录。
+                    // 1. ERR_USER_SIG_EXPIRED(6206)
+                    // 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED(70001)
+                    // 注意:其他的错误码,请不要在这里调用登录接口,避免 IM SDK 登录进入死循环。
+                    Log.i("TTLiveRoomActivity", "connectIM failure, code:" + code + ", desc:" + desc);
+                    if (getView() != null) {
+                        getView().connectIMError(code, desc);
+                    }
+                }
+            });
+        }
+    }
+
+    private void registerListener(String roomId) {
+        setObMessageListener(roomId);
+        MessageManager.getInstance().register();
+        MessageManager.getInstance().registerMessageType(TTMemberChangedMessage.class);
+        MessageManager.getInstance().registerMessageType(TTDisplayMessage.class);
+        MessageManager.getInstance().registerMessageType(TTDeviceStateChangedMessage.class);
+        MessageManager.getInstance().registerMessageType(TCClassRoomTextMessage.class);
+    }
+
+    public void setObMessageListener(String roomId) {
+        if (disposablesManager.size() != 0) {
+            return;
+        }
+        Disposable subscribe = MessageManager.getInstance()
+                .obMessageReceiveByRoomId(roomId)
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new Consumer<TTMessage>() {
+                    @Override
+                    public void accept(TTMessage message) {
+                        BaseTIMMessageContent content = message.getContent();
+                        //将消息显示到列表上
+                        if (content instanceof TCClassRoomTextMessage) {
+                            if (getView() != null) {
+                                getView().receiveTextMessage(message);
+                            }
+                            return;
+                        }
+                        if (content instanceof TTMemberChangedMessage) {
+                            TTMemberChangedMessage changedMessage = (TTMemberChangedMessage) content;
+                            if (getView() != null) {
+                                getView().onMemberChanged(changedMessage);
+                            }
+                            return;
+                        }
+
+                        if (content instanceof TTDeviceStateChangedMessage) {
+                            TTDeviceStateChangedMessage stateChangedMessage = (TTDeviceStateChangedMessage) content;
+                            if (getView() != null) {
+                                getView().onDeviceStateChanged(stateChangedMessage);
+                            }
+                            return;
+                        }
+                    }
+                });
+        disposablesManager.add(subscribe);
+    }
+
+
+    public void startLocalPreview(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startLocalPreview(txCloudVideoView);
+        TRTCSdkManager.getInstance().startLocalAudio();
+    }
+
+    public void updateLocalView(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().updateLocalView(txCloudVideoView);
+    }
+
+    public void startPublish(String roomId, String userId) {
+        TRTCSdkManager.getInstance().startPublish(TTLiveConfig.getStreamId(roomId, userId));
+    }
+
+    public void startRemoteView(String targetUserId, TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, txCloudVideoView);
+    }
+
+    public void stopRemoteView(String targetUserId) {
+        TRTCSdkManager.getInstance().stopRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
+    }
+
+    public void changeCameraEnable(boolean cameraDisable) {
+        TRTCSdkManager.getInstance().setCameraDisable(cameraDisable);
+    }
+
+    public void changeRemoteAudioVolume(String targetId, List<ClassMember> memberList, boolean isEnable) {
+        if (memberList == null) {
+            return;
+        }
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < memberList.size(); i++) {
+            ClassMember classMember = memberList.get(i);
+            if (classMember.getRole() != Role.LECTURER) {
+                String userId = classMember.getUserId();
+                String name = TextUtils.isEmpty(classMember.getUserName()) ? classMember.getUserId() : classMember.getUserName();
+                if (TextUtils.equals(classMember.getUserId(), targetId)) {
+                    builder.append("\n").append("设置:" + name + "-音量:" + (100));
+                    TRTCSdkManager.getInstance().setRemoteAudioVolume(userId, 100);
+                } else {
+                    builder.append("\n").append("设置:" + name + "-音量:" + (isEnable ? 100 : 0));
+                    TRTCSdkManager.getInstance().setRemoteAudioVolume(userId, isEnable ? 100 : 0);
+                }
+            }
+        }
+        Log.i("pq", builder.toString().trim());
+    }
+
+    public void changeRemoteAudioVolume(String targetId,boolean isEnable){
+        TRTCSdkManager.getInstance().setRemoteAudioVolume(targetId, isEnable ? 100 : 0);
+    }
+
+    public void sendTextMessage(String targetId, String message) {
+        if (!TextUtils.isEmpty(targetId)) {
+            TCClassRoomTextMessage tcTextMessage = new TCClassRoomTextMessage();
+            tcTextMessage.setText(message);
+            MessageManager.getInstance().sendMessage(targetId, true, tcTextMessage);
+        }
+    }
+}

+ 77 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/TopOperateControlPresenter.java

@@ -0,0 +1,77 @@
+package com.dayayuemeng.classroom.presenter;
+
+import com.cooleshow.base.common.BaseApplication;
+import com.cooleshow.base.presenter.BasePresenter;
+import com.daya.tclive.manager.TRTCSdkManager;
+import com.dayayuemeng.classroom.api.ResultCallback;
+import com.dayayuemeng.classroom.contract.TopOperateControlView;
+import com.dayayuemeng.classroom.repository.ClassRepository;
+import com.tencent.trtc.TRTCCloudDef;
+
+import androidx.lifecycle.LiveData;
+
+/**
+ * Author by pq, Date on 2023/4/24.
+ */
+public class TopOperateControlPresenter extends BasePresenter<TopOperateControlView.View> {
+    private ClassRepository mClassRepository;
+
+    private ClassRepository getClassRepository() {
+        if (mClassRepository == null) {
+            mClassRepository = new ClassRepository(BaseApplication.Companion.getContext());
+        }
+        return mClassRepository;
+    }
+
+    public void deviceSyncMic(String roomId, boolean microphoneOn) {
+        getClassRepository().deviceSyncMic(roomId, microphoneOn, new ResultCallback<Boolean>() {
+            @Override
+            public void onSuccess(Boolean result) {
+                if (getView() != null) {
+                    getView().deviceSyncMicResult(microphoneOn,result);
+                }
+            }
+
+            @Override
+            public void onFail(int errorCode, String errorStr) {
+                if (getView() != null) {
+                    getView().deviceSyncMicResult(microphoneOn,false);
+                }
+            }
+        });
+    }
+
+    public void deviceSyncCamera(String roomId, boolean cameraOn){
+        getClassRepository().deviceSyncCamera(roomId, cameraOn, new ResultCallback<Boolean>() {
+            @Override
+            public void onSuccess(Boolean result) {
+                if (getView() != null) {
+                    getView().deviceSyncCameraResult(cameraOn,result);
+                }
+            }
+
+            @Override
+            public void onFail(int errorCode, String errorStr) {
+                if (getView() != null) {
+                    getView().deviceSyncCameraResult(cameraOn,false);
+                }
+            }
+        });
+    }
+
+    public void changeMicPhone(boolean microphoneOn) {
+        TRTCSdkManager.getInstance().setMicPhoneDisable(microphoneOn);
+    }
+
+    public void changeCamera(boolean cameraIsOn) {
+        TRTCSdkManager.getInstance().setCameraDisable(cameraIsOn);
+    }
+
+    public void setAudioRoute(boolean isSelected){
+        TRTCSdkManager.getInstance().setAudioRoute(isSelected ? TRTCCloudDef.TRTC_AUDIO_ROUTE_SPEAKER : TRTCCloudDef.TRTC_AUDIO_ROUTE_EARPIECE);
+    }
+
+    public void switchCamera(){
+        TRTCSdkManager.getInstance().switchCamera();
+    }
+}

+ 41 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/presenter/VideoListFragmentPresenter.java

@@ -0,0 +1,41 @@
+package com.dayayuemeng.classroom.presenter;
+
+import com.cooleshow.base.presenter.BasePresenter;
+import com.daya.tclive.manager.TRTCSdkManager;
+import com.dayayuemeng.classroom.contract.MainVideoFragmentContractView;
+import com.tencent.rtmp.ui.TXCloudVideoView;
+import com.tencent.trtc.TRTCCloudDef;
+
+/**
+ * Author by pq, Date on 2023/4/20.
+ */
+public class VideoListFragmentPresenter extends BasePresenter<MainVideoFragmentContractView.View> {
+    public void startLocalPreview(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startLocalPreview(txCloudVideoView);
+        TRTCSdkManager.getInstance().startLocalAudio();
+    }
+
+    public void startRemoteView(String targetUserId, TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().startRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, txCloudVideoView);
+    }
+
+    public void stopRemoteView(String targetUserId) {
+        TRTCSdkManager.getInstance().stopRemoteView(targetUserId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
+    }
+
+    public void updateLocalView(TXCloudVideoView txCloudVideoView) {
+        TRTCSdkManager.getInstance().updateLocalView(txCloudVideoView);
+    }
+
+    public void changeMicPhone(boolean microphoneOn) {
+        TRTCSdkManager.getInstance().setMicPhoneDisable(microphoneOn);
+    }
+
+    public void changeCameraEnable(boolean cameraDisable) {
+        TRTCSdkManager.getInstance().setCameraDisable(cameraDisable);
+    }
+
+    public void changeCamera(boolean cameraIsOn) {
+        TRTCSdkManager.getInstance().setCameraDisable(cameraIsOn);
+    }
+}

+ 96 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/receiver/HeadsetPlugReceiver.java

@@ -0,0 +1,96 @@
+package com.dayayuemeng.classroom.receiver;
+
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothProfile;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.cooleshow.base.utils.LOG;
+
+
+/**
+ * 有线耳机和蓝牙耳机插入和拔出广播监听
+ */
+public class HeadsetPlugReceiver extends BroadcastReceiver {
+    private static final String TAG = "HeadsetPlugReceiver";
+
+    public boolean FIRST_HEADSET_PLUG_RECEIVER = false;
+    private static OnHeadsetPlugListener headsetPlugListener = null;
+
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+        HeadsetInfo headsetInfo = null;
+
+        if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
+            int state = -1;
+            if (FIRST_HEADSET_PLUG_RECEIVER) {
+                if (intent.hasExtra("state")) {
+                    state = intent.getIntExtra("state", -1);
+                }
+                if (state == 1) {
+                    headsetInfo = new HeadsetInfo(true, 1);
+                } else if (state == 0) {
+                    headsetInfo = new HeadsetInfo(false, 1);
+                }
+            } else {
+                FIRST_HEADSET_PLUG_RECEIVER = true;
+            }
+        } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
+            int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
+            switch (state) {
+                case BluetoothProfile.STATE_DISCONNECTED:
+                    headsetInfo = new HeadsetInfo(false, 0);
+                    break;
+                case BluetoothProfile.STATE_CONNECTED:
+                    headsetInfo = new HeadsetInfo(true, 0);
+                    break;
+            }
+        }
+
+        if (null != headsetInfo && headsetPlugListener != null) {
+            LOG.d(TAG, "isConnected:" + headsetInfo.isConnected() + ",type:" + headsetInfo.getType());
+            headsetPlugListener.onNotifyHeadsetState(headsetInfo.isConnected(), headsetInfo.getType());
+        }
+    }
+
+    public static void setOnHeadsetPlugListener(OnHeadsetPlugListener onHeadsetPlugListener) {
+        headsetPlugListener = onHeadsetPlugListener;
+    }
+
+
+
+    public interface OnHeadsetPlugListener {
+        /**
+         * 耳机连接状态监听
+         *
+         * @param connected 是否连接
+         * @param type      连接类型 ,0:蓝牙耳机;1:有线耳机
+         */
+        void onNotifyHeadsetState(boolean connected, int type);
+    }
+
+    private class HeadsetInfo {
+        boolean isConnected;
+        int type;
+
+        HeadsetInfo(boolean isInsert, int type) {
+            this.isConnected = isInsert;
+            this.type = type;
+        }
+
+        boolean isConnected() {
+            return isConnected;
+        }
+
+        int getType() {
+            return type;
+        }
+
+        void setType(int type) {
+            this.type = type;
+        }
+    }
+}

+ 31 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/repository/BaseRepository.java

@@ -0,0 +1,31 @@
+package com.dayayuemeng.classroom.repository;
+
+import android.content.Context;
+
+import com.dayayuemeng.classroom.api.HttpClientManager;
+import com.dayayuemeng.classroom.api.retrofit.RetrofitClient;
+
+
+public class BaseRepository {
+    private RetrofitClient client;
+    private  Context           context;
+    private HttpClientManager httpManager;
+
+    public BaseRepository(Context context) {
+        this.httpManager = HttpClientManager.getInstance(context);
+        client = httpManager.getClient();
+        this.context = context;
+    }
+
+    public <T> T getService(Class<T> clazz) {
+        return client.createService(clazz);
+    }
+
+    public HttpClientManager getHttpManager() {
+        return httpManager;
+    }
+
+    public Context getContext() {
+        return context;
+    }
+}

+ 439 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/repository/ClassRepository.java

@@ -0,0 +1,439 @@
+package com.dayayuemeng.classroom.repository;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+
+import com.cooleshow.base.constanst.Constants;
+import com.cooleshow.base.data.net.RetrofitClientNoToken;
+import com.cooleshow.base.data.net.RetrofitFactory;
+import com.cooleshow.base.rx.BaseObserver;
+import com.cooleshow.base.utils.DeviceUtil;
+import com.cooleshow.base.utils.DeviceUtils;
+import com.cooleshow.base.utils.FileUtils;
+import com.dayayuemeng.classroom.api.LiveTeachingApi;
+import com.dayayuemeng.classroom.api.ResultCallback;
+import com.dayayuemeng.classroom.api.WhiteBoardApi;
+import com.dayayuemeng.classroom.api.retrofit.CallBackWrapper;
+import com.dayayuemeng.classroom.api.retrofit.RetrofitClient;
+import com.dayayuemeng.classroom.api.retrofit.RetrofitUtil;
+import com.dayayuemeng.classroom.bean.ClassMember;
+import com.dayayuemeng.classroom.bean.LoginResult;
+import com.dayayuemeng.classroom.bean.WhiteCreateBean;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import io.reactivex.rxjava3.schedulers.Schedulers;
+import okhttp3.MultipartBody;
+import okhttp3.RequestBody;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * 课堂数据仓库
+ */
+public class ClassRepository extends BaseRepository {
+    private static final String PARAM_ROOM_ID = "roomId";
+    private static final String PARAM_USER_ID = "userId";
+    private static final String PARAM_CAMERA_ON = "cameraOn";
+    // 5 原音6 伴奏
+    private static final String PARAM_DEVICE_TYPE = "deviceType";
+    private static final String PARAM_SOUND_VOLUME = "soundVolume";
+    private static final String MUSIC_MODE_ON = "musicModeOn";
+    private static final String PARAM_MIC_ON = "microphoneOn";
+    private static final String CANCEL_MUTE_FLAG = "cancelMuteFlag";
+    private static final String HAND_UP_ON = "handUpOn";
+    private static final String MUSIC_SCORE_ON = "musicScoreOn";
+    private static final String ACCOMPANIMENT_ON = "accompanimentOn";
+    private static final String PARAM_USERS = "users";
+    private static final String PARAM_TICKET = "ticket";
+    private static final String PARAM_ROLE = "role";
+    private static final String PARAM_WHITEBOARD_ID = "whiteboardId";
+    private static final String EXAM_SONG_ID = "musicScoreAccompanimentId";
+    private static final String PARAM_TYPE = "type";
+    private static final String PARAM_URI = "uri";
+    private LiveTeachingApi sealClassService;
+    private LiveTeachingApi liveClassNoToken;
+    private WhiteBoardApi whiteBoardService;
+
+    public ClassRepository(Context context) {
+        super(context);
+        sealClassService = getService(LiveTeachingApi.class);
+        liveClassNoToken = RetrofitClientNoToken.getInstance().getRetrofit().create(LiveTeachingApi.class);
+        whiteBoardService = RetrofitFactory.Companion.getInstance().create(WhiteBoardApi.class);
+    }
+
+    public void leave(String roomId, String userId, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put("deviceNum", DeviceUtils.getAndroidID());
+        sealClassService.leave(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+
+    public void kickOff(String roomId, String userId, final ResultCallback<Boolean> callBack) {
+
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        sealClassService.kickOff(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void queryNoJoinStu(String roomId, final ResultCallback<List<ClassMember>> callBack) {
+        sealClassService.queryNoJoinStu(roomId).enqueue(new CallBackWrapper<List<ClassMember>>(callBack));
+    }
+
+
+    public void controlCamera(String roomId, String userId, boolean cameraOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(PARAM_CAMERA_ON, cameraOn);
+        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void controlVolume(String roomId, String userId, boolean cameraOn, String deviceType, String soundVolume, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(PARAM_CAMERA_ON, cameraOn);
+        bodyMap.put(PARAM_DEVICE_TYPE, deviceType);
+        bodyMap.put(PARAM_SOUND_VOLUME, soundVolume);
+        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void sendImPlayMidiMessage(String userId, String roomId, boolean enable, int rate, int customType, int playVolume, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        HashMap<String, Object> contentMap = new HashMap<>();
+        contentMap.put(PARAM_USER_ID, userId);
+        contentMap.put("enable", enable);
+        contentMap.put("rate", rate);
+        contentMap.put("customType", customType);
+        contentMap.put("playVolume", playVolume);
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put("content", contentMap);
+        sealClassService.sendImPlayMidiMessage(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+
+    }
+
+
+    public void controlMicrophone(String roomId, String userId, boolean microphone, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(PARAM_MIC_ON, microphone);
+        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void controlHandUpOn(String roomId, String userId, boolean handUpOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(HAND_UP_ON, handUpOn);
+        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void controlMusicMode(String roomId, String userId, boolean musicModeOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(MUSIC_MODE_ON, musicModeOn);
+        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+
+    }
+
+    public void batchControlCamera(String roomId, boolean cameraOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_CAMERA_ON, cameraOn);
+        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+
+    public void batchControlMusicMode(String roomId, boolean microphone, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(MUSIC_MODE_ON, microphone);
+        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void batchControlMicrophone(String roomId, String userId, boolean musicModeOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(PARAM_MIC_ON, musicModeOn);
+        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void batchControlMicrophone(String roomId, String userId, boolean musicModeOn, boolean cancelFlag, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(PARAM_MIC_ON, musicModeOn);
+        bodyMap.put(CANCEL_MUTE_FLAG, cancelFlag);
+        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void batchControlMuteCancelFlag(String roomId, boolean cancelFlag, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(CANCEL_MUTE_FLAG, cancelFlag);
+        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    //伴奏
+    public void batchControlExamSong(String roomId, String userId, String musicScoreOn, String accompanimentOn, String musicScoreAccompanimentId, String soudnValue, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(MUSIC_SCORE_ON, musicScoreOn);
+        bodyMap.put(ACCOMPANIMENT_ON, accompanimentOn);
+        bodyMap.put(EXAM_SONG_ID, musicScoreAccompanimentId);
+        bodyMap.put(PARAM_SOUND_VOLUME, soudnValue);
+        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+
+    }
+
+    public void controlExamSong(String roomId, String userId, String musicScoreOn, String accompanimentOn, String musicScoreAccompanimentId, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(MUSIC_SCORE_ON, musicScoreOn);
+        bodyMap.put(ACCOMPANIMENT_ON, accompanimentOn);
+        bodyMap.put(EXAM_SONG_ID, musicScoreAccompanimentId);
+        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void deviceApprove(String roomId, String ticket, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_TICKET, ticket);
+        sealClassService.deviceApprove(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void deviceReject(String roomId, String ticket, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_TICKET, ticket);
+        sealClassService.deviceReject(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void deviceSyncHandUpOn(String roomId, String userId, boolean handUpOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(HAND_UP_ON, handUpOn);
+        bodyMap.put(PARAM_USER_ID, userId);
+        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void deviceSyncMusicMode(String roomId, boolean musicModeOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(MUSIC_MODE_ON, musicModeOn);
+        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void deviceSyncCamera(String roomId, boolean cameraOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_CAMERA_ON, cameraOn);
+        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void deviceSyncMic(String roomId, boolean microphoneOn, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_MIC_ON, microphoneOn);
+        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void deviceSyncExamSong(String roomId, boolean examSong, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(MUSIC_SCORE_ON, examSong);
+        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+
+    public void applySpeech(String roomId, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        sealClassService.applySpeech(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+
+    public void approveSpeech(String roomId, String ticket, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_TICKET, ticket);
+        sealClassService.applyApprove(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+
+    public void rejectSpeech(String roomId, String ticket, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_TICKET, ticket);
+        sealClassService.applyReject(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void transferRole(String roomId, String userId, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        sealClassService.transferRole(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void upgradeIntive(String roomId, String userId, int role, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(PARAM_ROLE, role);
+        sealClassService.upgradeInvite(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void upgradeApprove(String roomId, String ticket, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_TICKET, ticket);
+        sealClassService.upgradeApprove(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void upgradeReject(String roomId, String ticket, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_TICKET, ticket);
+        sealClassService.upgradeReject(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    public void changeRole(String roomId, String userId, int role, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_USER_ID, userId);
+        bodyMap.put(PARAM_ROLE, role);
+        sealClassService.changeRole(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
+    }
+
+    /**
+     * 创建白板
+     *
+     * @param roomId
+     * @param callBack
+     */
+    public void createWhiteBoard(String roomId, ResultCallback<WhiteCreateBean> callBack) {
+        whiteBoardService.hereWhiteCreat("Page1", 0, roomId)
+                .subscribeOn(Schedulers.newThread())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribeWith(new BaseObserver<WhiteCreateBean>() {
+                    @Override
+                    protected void onSuccess(WhiteCreateBean data) {
+                        callBack.onSuccess(data);
+                    }
+                });
+    }
+
+
+    /**
+     * 通知学生下载伴奏
+     *
+     * @param roomId
+     */
+    public void pushDownloadexamSongMsg(String roomId, String musicScoreAccompanimentId, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(EXAM_SONG_ID, musicScoreAccompanimentId);
+        sealClassService.pushDownloadexamSongMsg(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<>(callBack));
+    }
+
+    /**
+     * 同步学生下载结果
+     *
+     * @param roomId
+     */
+    public void adjustExamSong(String roomId, String musicScoreAccompanimentId, int status, ResultCallback<Boolean> callBack) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(EXAM_SONG_ID, musicScoreAccompanimentId);
+        bodyMap.put("status", status);
+        sealClassService.adjustExamSong(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<>(callBack));
+    }
+
+
+
+    /**
+     * 课程申诉
+     */
+    public void addComplaints(String courseScheduleId, String url, String content, ResultCallback<Boolean> callBack) {
+        whiteBoardService.addComplaints(courseScheduleId, url, content, "ALL")
+                .subscribeOn(Schedulers.newThread())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribeWith(new BaseObserver<String>() {
+                    @Override
+                    protected void onSuccess(String data) {
+                        callBack.onSuccess(true);
+                    }
+
+                    @Override
+                    public void onError(Throwable e) {
+                        super.onError(e);
+                        callBack.onFail(-1, null);
+                    }
+                });
+    }
+
+    /**
+     * 下载文件
+     */
+    public void downloadFile(String fileUrl, String filePath, String fileName, ResultCallback<Boolean> callback) {
+        liveClassNoToken.downloadFileWithFixedUrl(fileUrl).enqueue(new Callback<ResponseBody>() {
+            @Override
+            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
+                if (FileUtils.writeFileToSDCard(response.body(), filePath, fileName)) {
+                    callback.onSuccess(true);
+                } else {
+                    callback.onSuccess(false);
+                }
+            }
+
+            @Override
+            public void onFailure(Call<ResponseBody> call, Throwable t) {
+                callback.onSuccess(false);
+            }
+        });
+    }
+
+    /**
+     * 切换共享画布区显示内容
+     *
+     * @param roomId   房间Id
+     * @param type     显示类型,参考{@link ScreenDisplay.Display}
+     * @param userId   当显示类型为用户时,传入该用户的id
+     * @param uri      当显示类型为白板时,传入白板id
+     * @param callback
+     */
+    public void switchDisplay(String roomId, int type, String userId, String uri, ResultCallback<Boolean> callback) {
+        HashMap<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put(PARAM_ROOM_ID, roomId);
+        bodyMap.put(PARAM_TYPE, type);
+        if (userId != null) {
+            bodyMap.put(PARAM_USER_ID, userId);
+        }
+        if (uri != null) {
+            bodyMap.put(PARAM_URI, uri);
+        }
+        sealClassService.switchDisplay(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<>(callback));
+    }
+
+    public void getRoomInfo(String roomId, ResultCallback<LoginResult> callBack) {
+        sealClassService.info(roomId).enqueue(new CallBackWrapper<LoginResult>(callBack));
+    }
+}

+ 127 - 0
classRoom/src/main/java/com/dayayuemeng/classroom/repository/OnClassEventListener.java

@@ -0,0 +1,127 @@
+package com.dayayuemeng.classroom.repository;
+
+
+import java.util.List;
+
+
+public interface OnClassEventListener {
+//    /**
+//     * 当有用户进出课堂时回调
+//     * @param action
+//     *         当前用户的行为:1.进入课堂;2.退出课堂;3.踢出课堂
+//     * @param classMember
+//     */
+//    void onMemberChanged(ClassMemberChangedAction action, ClassMember classMember);
+//
+//    /**
+//     * 当白板发送变化时回调
+//     * @param action
+//     *         发生变化的白板状态:1.创建白板;2.删除白板
+//     * @param whiteBoard
+//     */
+//    void onWhiteBoardChanged(WhiteBoardAction action, WhiteBoard whiteBoard);
+//
+//    /**
+//     * 当有邀请开启设备(摄像头、麦克风)请求时和邀请对方开启设备后对方有回应时回调
+//     * @param deviceControlInvite
+//     */
+//    void onOpenDeviceInvite(DeviceControlInvite deviceControlInvite);
+//
+//    /**
+//     * 当用户的摄像头,麦克风状态改变时回调
+//     * @param senderUserId
+//     * @param userId
+//     *         设备状态发生改变的用户id
+//     * @param deviceType
+// *         设备类型
+//     * @param isEnable
+//     * @param musicScoreAccompanimentId
+//     */
+//    void onDeviceStateChanged(String senderUserId, String userId, DeviceType deviceType, boolean isEnable, String musicScoreAccompanimentId);
+//
+//    /**
+//     * 当用户的摄像头,麦克风状态改变时回调
+//     * @param userId
+//     *         设备状态发生改变的用户id
+//     * @param deviceType
+//     *         设备类型
+//     * @param isEnable
+//     *         设备是否启用
+//     */
+//    void onDeviceStateChanged(String userId, DeviceType deviceType, boolean isEnable, String musicScoreAccompanimentId);
+//
+//    /**
+//     * 控制音量
+//     * @param soundVolume
+//     * @param deviceType
+//     */
+//    void onDeviceStateChanged(Integer soundVolume, DeviceType deviceType,String musicScoreAccompanimentId);
+//
+//    /**
+//     * 当共享画布区内容发送改变时回调
+//     */
+//    void onDisplayChanged(ScreenDisplay screenDisplay);
+//
+//    /**
+//     * 当白板翻页时回调
+//     * @param whiteBoardId
+//     *         白板 id
+//     * @param curPage
+//     *         当前页数
+//     * @param optUserId
+//     *         操作用户 id
+//     */
+//    void onWhiteBoardPageChanged(String whiteBoardId, int curPage, String optUserId);
+//
+//    /**
+//     * 用户角色改变回调
+//     * @param roleChangedUserList
+//     * @param optUserId
+//     *         操作用户 id
+//     */
+//    void onRoleChanged(List<RoleChangedUser> roleChangedUserList, String optUserId);
+//
+//    /**
+//     * 接受到旁听人申请发言回调
+//     * @param applyForSpeechRequest
+//     */
+//    void onApplyForSpeechRequest(ApplyForSpeechRequest applyForSpeechRequest);
+//
+//    /**
+//     * 当请求过期时回调
+//     * @param ticketExpired
+//     */
+//    void onTicketExpired(TicketExpired ticketExpired);
+//
+//    /**
+//     * 在申请发言有应答时回调
+//     * @param speechResult
+//     */
+//    void onRequestSpeechResult(SpeechResult speechResult);
+//
+//    /**
+//     * 在被邀请升级角色时回调
+//     */
+//    void onInviteUpgradeRole(UpgradeRoleInvite upgradeRoleInvite);
+//
+//    /**
+//     * 当有未读消息时回调
+//     * @param count
+//     */
+//    void onExistUnReadMessage(int count);
+//
+//    /**
+//     * 节拍器回调
+//     * @param
+//     */
+//    void onPlayMidiMessage(PlayMidi playMidi);
+//
+//    /**
+//     * 伴奏下载
+//     * @param
+//     */
+//    void onExamSongDownloadMessage(DownLoadSong song);
+//
+//
+//    void onExamSongDownloadStatus(String studentId, List<DownLoadSongStatus> downLoadSongStatus);
+}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů