zhaoyadi 2 年之前
父節點
當前提交
40a8c06bee
共有 23 個文件被更改,包括 852 次插入109 次删除
  1. 5 0
      .idea/misc.xml
  2. 3 4
      build.gradle
  3. 14 2
      kit/build.gradle
  4. 102 0
      kit/schemas/com.tencent.liteav.demo.superplayer.database.PlayerDatabase/2.json
  5. 102 0
      kit/schemas/com.tencent.liteav.demo.superplayer.database.PlayerDatabase/3.json
  6. 102 0
      kit/schemas/com.tencent.liteav.demo.superplayer.database.PlayerDatabase/4.json
  7. 35 0
      kit/src/main/java/com/tencent/liteav/demo/superplayer/ui/player/TimeOutPlayer.java
  8. 26 3
      kit/src/main/kotlin/com/tencent/liteav/demo/superplayer/database/PlayerDatabase.kt
  9. 2 1
      kit/src/main/kotlin/com/tencent/liteav/demo/superplayer/database/dao/HistoryDao.kt
  10. 15 0
      kit/src/main/kotlin/com/tencent/liteav/demo/superplayer/database/entity/CountDown.kt
  11. 8 0
      kit/src/main/kotlin/com/tencent/liteav/demo/superplayer/database/entity/History.kt
  12. 6 3
      ui/build.gradle
  13. 6 0
      ui/src/main/AndroidManifest.xml
  14. 3 3
      ui/src/main/java/com/tencent/liteav/demo/player/PlayerVerify.java
  15. 38 0
      ui/src/main/java/com/tencent/liteav/demo/player/util/PlayerTimerUtil.java
  16. 21 30
      ui/src/main/kotlin/com/tencent/liteav/demo/player/PlayerActivity.kt
  17. 73 62
      ui/src/main/kotlin/com/tencent/liteav/demo/player/PlayerMenu.kt
  18. 71 0
      ui/src/main/kotlin/com/tencent/liteav/demo/player/PlayerTimer.kt
  19. 37 1
      ui/src/main/kotlin/com/tencent/liteav/demo/player/viewmodel/PlayerViewModel.kt
  20. 12 0
      ui/src/main/res/drawable/menu_timer_option_decoration.xml
  21. 0 0
      ui/src/main/res/layout/fragment_menu.xml
  22. 171 0
      ui/src/main/res/layout/fragment_timer.xml
  23. 0 0
      ui/src/main/res/layout/fragment_verify.xml

+ 5 - 0
.idea/misc.xml

@@ -104,6 +104,7 @@
         <entry key="..\:/demo/.android/Player_Android/Demo/superplayerkit/src/main/res/layout/superplayer_vod_view.xml" value="0.18" />
         <entry key="..\:/demo/.android/Player_Android/Demo/superplayerkit/src/main/res/layout/superplayer_vod_vipwatch_view.xml" value="0.28306159420289856" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/drawable/menu_background.xml" value="0.1675" />
+        <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/drawable/menu_timer_option_decoration.xml" value="0.2735" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/drawable/sign_equal.xml" value="0.206" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/drawable/sign_multiply.xml" value="0.206" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/drawable/sign_plus.xml" value="0.206" />
@@ -112,9 +113,13 @@
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/drawable/verify_check_background.xml" value="0.206" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/drawable/verify_result_background.xml" value="0.206" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/drawable/verify_result_value_background.xml" value="0.206" />
+        <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/layout/activity_main.xml" value="0.24077868852459017" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/layout/activity_menu.xml" value="0.22370218579234974" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/layout/activity_player.xml" value="0.22370218579234974" />
         <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/layout/activity_verify.xml" value="0.2" />
+        <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/layout/fragment_menu.xml" value="0.2" />
+        <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/layout/fragment_timer.xml" value="0.25" />
+        <entry key="..\:/demo/.android/Player_Android/Demo/ui/src/main/res/layout/item_menu.xml" value="0.2342896174863388" />
       </map>
     </option>
   </component>

+ 3 - 4
build.gradle

@@ -30,11 +30,10 @@ task clean(type: Delete) {
 }
 
 ext {
-    compileSdkVersion = 31
-    buildToolsVersion = "29.0.2"
-    supportSdkVersion = "26.1.0"
+    compileSdkVersion = 32
+    buildToolsVersion = 32
     minSdkVersion = 21
-    targetSdkVersion = 31
+    targetSdkVersion = 32
     versionCode = 1
     versionName = "v1.0"
     liteavSdk = "com.tencent.liteav:LiteAVSDK_Player:latest.release"

+ 14 - 2
kit/build.gradle

@@ -1,4 +1,4 @@
-plugins{
+plugins {
     id 'com.android.library'
     id 'kotlin-android'
     id 'kotlin-kapt'
@@ -6,7 +6,6 @@ plugins{
 
 android {
     compileSdkVersion rootProject.ext.compileSdkVersion
-    buildToolsVersion rootProject.ext.buildToolsVersion
 
     defaultConfig {
         minSdkVersion rootProject.ext.minSdkVersion
@@ -16,6 +15,17 @@ android {
 
         testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
 
+        javaCompileOptions {
+            annotationProcessorOptions {
+                arguments += [
+                        "room.schemaLocation": "$projectDir/schemas".toString()
+                ]
+            }
+        }
+    }
+
+    buildFeatures {
+        viewBinding true
     }
 
     sourceSets {
@@ -47,6 +57,8 @@ dependencies {
     implementation 'androidx.exifinterface:exifinterface:1.3.3'
     api 'androidx.constraintlayout:constraintlayout:2.1.4'
 
+    implementation("org.greenrobot:eventbus:3.3.1")
+
     def room_version = "2.4.0"
     implementation "androidx.room:room-runtime:$room_version"
     kapt "androidx.room:room-compiler:$room_version"

+ 102 - 0
kit/schemas/com.tencent.liteav.demo.superplayer.database.PlayerDatabase/2.json

@@ -0,0 +1,102 @@
+{
+  "formatVersion": 1,
+  "database": {
+    "version": 2,
+    "identityHash": "4f3ffceb3ca527a53adae11af7ab34bf",
+    "entities": [
+      {
+        "tableName": "History",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `course_id` TEXT NOT NULL, `section_id` TEXT, `date` TEXT NOT NULL)",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "start",
+            "columnName": "start",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "end",
+            "columnName": "end",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "courseId",
+            "columnName": "course_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "sectionId",
+            "columnName": "section_id",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "date",
+            "columnName": "date",
+            "affinity": "TEXT",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": true
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "CountDown",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `course_id` TEXT NOT NULL, `type` INTEGER NOT NULL, `value` INTEGER NOT NULL)",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "courseId",
+            "columnName": "course_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "type",
+            "columnName": "type",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "value",
+            "columnName": "value",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": true
+        },
+        "indices": [],
+        "foreignKeys": []
+      }
+    ],
+    "views": [],
+    "setupQueries": [
+      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '4f3ffceb3ca527a53adae11af7ab34bf')"
+    ]
+  }
+}

+ 102 - 0
kit/schemas/com.tencent.liteav.demo.superplayer.database.PlayerDatabase/3.json

@@ -0,0 +1,102 @@
+{
+  "formatVersion": 1,
+  "database": {
+    "version": 3,
+    "identityHash": "1fbb5d3e0b17e0f275f418969aff1589",
+    "entities": [
+      {
+        "tableName": "History",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `course_id` TEXT NOT NULL, `section_id` TEXT, `date` TEXT)",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "start",
+            "columnName": "start",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "end",
+            "columnName": "end",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "courseId",
+            "columnName": "course_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "sectionId",
+            "columnName": "section_id",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "date",
+            "columnName": "date",
+            "affinity": "TEXT",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": true
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "CountDown",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `course_id` TEXT NOT NULL, `type` INTEGER NOT NULL, `value` INTEGER NOT NULL)",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "courseId",
+            "columnName": "course_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "type",
+            "columnName": "type",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "value",
+            "columnName": "value",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": true
+        },
+        "indices": [],
+        "foreignKeys": []
+      }
+    ],
+    "views": [],
+    "setupQueries": [
+      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1fbb5d3e0b17e0f275f418969aff1589')"
+    ]
+  }
+}

+ 102 - 0
kit/schemas/com.tencent.liteav.demo.superplayer.database.PlayerDatabase/4.json

@@ -0,0 +1,102 @@
+{
+  "formatVersion": 1,
+  "database": {
+    "version": 4,
+    "identityHash": "1fbb5d3e0b17e0f275f418969aff1589",
+    "entities": [
+      {
+        "tableName": "History",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `course_id` TEXT NOT NULL, `section_id` TEXT, `date` TEXT)",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "start",
+            "columnName": "start",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "end",
+            "columnName": "end",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "courseId",
+            "columnName": "course_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "sectionId",
+            "columnName": "section_id",
+            "affinity": "TEXT",
+            "notNull": false
+          },
+          {
+            "fieldPath": "date",
+            "columnName": "date",
+            "affinity": "TEXT",
+            "notNull": false
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": true
+        },
+        "indices": [],
+        "foreignKeys": []
+      },
+      {
+        "tableName": "CountDown",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `course_id` TEXT NOT NULL, `type` INTEGER NOT NULL, `value` INTEGER NOT NULL)",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "INTEGER",
+            "notNull": false
+          },
+          {
+            "fieldPath": "courseId",
+            "columnName": "course_id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "type",
+            "columnName": "type",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "value",
+            "columnName": "value",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "columnNames": [
+            "id"
+          ],
+          "autoGenerate": true
+        },
+        "indices": [],
+        "foreignKeys": []
+      }
+    ],
+    "views": [],
+    "setupQueries": [
+      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1fbb5d3e0b17e0f275f418969aff1589')"
+    ]
+  }
+}

+ 35 - 0
kit/src/main/java/com/tencent/liteav/demo/superplayer/ui/player/TimeOutPlayer.java

@@ -0,0 +1,35 @@
+package com.tencent.liteav.demo.superplayer.ui.player;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class TimeOutPlayer extends AbsPlayer implements View.OnClickListener{
+
+    public TimeOutPlayer(Context context) {
+        super(context);
+    }
+
+    public TimeOutPlayer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public TimeOutPlayer(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    public void onClick(View v) {
+
+    }
+
+    @Override
+    public void hide() {
+        super.hide();
+    }
+
+    @Override
+    public void show() {
+        super.show();
+    }
+}

+ 26 - 3
kit/src/main/kotlin/com/tencent/liteav/demo/superplayer/database/PlayerDatabase.kt

@@ -1,18 +1,22 @@
 package com.tencent.liteav.demo.superplayer.database
 
 import android.content.Context
+import android.util.Log
+import androidx.room.AutoMigration
 import androidx.room.Database
 import androidx.room.Room
 import androidx.room.RoomDatabase
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
 import com.tencent.liteav.demo.superplayer.database.dao.CountDownDao
 import com.tencent.liteav.demo.superplayer.database.dao.HistoryDao
 import com.tencent.liteav.demo.superplayer.database.entity.CountDown
 import com.tencent.liteav.demo.superplayer.database.entity.History
 
 @Database(
-    version = 1,
+    version = 4,
     entities = [History::class, CountDown::class],
-    exportSchema = false
+    exportSchema = true,
 )
 abstract class PlayerDatabase : RoomDatabase() {
     abstract fun historyDao(): HistoryDao
@@ -33,11 +37,30 @@ abstract class PlayerDatabase : RoomDatabase() {
                     context.applicationContext,
                     PlayerDatabase::class.java,
                     "player_database"
-                ).build()
+                ).addMigrations(migration1_2, migration2_3, migration3_4).build()
                 INSTANCE = instance
                 // return instance
                 instance
             }
         }
+
+        private val migration1_2 = object : Migration(1, 2) {
+            override fun migrate(database: SupportSQLiteDatabase) {
+                database.execSQL("ALTER TABLE `History` ADD COLUMN `section_id` TEXT;")
+            }
+        }
+
+        private val migration2_3 = object : Migration(2, 3) {
+            override fun migrate(database: SupportSQLiteDatabase) {
+                database.execSQL("ALTER TABLE `History` ADD COLUMN `date` TEXT;")
+            }
+        }
+
+        private val migration3_4 = object : Migration(3, 4) {
+            override fun migrate(database: SupportSQLiteDatabase) {
+                database.execSQL("DELETE FROM `History`;")
+                database.execSQL("DELETE FROM `CountDown`;")
+            }
+        }
     }
 }

+ 2 - 1
kit/src/main/kotlin/com/tencent/liteav/demo/superplayer/database/dao/HistoryDao.kt

@@ -2,6 +2,7 @@ package com.tencent.liteav.demo.superplayer.database.dao
 
 import androidx.room.Dao
 import androidx.room.Insert
+import androidx.room.OnConflictStrategy.REPLACE
 import androidx.room.Query
 import com.tencent.liteav.demo.superplayer.database.entity.History
 import kotlinx.coroutines.flow.Flow
@@ -11,7 +12,7 @@ public interface HistoryDao {
     @Query("SELECT * FROM history WHERE course_id = :courseId")
     fun getById(courseId: String): Flow<List<History>>
 
-    @Insert
+    @Insert(onConflict = REPLACE)
     fun insertHistory(history: History)
 
     @Insert

+ 15 - 0
kit/src/main/kotlin/com/tencent/liteav/demo/superplayer/database/entity/CountDown.kt

@@ -23,6 +23,21 @@ data class CountDown(
     @ColumnInfo(name = "value")
     val value: Int
 ) {
+
+    fun copy(
+        id: Long?,
+        courseId: String?,
+        type: Int?,
+        value: Int?
+    ): CountDown {
+        return CountDown(
+            id = id ?: this.id,
+            courseId = courseId ?: this.courseId,
+            type = type ?: this.type,
+            value = value ?: this.value
+        )
+    }
+
     companion object {
         @JvmStatic
         public val TYPE_EPISODE = 1;

+ 8 - 0
kit/src/main/kotlin/com/tencent/liteav/demo/superplayer/database/entity/History.kt

@@ -1,8 +1,10 @@
 package com.tencent.liteav.demo.superplayer.database.entity
 
 import androidx.room.ColumnInfo
+import androidx.room.ColumnInfo.TEXT
 import androidx.room.Entity
 import androidx.room.PrimaryKey
+import java.util.*
 
 @Entity
 data class History(
@@ -17,4 +19,10 @@ data class History(
 
     @ColumnInfo(name = "course_id")
     val courseId: String,
+
+    @ColumnInfo(name = "section_id")
+    val sectionId: String?,
+
+    @ColumnInfo(name = "date")
+    val date: String?,
 )

+ 6 - 3
ui/build.gradle

@@ -1,9 +1,10 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
+plugins{
+    id 'com.android.application'
+    id 'kotlin-android'
+}
 
 android {
     compileSdkVersion rootProject.ext.compileSdkVersion
-    buildToolsVersion rootProject.ext.buildToolsVersion
 
     defaultConfig {
         minSdkVersion rootProject.ext.minSdkVersion
@@ -45,6 +46,8 @@ dependencies {
 
     implementation 'androidx.activity:activity-ktx:1.5.1'
 
+    implementation("org.greenrobot:eventbus:3.3.1")
+
     implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
     implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
     implementation "androidx.lifecycle:lifecycle-common-java8:2.5.1"

+ 6 - 0
ui/src/main/AndroidManifest.xml

@@ -39,5 +39,11 @@
             android:screenOrientation="landscape"
             android:theme="@style/AppTheme.Dialog.Verify" />
 
+        <activity
+            android:name=".PlayerTimer"
+            android:launchMode="singleTop"
+            android:screenOrientation="landscape"
+            android:theme="@style/AppTheme.Dialog" />
+
     </application>
 </manifest>

+ 3 - 3
ui/src/main/java/com/tencent/liteav/demo/player/PlayerVerify.java

@@ -9,7 +9,7 @@ import android.view.View;
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AppCompatActivity;
 
-import com.tencent.liteav.demo.player.databinding.ActivityVerifyBinding;
+import com.tencent.liteav.demo.player.databinding.FragmentVerifyBinding;
 
 import java.util.Random;
 
@@ -20,14 +20,14 @@ public class PlayerVerify extends AppCompatActivity implements View.OnClickListe
         context.startActivity(intent);
     }
 
-    private ActivityVerifyBinding binding;
+    private FragmentVerifyBinding binding;
 
     private int a = 0, b = 0, c = 0;
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        binding = ActivityVerifyBinding.inflate(getLayoutInflater());
+        binding = FragmentVerifyBinding.inflate(getLayoutInflater());
         setContentView(binding.getRoot());
 
         Random random = new Random();

+ 38 - 0
ui/src/main/java/com/tencent/liteav/demo/player/util/PlayerTimerUtil.java

@@ -0,0 +1,38 @@
+package com.tencent.liteav.demo.player.util;
+
+import java.util.ArrayList;
+
+public class PlayerTimerUtil {
+    public interface Listener {
+        void onListen(int type, int value);
+    }
+
+    private ArrayList<Listener> listeners = new ArrayList<>();
+
+    private PlayerTimerUtil() {
+    }
+
+    private static final PlayerTimerUtil util = new PlayerTimerUtil();
+
+
+    public static PlayerTimerUtil getInstance() {
+        return util;
+    }
+
+    public static void addListener(Listener listener) {
+        getInstance().listeners.add(listener);
+    }
+
+    public static void removeListener(Listener listener) {
+        getInstance().listeners.remove(listener);
+    }
+
+    public static void setTimer(int type, int num) {
+        ArrayList<Listener> listeners = getInstance().listeners;
+        for (int i = 0; i < listeners.size(); i++) {
+            if (listeners.get(i) != null) {
+                listeners.get(i).onListen(type, num);
+            }
+        }
+    }
+}

+ 21 - 30
ui/src/main/kotlin/com/tencent/liteav/demo/player/PlayerActivity.kt

@@ -1,29 +1,29 @@
 package com.tencent.liteav.demo.player
 
 import android.content.Intent
-import android.view.View
-import com.tencent.liteav.demo.superplayer.SuperPlayerView.OnSuperPlayerViewCallback
-import com.tencent.liteav.demo.player.ui.PlayerListAdapter
-import com.tencent.liteav.demo.player.ViewInsets.ViewportMetrics
 import android.os.Bundle
 import android.util.Log
+import android.view.View
 import android.view.WindowManager
 import androidx.activity.viewModels
-import com.tencent.liteav.demo.superplayer.SuperPlayerDef
 import androidx.appcompat.app.AppCompatActivity
-import androidx.lifecycle.ViewModelProvider
-import androidx.lifecycle.viewmodel.viewModelFactory
 import androidx.recyclerview.widget.LinearLayoutManager
+import com.tencent.liteav.demo.player.ViewInsets.ViewportMetrics
+import com.tencent.liteav.demo.player.databinding.ActivityPlayerBinding
+import com.tencent.liteav.demo.player.ui.PlayerListAdapter
 import com.tencent.liteav.demo.player.ui.PlayerListDecoration
-import com.tencent.liteav.demo.superplayer.SuperPlayerGlobalConfig
-import com.tencent.rtmp.TXLiveConstants
-import com.tencent.liteav.demo.superplayer.SuperPlayerModel
 import com.tencent.liteav.demo.player.util.PlayerModelProvider
-import com.tencent.liteav.demo.player.databinding.ActivityPlayerBinding
 import com.tencent.liteav.demo.player.viewmodel.PlayerViewModel
 import com.tencent.liteav.demo.player.viewmodel.PlayerViewModelFactory
+import com.tencent.liteav.demo.superplayer.SuperPlayerDef
+import com.tencent.liteav.demo.superplayer.SuperPlayerGlobalConfig
+import com.tencent.liteav.demo.superplayer.SuperPlayerModel
+import com.tencent.liteav.demo.superplayer.SuperPlayerView.OnSuperPlayerViewCallback
 import com.tencent.liteav.demo.superplayer.database.PlayerDatabaseProvider
 import com.tencent.liteav.demo.superplayer.database.entity.History
+import com.tencent.rtmp.TXLiveConstants
+import java.text.SimpleDateFormat
+import java.util.*
 
 /**
  * Created by liyuejiao on 2018/7/3.
@@ -66,6 +66,7 @@ class PlayerActivity : AppCompatActivity(),
         initView()
         initData()
         updateList()
+        viewModel.loadConfig(this)
 
     }
 
@@ -108,24 +109,6 @@ class PlayerActivity : AppCompatActivity(),
         adjustSuperPlayerViewAndMaskHeight()
     }
 
-    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
-        super.onActivityResult(requestCode, resultCode, data)
-
-        when (requestCode) {
-            0 -> {
-                if (checkResultCode(resultCode)) {
-                }
-            }
-            else -> {
-
-            }
-        }
-    }
-
-    fun checkResultCode(resultCode: Int): Boolean {
-        return resultCode == RESULT_OK
-    }
-
     private fun initData() {
         initSuperVodGlobalSetting()
     }
@@ -237,7 +220,15 @@ class PlayerActivity : AppCompatActivity(),
 
     override fun onPlaying() {}
     override fun onPlayIndex(index: Int, model: SuperPlayerModel) {
-        viewModel.saveHistory(History(start = 0, end = 10, courseId = model.url))
+        viewModel.saveHistory(
+            History(
+                start = 0,
+                end = 10,
+                courseId = "0",
+                sectionId = model.title!!,
+                date = SimpleDateFormat("yyyy-MM-dd").format(Date())
+            )
+        )
         mVodPlayerListAdapter.setIndex(index)
     }
 

+ 73 - 62
ui/src/main/kotlin/com/tencent/liteav/demo/player/PlayerMenu.kt

@@ -1,75 +1,86 @@
-package com.tencent.liteav.demo.player;
+package com.tencent.liteav.demo.player
 
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.ImageView;
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.os.PersistableBundle
+import android.view.*
+import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.Fragment
+import com.tencent.liteav.demo.player.databinding.FragmentMenuBinding
 
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
+class PlayerMenu : AppCompatActivity(), View.OnClickListener {
+    private var _viewBinding: FragmentMenuBinding? = null
+    private val viewBinding get() = _viewBinding!!
 
-import com.tencent.liteav.demo.player.ui.MenuItemView;
+    private val imageBack get() = viewBinding.menuItemBack
+    private val imageShare get() = viewBinding.menuItemShare
+    private val imageFavorite get() = viewBinding.menuItemFavorite
+    private val imageCast get() = viewBinding.menuItemCast
+    private val imageTimer get() = viewBinding.menuItemTimer
 
-public class PlayerMenu extends AppCompatActivity implements View.OnClickListener {
-    private static final String KEY = "COURSE_ID";
+    private lateinit var courseId: String
 
-    public static void start(Context context, String courseId) {
-        Intent intent = new Intent(context, PlayerMenu.class);
-        intent.putExtra(KEY, courseId);
-        context.startActivity(intent);
-    }
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
 
-    private ImageView imageBack;
-    private MenuItemView imageShare;
-    private MenuItemView imageFavorite;
-    private MenuItemView imageCast;
-    private MenuItemView imageTimer;
-
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_menu);
-
-        getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
-
-        imageBack = findViewById(R.id.menu_item_back);
-        imageBack.setOnClickListener(this);
-
-        imageShare = findViewById(R.id.menu_item_share);
-        imageShare.setOnClickListener(this);
-        imageShare.setIcon(R.mipmap.item_share);
-        imageShare.setTitle("分享");
-
-        imageFavorite = findViewById(R.id.menu_item_favorite);
-        imageFavorite.setOnClickListener(this);
-        imageFavorite.setIcon(R.mipmap.item_favorite);
-        imageFavorite.setTitle("收藏");
-
-        imageCast = findViewById(R.id.menu_item_cast);
-        imageCast.setOnClickListener(this);
-        imageCast.setIcon(R.mipmap.item_cast);
-        imageCast.setTitle("投屏");
-
-        imageTimer = findViewById(R.id.menu_item_timer);
-        imageTimer.setOnClickListener(this);
-        imageTimer.setIcon(R.mipmap.item_timer);
-        imageTimer.setTitle("定时关闭");
-    }
+        _viewBinding = FragmentMenuBinding.inflate(layoutInflater)
+        setContentView(viewBinding.root)
+
+        window.setLayout(
+            WindowManager.LayoutParams.MATCH_PARENT,
+            WindowManager.LayoutParams.MATCH_PARENT
+        )
+
+        courseId = intent?.getStringExtra(KEY_COURSE_ID) ?: "0"
+
+        imageBack.setOnClickListener(this)
+
+        imageShare.setOnClickListener(this)
+        imageShare.setIcon(R.mipmap.item_share)
+        imageShare.setTitle("分享")
 
-    @Override
-    public void onClick(View v) {
-        if (v.getId() == R.id.menu_item_back) {
-            finish();
-        } else if (v.getId() == R.id.menu_item_cast) {
+        imageFavorite.setOnClickListener(this)
+        imageFavorite.setIcon(R.mipmap.item_favorite)
+        imageFavorite.setTitle("收藏")
 
-        } else if (v.getId() == R.id.menu_item_favorite) {
+        imageCast.setOnClickListener(this)
+        imageCast.setIcon(R.mipmap.item_cast)
+        imageCast.setTitle("投屏")
+
+        imageTimer.setOnClickListener(this)
+        imageTimer.setIcon(R.mipmap.item_timer)
+        imageTimer.setTitle("定时关闭")
+    }
+
+    override fun onClick(v: View) {
+        when (v.id) {
+            R.id.menu_item_back -> {
+                finish()
+            }
+            R.id.menu_item_cast -> {
+            }
+            R.id.menu_item_favorite -> {
+            }
+            R.id.menu_item_share -> {
+            }
+            R.id.menu_item_timer -> {
+                val intent = Intent(this, PlayerTimer::class.java)
+                startActivity(intent)
+                finish()
+            }
+        }
+    }
 
-        } else if (v.getId() == R.id.menu_item_share) {
 
-        } else if (v.getId() == R.id.menu_item_timer) {
+    companion object {
+        const val KEY_COURSE_ID = "course_id"
 
+        fun start(context: Context, courseId: String) {
+            val intent = Intent(context, PlayerMenu::class.java).apply {
+                putExtra(KEY_COURSE_ID, courseId)
+            }
+            context.startActivity(intent)
         }
     }
-}
+}

+ 71 - 0
ui/src/main/kotlin/com/tencent/liteav/demo/player/PlayerTimer.kt

@@ -0,0 +1,71 @@
+package com.tencent.liteav.demo.player
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import com.tencent.liteav.demo.player.databinding.FragmentTimerBinding
+import com.tencent.liteav.demo.player.util.PlayerTimerUtil
+
+class PlayerTimer : AppCompatActivity(), View.OnClickListener {
+    private var _viewBinding: FragmentTimerBinding? = null
+    private val viewBinding get() = _viewBinding!!
+
+    private val none get() = viewBinding.timerItemNone
+
+    private val ep1 get() = viewBinding.timerItemEpisodeOne
+    private val ep2 get() = viewBinding.timerItemEpisodeTwo
+    private val ep3 get() = viewBinding.timerItemEpisodeThree
+
+    private val dt10 get() = viewBinding.timerItemDuration10
+    private val dt20 get() = viewBinding.timerItemDuration20
+    private val dt30 get() = viewBinding.timerItemDuration30
+    private val custom get() = viewBinding.timerItemDurationCustom
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        _viewBinding = FragmentTimerBinding.inflate(layoutInflater)
+        setContentView(viewBinding.root)
+
+        window.setLayout(-1, -1)
+
+        none.setOnClickListener(this)
+        ep1.setOnClickListener(this)
+        ep2.setOnClickListener(this)
+        ep3.setOnClickListener(this)
+        dt10.setOnClickListener(this)
+        dt20.setOnClickListener(this)
+        dt30.setOnClickListener(this)
+        custom.setOnClickListener(this)
+    }
+
+    override fun onClick(v: View) {
+        when (v.id) {
+            none.id -> {
+                PlayerTimerUtil.setTimer(0, 0)
+            }
+            ep1.id -> {
+                PlayerTimerUtil.setTimer(1, 1)
+            }
+            ep2.id -> {
+                PlayerTimerUtil.setTimer(1, 2)
+            }
+            ep3.id -> {
+                PlayerTimerUtil.setTimer(1, 3)
+            }
+            dt10.id -> {
+                PlayerTimerUtil.setTimer(2, 10)
+            }
+            dt20.id -> {
+                PlayerTimerUtil.setTimer(2, 20)
+            }
+            dt30.id -> {
+                PlayerTimerUtil.setTimer(2, 30)
+            }
+            custom.id -> {
+                PlayerTimerUtil.setTimer(2, 100)
+            }
+        }
+
+        finish()
+    }
+}

+ 37 - 1
ui/src/main/kotlin/com/tencent/liteav/demo/player/viewmodel/PlayerViewModel.kt

@@ -1,10 +1,12 @@
 package com.tencent.liteav.demo.player.viewmodel
 
 import android.content.Context
+import android.util.Log
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
+import com.tencent.liteav.demo.player.util.PlayerTimerUtil
 import com.tencent.liteav.demo.superplayer.database.entity.CountDown
 import com.tencent.liteav.demo.superplayer.database.entity.History
 import com.tencent.liteav.demo.superplayer.database.repo.PlayerRepository
@@ -14,11 +16,18 @@ import kotlinx.coroutines.launch
 
 class PlayerViewModel(
     private val repository: PlayerRepository
-) : ViewModel() {
+) : ViewModel(), PlayerTimerUtil.Listener {
+
+    init {
+        PlayerTimerUtil.addListener(this)
+    }
+
     private var countDown: CountDown? = null
 
     private val countDownLiveData: MutableLiveData<Long> = MutableLiveData()
 
+    private val toastStr: MutableLiveData<String> = MutableLiveData()
+
     public fun loadConfig(context: Context) = viewModelScope.launch {
         repository.findHasCountDown("").first()?.let {
 
@@ -40,6 +49,33 @@ class PlayerViewModel(
 
         }
     }
+
+    override fun onListen(type: Int, value: Int) {
+        Log.d("PVM", "onListen: $type , $value")
+
+        if (type == 0) {
+
+        } else {
+
+            val countdown = countDown?.copy(
+                courseId = "",
+                type = type,
+                value = value
+            ) ?: CountDown(
+                courseId = "",
+                type = type,
+                value = value
+            )
+            setCountDown(countdown)
+            saveCountDown(countdown)
+        }
+    }
+
+    override fun onCleared() {
+        super.onCleared()
+        PlayerTimerUtil.removeListener(this)
+    }
+
 }
 
 class PlayerViewModelFactory(private val repository: PlayerRepository) : ViewModelProvider.Factory {

+ 12 - 0
ui/src/main/res/drawable/menu_timer_option_decoration.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <corners android:radius="20dp" />
+
+    <size
+        android:width="80dp"
+        android:height="40dp" />
+
+    <solid android:color="#FFFF9744" />
+</shape>

+ 0 - 0
ui/src/main/res/layout/activity_menu.xml → ui/src/main/res/layout/fragment_menu.xml


+ 171 - 0
ui/src/main/res/layout/fragment_timer.xml

@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_margin="0dp"
+    android:orientation="horizontal"
+    android:padding="0dp">
+
+    <View
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="268dp"
+        android:layout_height="match_parent"
+        android:background="@drawable/menu_background">
+
+        <ImageView
+            android:id="@+id/menu_item_back"
+            android:layout_width="27dp"
+            android:layout_height="80dp"
+            android:src="@mipmap/item_back"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:id="@+id/layout_title"
+            android:layout_width="wrap_content"
+            android:layout_height="28dp"
+            android:layout_marginTop="40dp"
+            android:text="定时停止播放"
+            android:textColor="#ff333333"
+            android:textSize="20sp"
+            app:layout_constraintLeft_toRightOf="@id/menu_item_back"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+
+        <TextView
+            android:id="@+id/timer_item_none"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="24dp"
+            android:background="@drawable/menu_timer_option_decoration"
+            android:gravity="center"
+            android:text="不开启"
+            android:textAlignment="center"
+            android:textColor="#ffffffff"
+            android:textSize="14sp"
+            app:layout_constraintLeft_toRightOf="@id/menu_item_back"
+            app:layout_constraintRight_toLeftOf="@id/timer_item_episode_one"
+            app:layout_constraintTop_toBottomOf="@id/layout_title" />
+
+
+        <TextView
+            android:id="@+id/timer_item_episode_one"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="24dp"
+            android:background="@drawable/menu_timer_option_decoration"
+            android:gravity="center"
+            android:text="播完本集"
+            android:textAlignment="center"
+            android:textColor="#ffffffff"
+            android:textSize="14sp"
+            app:layout_constraintLeft_toRightOf="@id/timer_item_none"
+            app:layout_constraintRight_toRightOf="@id/guideline"
+            app:layout_constraintTop_toBottomOf="@id/layout_title" />
+
+        <TextView
+            android:id="@+id/timer_item_episode_two"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="20dp"
+            android:background="@drawable/menu_timer_option_decoration"
+            android:gravity="center"
+            android:text="播完2集"
+            android:textAlignment="center"
+            android:textColor="#ffffffff"
+            android:textSize="14sp"
+            app:layout_constraintLeft_toRightOf="@id/menu_item_back"
+            app:layout_constraintRight_toLeftOf="@id/timer_item_episode_three"
+            app:layout_constraintTop_toBottomOf="@id/timer_item_none" />
+
+
+        <TextView
+            android:id="@+id/timer_item_episode_three"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="20dp"
+            android:background="@drawable/menu_timer_option_decoration"
+            android:gravity="center"
+            android:text="播完3集"
+            android:textColor="#ffffffff"
+            android:textSize="14sp"
+            app:layout_constraintLeft_toRightOf="@id/timer_item_episode_two"
+            app:layout_constraintRight_toRightOf="@id/guideline"
+            app:layout_constraintTop_toBottomOf="@id/timer_item_episode_one" />
+
+        <!-- 时长型定时 -->
+
+        <TextView
+            android:id="@+id/timer_item_duration_10"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="20dp"
+            android:background="@drawable/menu_timer_option_decoration"
+            android:gravity="center"
+            android:text="10分钟"
+            android:textColor="#ffffffff"
+            android:textSize="14sp"
+            app:layout_constraintLeft_toRightOf="@id/menu_item_back"
+            app:layout_constraintRight_toLeftOf="@id/timer_item_duration_20"
+            app:layout_constraintTop_toBottomOf="@id/timer_item_episode_two" />
+
+
+        <TextView
+            android:id="@+id/timer_item_duration_20"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="20dp"
+            android:background="@drawable/menu_timer_option_decoration"
+            android:gravity="center"
+            android:text="20分钟"
+            android:textColor="#ffffffff"
+            android:textSize="14sp"
+            app:layout_constraintLeft_toRightOf="@id/timer_item_duration_10"
+            app:layout_constraintRight_toRightOf="@id/guideline"
+            app:layout_constraintTop_toBottomOf="@id/timer_item_episode_three" />
+
+        <TextView
+            android:id="@+id/timer_item_duration_30"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="20dp"
+            android:background="@drawable/menu_timer_option_decoration"
+            android:gravity="center"
+            android:text="30分钟"
+            android:textColor="#ffffffff"
+            android:textSize="14sp"
+            app:layout_constraintLeft_toRightOf="@id/menu_item_back"
+            app:layout_constraintRight_toLeftOf="@id/timer_item_duration_custom"
+            app:layout_constraintTop_toBottomOf="@id/timer_item_duration_10" />
+
+
+        <TextView
+            android:id="@+id/timer_item_duration_custom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="20dp"
+            android:background="@drawable/menu_timer_option_decoration"
+            android:gravity="center"
+            android:text="自定义"
+            android:textColor="#ffffffff"
+            android:textSize="14sp"
+            app:layout_constraintLeft_toRightOf="@id/timer_item_duration_30"
+            app:layout_constraintRight_toRightOf="@id/guideline"
+            app:layout_constraintTop_toBottomOf="@id/timer_item_duration_20" />
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            app:layout_constraintGuide_end="17dp" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</LinearLayout>

+ 0 - 0
ui/src/main/res/layout/activity_verify.xml → ui/src/main/res/layout/fragment_verify.xml