Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
T
tx_player_fork
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蒋俊
tx_player_fork
Commits
cd5e26a0
提交
cd5e26a0
authored
7月 11, 2022
作者:
dokieyang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
1、update version to 1.0.3
2、add PIP for iOS
上级
613b1868
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
30 个修改的文件
包含
767 行增加
和
82 行删除
+767
-82
CHANGELOG.md
Flutter/CHANGELOG.md
+13
-1
build.gradle
Flutter/android/build.gradle
+1
-1
CommonUtil.java
...oid/src/main/java/com/tencent/vod/flutter/CommonUtil.java
+46
-0
FTXDownloadManager.java
...main/java/com/tencent/vod/flutter/FTXDownloadManager.java
+0
-0
FTXEvent.java
...droid/src/main/java/com/tencent/vod/flutter/FTXEvent.java
+11
-0
播放器组件.md
Flutter/docs/播放器组件.md
+25
-14
AndroidManifest.xml
Flutter/example/android/app/src/main/AndroidManifest.xml
+5
-0
project.pbxproj
Flutter/example/ios/Runner.xcodeproj/project.pbxproj
+39
-0
Info.plist
Flutter/example/ios/Runner/Info.plist
+6
-0
demo_txvodplayer.dart
Flutter/example/lib/demo_txvodplayer.dart
+5
-2
string_resource.dart
Flutter/example/lib/superplayer/common/string_resource.dart
+4
-0
demo_superplayer_lib.dart
Flutter/example/lib/superplayer/demo_superplayer_lib.dart
+1
-0
superplayer_widget.dart
Flutter/example/lib/superplayer/ui/superplayer_widget.dart
+35
-11
demo_video_slider_view.dart
Flutter/example/lib/ui/demo_video_slider_view.dart
+6
-0
CommonUtil.h
Flutter/ios/Classes/CommonUtil.h
+13
-0
CommonUtil.m
Flutter/ios/Classes/CommonUtil.m
+56
-0
FTXDownloadManager.m
Flutter/ios/Classes/FTXDownloadManager.m
+145
-1
FTXEvent.h
Flutter/ios/Classes/FTXEvent.h
+36
-3
FTXVodPlayer.h
Flutter/ios/Classes/FTXVodPlayer.h
+18
-0
FTXVodPlayer.m
Flutter/ios/Classes/FTXVodPlayer.m
+0
-0
SuperPlayerPlugin.m
Flutter/ios/Classes/SuperPlayerPlugin.m
+38
-2
pictureInpicture_en.jpg
Flutter/ios/Classes/TXResource/pictureInpicture_en.jpg
+0
-0
pictureInpicture_zh.jpg
Flutter/ios/Classes/TXResource/pictureInpicture_zh.jpg
+0
-0
super_player.podspec
Flutter/ios/super_player.podspec
+2
-1
common_utils.dart
Flutter/lib/Core/tools/common_utils.dart
+32
-0
txplayer_define.dart
Flutter/lib/Core/txplayer_define.dart
+119
-15
txvoddownload_controller.dart
Flutter/lib/Core/txvoddownload_controller.dart
+105
-27
super_player.dart
Flutter/lib/super_player.dart
+4
-2
pubspec.yaml
Flutter/pubspec.yaml
+1
-1
super_player_test.dart
Flutter/test/super_player_test.dart
+1
-1
没有找到文件。
Flutter/CHANGELOG.md
浏览文件 @
cd5e26a0
#### Version: 1.0.
2
当前最新版本
#### Version: 1.0.
3
当前最新版本
##### 分支描述:
...
...
@@ -6,8 +6,20 @@ main 分支:Android & iOS 端集成TXLiteAVSDK_Player lastest版本
Professional 分支:Android & iOS 端集成TXLiteAVSDK_Professional lastest版本
版本特性:
-
iOS 端新增画中画(PIP) 功能
#### Version: 1.0.2 2022.07.05
##### 版本特性:
-
Android 端新增画中画(PIP) 功能
-
播放器组件(superplayer)用Dart重写,方便自定义集成
-
修复通过appId 、fileId和 psign 播放失败问题
-
set Android TXLiteAVSDK_Professional to 10.2.0.11131,tag:release_player_v1.0.2
-
set iOS TXLiteAVSDK_Professional to 10.2.11418, tag:release_pro_v1.0.2
Flutter/android/build.gradle
浏览文件 @
cd5e26a0
group
'com.tencent.vod.flutter'
apply
from:
'config.gradle'
version
'1.0.
2
'
version
'1.0.
3
'
buildscript
{
repositories
{
...
...
Flutter/android/src/main/java/com/tencent/vod/flutter/CommonUtil.java
浏览文件 @
cd5e26a0
// Copyright (c) 2022 Tencent. All rights reserved.
package
com
.
tencent
.
vod
.
flutter
;
import
android.os.Bundle
;
import
com.tencent.rtmp.downloader.TXVodDownloadDataSource
;
import
com.tencent.rtmp.downloader.TXVodDownloadMediaInfo
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Set
;
/**
* 通用工具类
*/
public
class
CommonUtil
{
static
final
Map
<
Integer
,
Integer
>
DOWNLOAD_STATE_MAP
=
new
HashMap
<
Integer
,
Integer
>()
{{
put
(
TXVodDownloadMediaInfo
.
STATE_INIT
,
FTXEvent
.
EVENT_DOWNLOAD_START
);
put
(
TXVodDownloadMediaInfo
.
STATE_START
,
FTXEvent
.
EVENT_DOWNLOAD_PROGRESS
);
put
(
TXVodDownloadMediaInfo
.
STATE_FINISH
,
FTXEvent
.
EVENT_DOWNLOAD_FINISH
);
put
(
TXVodDownloadMediaInfo
.
STATE_STOP
,
FTXEvent
.
EVENT_DOWNLOAD_STOP
);
put
(
TXVodDownloadMediaInfo
.
STATE_ERROR
,
FTXEvent
.
EVENT_DOWNLOAD_ERROR
);
}};
public
static
Map
<
String
,
Object
>
getParams
(
int
event
,
Bundle
bundle
)
{
Map
<
String
,
Object
>
param
=
new
HashMap
<>();
if
(
event
!=
0
)
{
...
...
@@ -24,4 +39,35 @@ public class CommonUtil {
return
param
;
}
public
static
int
getCacheVideoQuality
(
Integer
width
,
Integer
height
)
{
if
(
width
==
null
||
height
==
null
)
{
return
TXVodDownloadDataSource
.
QUALITY_FLU
;
}
int
minValue
=
Math
.
min
(
width
,
height
);
int
cacheQualityIndex
;
if
(
minValue
==
240
||
minValue
==
180
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_FLU
;
}
else
if
(
minValue
==
480
||
minValue
==
360
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_SD
;
}
else
if
(
minValue
==
540
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_SD
;
}
else
if
(
minValue
==
720
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_HD
;
}
else
if
(
minValue
==
1080
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_FHD
;
}
else
if
(
minValue
==
1440
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_2K
;
}
else
if
(
minValue
==
2160
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_4K
;
}
else
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_UNK
;
}
return
cacheQualityIndex
;
}
public
static
int
getDownloadEventByState
(
int
mediaInfoDownloadState
)
{
Integer
event
=
DOWNLOAD_STATE_MAP
.
get
(
mediaInfoDownloadState
);
return
null
!=
event
?
event
:
FTXEvent
.
EVENT_DOWNLOAD_ERROR
;
}
}
Flutter/android/src/main/java/com/tencent/vod/flutter/FTXDownloadManager.java
浏览文件 @
cd5e26a0
差异被折叠。
点击展开。
Flutter/android/src/main/java/com/tencent/vod/flutter/FTXEvent.java
浏览文件 @
cd5e26a0
...
...
@@ -24,6 +24,17 @@ public class FTXEvent {
// 视频预下载出错
public
static
final
int
EVENT_PREDOWNLOAD_ON_ERROR
=
201
;
// 视频下载开始
public
static
final
int
EVENT_DOWNLOAD_START
=
301
;
// 视频下载进度
public
static
final
int
EVENT_DOWNLOAD_PROGRESS
=
302
;
// 视频下载停止
public
static
final
int
EVENT_DOWNLOAD_STOP
=
303
;
// 视频下载完成
public
static
final
int
EVENT_DOWNLOAD_FINISH
=
304
;
// 视频下载错误
public
static
final
int
EVENT_DOWNLOAD_ERROR
=
305
;
public
static
final
int
NO_ERROR
=
0
;
/**
* pip 事件
...
...
Flutter/docs/播放器组件.md
浏览文件 @
cd5e26a0
...
...
@@ -564,23 +564,24 @@ loader.getVideoData(model, (resultModel) {
#### 画中画模式的使用
##### android平台
1.
安卓平台配置
1.
添加原生
配置
1.
1 在自己项目的android包下,找到 AndroidManifest.xml ,在项目入口activity节点下,增加如下
配置
在自己项目的android包下,找到 AndroidManifest.xml ,在项目入口activity节点下,增加如下配置
```xml
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
```
```
xml
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
```
在自己项目android包下,找到build.gralde,确认 compileSdkVersion 和 targetSdkVersion 的版本为31或以上
在自己项目android包下,找到build.gralde,确认 compileSdkVersion 和 targetSdkVersion 的版本为31或以上
1.
2 继承pip activity
2.
继承pip activity
将github项目中example/android 中的 FTXFlutterPipActivity.java 复制到自己入口 Activity 的同目录下,并将自己 Activity 的父类修改为该类。
将github项目中example/android 中的 FTXFlutterPipActivity.java 复制到自己入口 Activity 的同目录下,并将自己 Activity 的父类修改为该类。
2.
iOS平台配置
2.
1 在自己项目的target下选择Signing & Capabilities 添加Background Modes,勾选Audio,AirPlay,and Picture in Picture
3.
复制superPlayer示例代码
...
...
@@ -600,7 +601,11 @@ SuperPlayerPlugin.instance.onExtraEventBroadcast.listen((event) {
// enter pip mode
}
else
if
(
eventCode
==
TXVodPlayEvent
.
EVENT_PIP_MODE_ALREADY_ENTER
)
{
// already enter pip mode
}
}
else
if
(
eventCode
==
TXVodPlayEvent
.
EVENT_IOS_PIP_MODE_WILL_EXIT
)
{
// will exit pip mode
}
else
if
(
eventCode
==
TXVodPlayEvent
.
EVENT_IOS_PIP_MODE_RESTORE_UI
)
{
// restore UI only support iOS
}
});
```
...
...
@@ -614,6 +619,14 @@ SuperPlayerPlugin.instance.onExtraEventBroadcast.listen((event) {
| ERROR_PIP_LOWER_VERSION | -101 | android版本过低,不支持画中画模式 |
| ERROR_PIP_DENIED_PERMISSION | -102 | 画中画模式权限未打开,或者当前设备不支持画中画 |
| ERROR_PIP_ACTIVITY_DESTROYED | -103 | 当前界面已经销毁 |
| ERROR_IOS_PIP_DEVICE_NOT_SUPPORT | -104 | 设备或系统版本不支持(iPad iOS9+ 才支持PIP) | only support iOS
| ERROR_IOS_PIP_PLAYER_NOT_SUPPORT | -105 | 播放器不支持 | only support iOS
| ERROR_IOS_PIP_VIDEO_NOT_SUPPORT | -106 | 视频不支持 | only support iOS
| ERROR_IOS_PIP_IS_NOT_POSSIBLE | -107 | PIP控制器不可用 | only support iOS
| ERROR_IOS_PIP_FROM_SYSTEM | -108 | PIP控制器报错 | only support iOS
| ERROR_IOS_PIP_PLAYER_NOT_EXIST | -109 | 播放器对象不存在 | only support iOS
| ERROR_IOS_PIP_IS_RUNNING | -110 | PIP功能已经运行 | only support iOS
| ERROR_IOS_PIP_NOT_RUNNING | -111 | PIP功能没有启动 | only support iOS
6.
判断当前设备是否支持画中画
...
...
@@ -628,5 +641,3 @@ if(result == TXVodPlayEvent.NO_ERROR) {
result的返回结果的含义和画中画模式错误码一致
Flutter/example/android/app/src/main/AndroidManifest.xml
浏览文件 @
cd5e26a0
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
package=
"com.example.super_player_example"
>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<application
android:label=
"super_player_example"
android:icon=
"@mipmap/ic_launcher"
android:requestLegacyExternalStorage=
"true"
tools:replace=
"android:label"
>
<activity
android:name=
".MainActivity"
...
...
Flutter/example/ios/Runner.xcodeproj/project.pbxproj
浏览文件 @
cd5e26a0
...
...
@@ -149,6 +149,8 @@
97C146EC1CF9000F007C117D
/* Resources */
,
9705A1C41CF9048500538489
/* Embed Frameworks */
,
3B06AD1E1E4923F5004D2608
/* Thin Binary */
,
A040688731A45DDEFDE947A6
/* [CP] Embed Pods Frameworks */
,
07B0A88CAEDB5F32ECB22F06
/* [CP] Copy Pods Resources */
,
);
buildRules
=
(
);
...
...
@@ -206,6 +208,23 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
07B0A88CAEDB5F32ECB22F06
/* [CP] Copy Pods Resources */
=
{
isa
=
PBXShellScriptBuildPhase
;
buildActionMask
=
2147483647
;
files
=
(
);
inputFileListPaths
=
(
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist"
,
);
name
=
"[CP] Copy Pods Resources"
;
outputFileListPaths
=
(
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist"
,
);
runOnlyForDeploymentPostprocessing
=
0
;
shellPath
=
/bin/sh
;
shellScript
=
"\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"
;
showEnvVarsInLog
=
0
;
};
2758E5B40301380ECA281800
/* [CP] Check Pods Manifest.lock */
=
{
isa
=
PBXShellScriptBuildPhase
;
buildActionMask
=
2147483647
;
...
...
@@ -256,6 +275,23 @@
shellPath
=
/bin/sh
;
shellScript
=
"/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"
;
};
A040688731A45DDEFDE947A6
/* [CP] Embed Pods Frameworks */
=
{
isa
=
PBXShellScriptBuildPhase
;
buildActionMask
=
2147483647
;
files
=
(
);
inputFileListPaths
=
(
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist"
,
);
name
=
"[CP] Embed Pods Frameworks"
;
outputFileListPaths
=
(
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist"
,
);
runOnlyForDeploymentPostprocessing
=
0
;
shellPath
=
/bin/sh
;
shellScript
=
"\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"
;
showEnvVarsInLog
=
0
;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
...
...
@@ -295,6 +331,7 @@
isa
=
XCBuildConfiguration
;
buildSettings
=
{
ALWAYS_SEARCH_USER_PATHS
=
NO
;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED
=
YES
;
CLANG_ANALYZER_NONNULL
=
YES
;
CLANG_CXX_LANGUAGE_STANDARD
=
"gnu++0x"
;
CLANG_CXX_LIBRARY
=
"libc++"
;
...
...
@@ -367,6 +404,7 @@
isa
=
XCBuildConfiguration
;
buildSettings
=
{
ALWAYS_SEARCH_USER_PATHS
=
NO
;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED
=
YES
;
CLANG_ANALYZER_NONNULL
=
YES
;
CLANG_CXX_LANGUAGE_STANDARD
=
"gnu++0x"
;
CLANG_CXX_LIBRARY
=
"libc++"
;
...
...
@@ -422,6 +460,7 @@
isa
=
XCBuildConfiguration
;
buildSettings
=
{
ALWAYS_SEARCH_USER_PATHS
=
NO
;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED
=
YES
;
CLANG_ANALYZER_NONNULL
=
YES
;
CLANG_CXX_LANGUAGE_STANDARD
=
"gnu++0x"
;
CLANG_CXX_LIBRARY
=
"libc++"
;
...
...
Flutter/example/ios/Runner/Info.plist
浏览文件 @
cd5e26a0
...
...
@@ -27,6 +27,10 @@
<
k
e
y
>
NSAllowsArbitraryLoads
<
/k
e
y
>
<
tru
e
/
>
<
/
d
i
c
t
>
<
k
e
y
>
UIBackgroundModes
<
/k
e
y
>
<
a
rr
a
y
>
<
string
>
audio
<
/string
>
<
/
a
rr
a
y
>
<
k
e
y
>
UILaunchStoryboardName
<
/k
e
y
>
<
string
>
LaunchScreen
<
/string
>
<
k
e
y
>
UIMainStoryboardFile
<
/k
e
y
>
...
...
@@ -48,5 +52,7 @@
<
fa
ls
e
/
>
<
k
e
y
>
io.flutter.embedded_views_preview
<
/k
e
y
>
<
tru
e
/
>
<
k
e
y
>
CADisableMinimumFrameDurationOnPhone
<
/k
e
y
>
<
tru
e
/
>
<
/
d
i
c
t
>
<
/plist
>
Flutter/example/lib/demo_txvodplayer.dart
浏览文件 @
cd5e26a0
...
...
@@ -56,8 +56,11 @@ class _DemoTXVodlayerState extends State<DemoTXVodPlayer>
}
else
if
(
event
[
"event"
]
==
TXVodPlayEvent
.
PLAY_EVT_PLAY_PROGRESS
)
{
_currentProgress
=
event
[
TXVodPlayEvent
.
EVT_PLAY_PROGRESS
].
toDouble
();
double
videoDuration
=
event
[
TXVodPlayEvent
.
EVT_PLAY_DURATION
].
toDouble
();
// 总播放时长,转换后的单位 秒
progressSliderKey
.
currentState
?.
updatePorgess
(
_currentProgress
/
videoDuration
,
videoDuration
);
if
(
videoDuration
==
0.0
)
{
progressSliderKey
.
currentState
?.
updatePorgess
(
0.0
,
0.0
);
}
else
{
progressSliderKey
.
currentState
?.
updatePorgess
(
_currentProgress
/
videoDuration
,
videoDuration
);
}
}
else
if
(
event
[
"event"
]
==
TXVodPlayEvent
.
PLAY_EVT_GET_PLAYINFO_SUCC
)
{
String
?
playUrl
=
event
[
TXVodPlayEvent
.
EVT_PLAY_URL
]?.
toString
();
}
...
...
Flutter/example/lib/superplayer/common/string_resource.dart
浏览文件 @
cd5e26a0
...
...
@@ -16,4 +16,8 @@ class StringResource {
static
const
BRIGHTNESS_LABEL
=
"亮度"
;
static
const
MULITIPE_SPEED_PLAY_LABEL
=
"多倍速播放"
;
static
const
HARDWARE_ACCE_LABEL
=
"硬件加速"
;
static
const
OPEN_PIP
=
"正在开启画中画"
;
static
const
CLOSE_PIP
=
"正在关闭画中画"
;
static
const
ERROR_PIP
=
"画中画开启失败"
;
}
Flutter/example/lib/superplayer/demo_superplayer_lib.dart
浏览文件 @
cd5e26a0
...
...
@@ -11,6 +11,7 @@ import 'package:auto_orientation/auto_orientation.dart';
import
'package:flutter/material.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_easyloading/flutter_easyloading.dart'
;
import
'package:super_player/super_player.dart'
;
part
'superplayer_observer.dart'
;
...
...
Flutter/example/lib/superplayer/ui/superplayer_widget.dart
浏览文件 @
cd5e26a0
...
...
@@ -90,27 +90,51 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
}
});
// only register listen once
_pipSubscription
=
SuperPlayerPlugin
.
instance
.
onExtraEventBroadcast
.
listen
((
event
)
{
_pipSubscription
=
SuperPlayerPlugin
.
instance
.
onExtraEventBroadcast
.
listen
((
event
)
{
int
eventCode
=
event
[
"event"
];
if
(
eventCode
==
TXVodPlayEvent
.
EVENT_PIP_MODE_ALREADY_EXIT
)
{
// exit floatingMode
Navigator
.
of
(
context
).
pop
();
_isFloatingMode
=
false
;
if
(
_isPlaying
)
{
// pause play when exit PIP, prevent user just close PIP, but not back to app
_playController
.
_vodPlayerController
?.
pause
();
if
(
Platform
.
isAndroid
)
{
Navigator
.
of
(
context
).
pop
();
if
(
_isPlaying
)
{
// pause play when exit PIP, prevent user just close PIP, but not back to app
_playController
.
_vodPlayerController
?.
pause
();
}
}
else
if
(
Platform
.
isIOS
)
{
EasyLoading
.
dismiss
();
}
_isFloatingMode
=
false
;
}
else
if
(
eventCode
==
TXVodPlayEvent
.
EVENT_PIP_MODE_REQUEST_START
)
{
// EVENT_PIP_MODE_ALREADY_ENTER 的状态变化有滞后性,进入PIP之后才会通知,这里需要监听EVENT_PIP_MODE_REQUEST_START,
// 在即将进入PIP模式下就要开始进行PIP模式的UI准备
// enter floatingMode
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
{
return
SuperPlayerFloatView
(
_playController
,
_aspectRatio
);
}));
if
(
Platform
.
isAndroid
)
{
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
{
return
SuperPlayerFloatView
(
_playController
,
_aspectRatio
);
}));
}
else
if
(
Platform
.
isIOS
)
{
EasyLoading
.
showToast
(
StringResource
.
OPEN_PIP
);
}
_isFloatingMode
=
true
;
}
else
if
(
eventCode
==
TXVodPlayEvent
.
EVENT_PIP_MODE_ALREADY_ENTER
)
{
if
(
Platform
.
isIOS
)
{
EasyLoading
.
dismiss
();
}
}
else
if
(
eventCode
==
TXVodPlayEvent
.
EVENT_IOS_PIP_MODE_WILL_EXIT
)
{
if
(
Platform
.
isIOS
)
{
EasyLoading
.
showToast
(
StringResource
.
CLOSE_PIP
);
}
}
else
{
if
(
Platform
.
isIOS
)
{
EasyLoading
.
showToast
(
StringResource
.
ERROR_PIP
);
}
_isFloatingMode
=
false
;
print
(
'
$eventCode
'
);
}
});
_volumeSubscription
=
SuperPlayerPlugin
.
instance
.
onEventBroadcast
.
listen
((
event
)
{
_volumeSubscription
=
SuperPlayerPlugin
.
instance
.
onEventBroadcast
.
listen
((
event
)
{
int
eventCode
=
event
[
"event"
];
if
(
_isFloatingMode
&&
_isPlaying
)
{
if
(
eventCode
==
TXVodPlayEvent
.
EVENT_AUDIO_FOCUS_PAUSE
)
{
...
...
@@ -327,7 +351,7 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
Widget
_getPipEnterView
()
{
return
Visibility
(
visible:
_isShowControlView
&&
!
_isFullScreen
&&
Platform
.
isAndroid
,
// PIP 暂时只支持Android
visible:
_isShowControlView
&&
!
_isFullScreen
,
child:
Positioned
(
right:
10
,
top:
0
,
...
...
Flutter/example/lib/ui/demo_video_slider_view.dart
浏览文件 @
cd5e26a0
...
...
@@ -67,6 +67,12 @@ class VideoSliderState extends State<VideoSliderView> {
void
updatePorgess
(
double
progress
,
double
totalDuration
)
{
if
(!
isSliding
)
{
setState
(()
{
if
(
progress
>
1.0
)
{
progress
=
1.0
;
}
if
(
progress
<
0
)
{
progress
=
0
;
}
_currentProgress
=
progress
;
_videoDuration
=
totalDuration
;
});
...
...
Flutter/ios/Classes/CommonUtil.h
0 → 100644
浏览文件 @
cd5e26a0
// Copyright (c) 2022 Tencent. All rights reserved.
#import "TXVodDownloadManager.h"
#import <Foundation/Foundation.h>
#import "FTXEvent.h"
@interface
CommonUtil
:
NSObject
+
(
int
)
getCacheVideoQuality
:(
int
)
width
height
:(
int
)
pHeight
;
+
(
int
)
getDownloadEventByState
:(
int
)
downloadState
;
@end
Flutter/ios/Classes/CommonUtil.m
0 → 100644
浏览文件 @
cd5e26a0
// Copyright (c) 2022 Tencent. All rights reserved.
#import "CommonUtil.h"
@implementation
CommonUtil
+
(
int
)
getCacheVideoQuality
:(
int
)
width
height
:(
int
)
pHeight
{
int
minValue
=
MIN
(
width
,
pHeight
);
int
cacheQualityIndex
;
if
(
minValue
==
240
||
minValue
==
180
)
{
cacheQualityIndex
=
TXVodQualityFLU
;
}
else
if
(
minValue
==
480
||
minValue
==
360
)
{
cacheQualityIndex
=
TXVodQualitySD
;
}
else
if
(
minValue
==
540
)
{
cacheQualityIndex
=
TXVodQualitySD
;
}
else
if
(
minValue
==
720
)
{
cacheQualityIndex
=
TXVodQualityHD
;
}
else
if
(
minValue
==
1080
)
{
cacheQualityIndex
=
TXVodQualityFHD
;
}
else
if
(
minValue
==
1440
)
{
cacheQualityIndex
=
TXVodQuality2K
;
}
else
if
(
minValue
==
2160
)
{
cacheQualityIndex
=
TXVodQuality4K
;
}
else
{
cacheQualityIndex
=
TXVodQualityFLU
;
}
return
cacheQualityIndex
;
}
+
(
int
)
getDownloadEventByState
:(
int
)
downloadState
{
int
result
;
switch
(
downloadState
)
{
case
TXVodDownloadMediaInfoStateInit
:
result
=
EVENT_DOWNLOAD_START
;
break
;
case
TXVodDownloadMediaInfoStateStart
:
result
=
EVENT_DOWNLOAD_PROGRESS
;
break
;
case
TXVodDownloadMediaInfoStateStop
:
result
=
EVENT_DOWNLOAD_STOP
;
break
;
case
TXVodDownloadMediaInfoStateError
:
result
=
EVENT_DOWNLOAD_ERROR
;
break
;
case
TXVodDownloadMediaInfoStateFinish
:
result
=
EVENT_DOWNLOAD_FINISH
;
break
;
default:
result
=
EVENT_DOWNLOAD_ERROR
;
break
;
}
return
result
;
}
@end
Flutter/ios/Classes/FTXDownloadManager.m
浏览文件 @
cd5e26a0
...
...
@@ -5,9 +5,11 @@
#import "FTXEvent.h"
#import "FTXDownloadManager.h"
#import "TXVodPreloadManager.h"
#import "TXVodDownloadManager.h"
#import "FTXEvent.h"
#import "CommonUtil.h"
@interface
FTXDownloadManager
()
<
FlutterStreamHandler
,
TXVodPreloadManagerDelegate
>
@interface
FTXDownloadManager
()
<
FlutterStreamHandler
,
TXVodPreloadManagerDelegate
,
TXVodDownloadDelegate
>
@end
...
...
@@ -30,6 +32,11 @@
_eventChannel
=
[
FlutterEventChannel
eventChannelWithName
:
@"cloud.tencent.com/txvodplayer/download/event"
binaryMessenger
:[
registrar
messenger
]];
[
_eventChannel
setStreamHandler
:
self
];
NSLog
(
@"dokie initWithRegistrar"
);
[[
TXVodDownloadManager
shareInstance
]
setDelegate
:
self
];
// 设置下载存储路径
NSString
*
cachesDir
=
[
NSSearchPathForDirectoriesInDomains
(
NSCachesDirectory
,
NSUserDomainMask
,
YES
)
firstObject
];
NSString
*
path
=
[
NSString
stringWithFormat
:
@"%@/videoCache"
,
cachesDir
];
[[
TXVodDownloadManager
shareInstance
]
setDownloadPath
:
path
];
}
return
self
;
}
...
...
@@ -61,6 +68,53 @@
int
taskId
=
[
args
[
@"taskId"
]
intValue
];
[[
TXVodPreloadManager
sharedManager
]
stopPreload
:
taskId
];
result
(
nil
);
}
else
if
([
@"startDownload"
isEqualToString
:
call
.
method
])
{
NSNumber
*
quality
=
args
[
@"quality"
];
NSString
*
videoUrl
=
args
[
@"url"
];
NSNumber
*
appIdNum
=
args
[
@"appId"
];
NSString
*
fileId
=
args
[
@"fileId"
];
NSString
*
pSign
=
args
[
@"pSign"
];
NSString
*
userName
=
args
[
@"userName"
];
if
([
NSNull
null
]
!=
(
NSNull
*
)
videoUrl
)
{
[[
TXVodDownloadManager
shareInstance
]
startDownload
:
userName
url
:
videoUrl
];
}
else
if
([
NSNull
null
]
!=
(
NSNull
*
)
appIdNum
&&
[
NSNull
null
]
!=
(
NSNull
*
)
fileId
)
{
TXVodDownloadDataSource
*
dataSource
=
[[
TXVodDownloadDataSource
alloc
]
init
];
dataSource
.
appId
=
[
appIdNum
intValue
];
dataSource
.
fileId
=
fileId
;
dataSource
.
userName
=
userName
;
dataSource
.
quality
=
[
self
optQuality
:
quality
];
if
([
NSNull
null
]
!=
(
NSNull
*
)
pSign
)
{
dataSource
.
pSign
=
pSign
;
}
[[
TXVodDownloadManager
shareInstance
]
startDownload
:
dataSource
];
}
result
(
nil
);
}
else
if
([
@"stopDownload"
isEqualToString
:
call
.
method
])
{
NSNumber
*
quality
=
args
[
@"quality"
];
NSString
*
videoUrl
=
args
[
@"url"
];
NSNumber
*
appIdNum
=
args
[
@"appId"
];
NSString
*
fileId
=
args
[
@"fileId"
];
TXVodDownloadMediaInfo
*
mediaInfo
=
[
self
parseMediaInfoFromInfo
:
quality
url
:
videoUrl
appId
:
appIdNum
fileId
:
fileId
];
[[
TXVodDownloadManager
shareInstance
]
stopDownload
:
mediaInfo
];
result
(
nil
);
}
else
if
([
@"setDownloadHeaders"
isEqualToString
:
call
.
method
])
{
[[
TXVodDownloadManager
shareInstance
]
setHeaders
:
args
];
result
(
nil
);
}
else
if
([
@"getDownloadList"
isEqualToString
:
call
.
method
])
{
NSArray
<
TXVodDownloadMediaInfo
*>
*
mediaInfoList
=
[[
TXVodDownloadManager
shareInstance
]
getDownloadMediaInfoList
];
NSMutableArray
<
NSDictionary
*>
*
resultDicArray
=
[[
NSMutableArray
alloc
]
init
];
for
(
int
i
=
0
;
i
<
mediaInfoList
.
count
;
i
++
)
{
[
resultDicArray
addObject
:[
self
buildMapFromDownloadMediaInfo
:
mediaInfoList
[
i
]]];
}
result
(
resultDicArray
);
}
else
if
([
@"getDownloadInfo"
isEqualToString
:
call
.
method
])
{
NSNumber
*
quality
=
args
[
@"quality"
];
NSString
*
videoUrl
=
args
[
@"url"
];
NSNumber
*
appIdNum
=
args
[
@"appId"
];
NSString
*
fileId
=
args
[
@"fileId"
];
TXVodDownloadMediaInfo
*
mediaInfo
=
[
self
parseMediaInfoFromInfo
:
quality
url
:
videoUrl
appId
:
appIdNum
fileId
:
fileId
];
NSDictionary
*
resultDic
=
[
self
buildMapFromDownloadMediaInfo
:
mediaInfo
];
result
(
resultDic
);
}
}
...
...
@@ -120,4 +174,94 @@
[
_eventSink
success
:[
FTXDownloadManager
getParamsWithEvent
:
EVENT_PREDOWNLOAD_ON_ERROR
withParams
:
dict
]];
}
#pragma mark - TXDownloadManager
-
(
int
)
optQuality
:
(
NSNumber
*
)
quality
{
return
([
NSNull
null
]
==
(
NSNull
*
)
quality
||
nil
==
quality
)
?
TXVodQualityFLU
:
[
quality
intValue
];
}
-
(
TXVodDownloadMediaInfo
*
)
parseMediaInfoFromInfo
:
(
NSNumber
*
)
quality
url
:
(
NSString
*
)
videoUrl
appId
:
(
NSNumber
*
)
pAppId
fileId
:
(
NSString
*
)
pFileId
{
TXVodDownloadMediaInfo
*
mediaInfo
=
nil
;
if
(
nil
!=
videoUrl
&&
[
NSNull
null
]
!=
(
NSNull
*
)
videoUrl
)
{
TXVodDownloadMediaInfo
*
urlInfo
=
[[
TXVodDownloadMediaInfo
alloc
]
init
];
urlInfo
.
url
=
videoUrl
;
mediaInfo
=
[[
TXVodDownloadManager
shareInstance
]
getDownloadMediaInfo
:
urlInfo
];
}
else
if
([
NSNull
null
]
!=
(
NSNull
*
)
pFileId
&&
[
NSNull
null
]
!=
(
NSNull
*
)
pAppId
)
{
TXVodDownloadMediaInfo
*
fileIdInfo
=
[[
TXVodDownloadMediaInfo
alloc
]
init
];
TXVodDownloadDataSource
*
dataSource
=
[[
TXVodDownloadDataSource
alloc
]
init
];
dataSource
.
appId
=
[
pAppId
intValue
];
dataSource
.
fileId
=
pFileId
;;
dataSource
.
quality
=
[
self
optQuality
:
quality
];
fileIdInfo
.
dataSource
=
dataSource
;
mediaInfo
=
[[
TXVodDownloadManager
shareInstance
]
getDownloadMediaInfo
:
fileIdInfo
];
}
return
mediaInfo
;
}
-
(
NSMutableDictionary
*
)
buildMapFromDownloadMediaInfo
:
(
TXVodDownloadMediaInfo
*
)
info
{
NSMutableDictionary
*
dict
=
[[
NSMutableDictionary
alloc
]
init
];
if
(
nil
!=
info
&&
[
NSNull
null
]
!=
(
NSNull
*
)
info
)
{
[
dict
setValue
:
info
.
playPath
forKey
:
@"playPath"
];
[
dict
setValue
:
@
(
info
.
progress
)
forKey
:
@"progress"
];
[
dict
setValue
:
@
([
CommonUtil
getDownloadEventByState
:(
int
)
info
.
downloadState
])
forKey
:
@"downloadState"
];
[
dict
setValue
:
info
.
userName
forKey
:
@"userName"
];
[
dict
setValue
:
@
(
info
.
duration
)
forKey
:
@"duration"
];
[
dict
setValue
:
@
(
info
.
playableDuration
)
forKey
:
@"playableDuration"
];
[
dict
setValue
:
@
(
info
.
size
)
forKey
:
@"size"
];
[
dict
setValue
:
@
(
info
.
downloadSize
)
forKey
:
@"downloadSize"
];
if
([
NSNull
null
]
!=
(
NSNull
*
)
info
.
url
&&
info
.
url
.
length
>
0
)
{
[
dict
setValue
:
info
.
url
forKey
:
@"url"
];
}
if
(
nil
!=
info
.
dataSource
&&
[
NSNull
null
]
!=
(
NSNull
*
)
info
.
dataSource
)
{
TXVodDownloadDataSource
*
dataSource
=
info
.
dataSource
;
[
dict
setValue
:
@
(
dataSource
.
appId
)
forKey
:
@"appId"
];
[
dict
setValue
:
dataSource
.
fileId
forKey
:
@"fileId"
];
[
dict
setValue
:
dataSource
.
pSign
forKey
:
@"pSign"
];
[
dict
setValue
:
@
(
dataSource
.
quality
)
forKey
:
@"quality"
];
[
dict
setValue
:
dataSource
.
token
forKey
:
@"token"
];
}
}
return
dict
;
}
/// 下载开始
-
(
void
)
onDownloadStart
:
(
TXVodDownloadMediaInfo
*
)
mediaInfo
{
[
_eventSink
success
:[
FTXDownloadManager
getParamsWithEvent
:
EVENT_DOWNLOAD_START
withParams
:[
self
buildMapFromDownloadMediaInfo
:
mediaInfo
]]];
}
/// 下载进度
-
(
void
)
onDownloadProgress
:
(
TXVodDownloadMediaInfo
*
)
mediaInfo
{
[
_eventSink
success
:[
FTXDownloadManager
getParamsWithEvent
:
EVENT_DOWNLOAD_PROGRESS
withParams
:[
self
buildMapFromDownloadMediaInfo
:
mediaInfo
]]];
}
/// 下载停止
-
(
void
)
onDownloadStop
:
(
TXVodDownloadMediaInfo
*
)
mediaInfo
{
[
_eventSink
success
:[
FTXDownloadManager
getParamsWithEvent
:
EVENT_DOWNLOAD_STOP
withParams
:[
self
buildMapFromDownloadMediaInfo
:
mediaInfo
]]];
}
/// 下载完成
-
(
void
)
onDownloadFinish
:
(
TXVodDownloadMediaInfo
*
)
mediaInfo
{
[
_eventSink
success
:[
FTXDownloadManager
getParamsWithEvent
:
EVENT_DOWNLOAD_FINISH
withParams
:[
self
buildMapFromDownloadMediaInfo
:
mediaInfo
]]];
}
/// 下载错误
-
(
void
)
onDownloadError
:
(
TXVodDownloadMediaInfo
*
)
mediaInfo
errorCode
:
(
TXDownloadError
)
code
errorMsg
:
(
NSString
*
)
msg
{
NSMutableDictionary
*
dict
=
[
self
buildMapFromDownloadMediaInfo
:
mediaInfo
];
[
dict
setValue
:
@
(
code
)
forKey
:
@"errorCode"
];
[
dict
setValue
:
msg
forKey
:
@"errorMsg"
];
[
_eventSink
success
:[
FTXDownloadManager
getParamsWithEvent
:
EVENT_DOWNLOAD_ERROR
withParams
:
dict
]];
}
/**
* 下载HLS,遇到加密的文件,将解密key给外部校验,ijk遗留,暂时弃用
* @param mediaInfo 下载对象
* @param url Url地址
* @param data 服务器返回
* @return 0:校验正确,继续下载;否则校验失败,抛出下载错误(SDK 获取失败)
*/
-
(
int
)
hlsKeyVerify
:
(
TXVodDownloadMediaInfo
*
)
mediaInfo
url
:
(
NSString
*
)
url
data
:
(
NSData
*
)
data
{
return
0
;
}
@end
Flutter/ios/Classes/FTXEvent.h
浏览文件 @
cd5e26a0
...
...
@@ -3,12 +3,45 @@
#define FTXEvent_h
// 音频变化事件code
#define EVENT_VOLUME_CHANGED 0x01
#define EVENT_AUDIO_FOCUS_PAUSE 0x02
#define EVENT_AUDIO_FOCUS_PLAY 0x03
#define EVENT_VOLUME_CHANGED 1
#define EVENT_AUDIO_FOCUS_PAUSE 2
#define EVENT_AUDIO_FOCUS_PLAY 3
// 画中画事件code
#define EVENT_PIP_MODE_ALREADY_ENTER 1
#define EVENT_PIP_MODE_ALREADY_EXIT 2
#define EVENT_PIP_MODE_REQUEST_START 3
#define EVENT_PIP_MODE_UI_STATE_CHANGED 4
#define EVENT_PIP_MODE_RESTORE_UI 5
#define EVENT_PIP_MODE_WILL_EXIT 6
// 画中画错误事件code
#define NO_ERROR 0 ///< 无错误
#define ERROR_IOS_PIP_DEVICE_NOT_SUPPORT -104 ///< 设备或系统版本不支持(iPad iOS9+ 才支持PIP)
#define ERROR_IOS_PIP_PLAYER_NOT_SUPPORT -105 ///< 播放器不支持
#define ERROR_IOS_PIP_VIDEO_NOT_SUPPORT -106 ///< 视频不支持
#define ERROR_IOS_PIP_IS_NOT_POSSIBLE -107 ///< PIP控制器不可用
#define ERROR_IOS_PIP_FROM_SYSTEM -108 ///< PIP控制器报错
#define ERROR_IOS_PIP_PLAYER_NOT_EXIST -109 ///< 播放器对象不存在
#define ERROR_IOS_PIP_IS_RUNNING -110 ///< PIP功能已经运行
#define ERROR_IOS_PIP_NOT_RUNNING -111 ///< PIP功能没有启动
// 视频预下载完成
#define EVENT_PREDOWNLOAD_ON_COMPLETE 200
// 视频预下载出错
#define EVENT_PREDOWNLOAD_ON_ERROR 201
// 视频下载开始
#define EVENT_DOWNLOAD_START 301
// 视频下载进度
#define EVENT_DOWNLOAD_PROGRESS 302
// 视频下载停止
#define EVENT_DOWNLOAD_STOP 303
// 视频下载完成
#define EVENT_DOWNLOAD_FINISH 304
// 视频下载错误
#define EVENT_DOWNLOAD_ERROR 305
#endif
/* FTXEvent_h */
Flutter/ios/Classes/FTXVodPlayer.h
浏览文件 @
cd5e26a0
...
...
@@ -7,8 +7,26 @@
NS_ASSUME_NONNULL_BEGIN
@protocol
FTXVodPlayerDelegate
<
NSObject
>
-
(
void
)
onPlayerPipRequestStart
;
-
(
void
)
onPlayerPipStateDidStart
;
-
(
void
)
onPlayerPipStateWillStop
;
-
(
void
)
onPlayerPipStateDidStop
;
-
(
void
)
onPlayerPipStateRestoreUI
;
-
(
void
)
onPlayerPipStateError
:(
NSInteger
)
errorId
;
@end
@interface
FTXVodPlayer
:
FTXBasePlayer
@property
(
nonatomic
,
weak
)
id
<
FTXVodPlayerDelegate
>
delegate
;
-
(
instancetype
)
initWithRegistrar
:(
id
<
FlutterPluginRegistrar
>
)
registrar
;
@end
...
...
Flutter/ios/Classes/FTXVodPlayer.m
浏览文件 @
cd5e26a0
差异被折叠。
点击展开。
Flutter/ios/Classes/SuperPlayerPlugin.m
浏览文件 @
cd5e26a0
...
...
@@ -9,7 +9,7 @@
#import <TXLiteAVSDK_Player/TXLiteAVSDK.h>
#import "FTXDownloadManager.h"
@interface
SuperPlayerPlugin
()
<
FlutterStreamHandler
>
@interface
SuperPlayerPlugin
()
<
FlutterStreamHandler
,
FTXVodPlayerDelegate
>
@property
(
nonatomic
,
strong
)
NSObject
<
FlutterPluginRegistrar
>*
registrar
;
@property
(
nonatomic
,
strong
)
NSMutableDictionary
*
players
;
...
...
@@ -19,7 +19,9 @@
@implementation
SuperPlayerPlugin
{
float
orginBrightness
;
FlutterEventChannel
*
_eventChannel
;
FlutterEventChannel
*
_pipEventChannel
;
FTXPlayerEventSinkQueue
*
_eventSink
;
FTXPlayerEventSinkQueue
*
_pipEventSink
;
FTXAudioManager
*
audioManager
;
FTXDownloadManager
*
_FTXDownloadManager
;
}
...
...
@@ -56,8 +58,11 @@ SuperPlayerPlugin* instance;
audioManager
=
[[
FTXAudioManager
alloc
]
init
];
// volume event stream
_eventSink
=
[
FTXPlayerEventSinkQueue
new
];
_pipEventSink
=
[
FTXPlayerEventSinkQueue
new
];
_eventChannel
=
[
FlutterEventChannel
eventChannelWithName
:
@"cloud.tencent.com/playerPlugin/event"
binaryMessenger
:[
registrar
messenger
]];
_pipEventChannel
=
[
FlutterEventChannel
eventChannelWithName
:
@"cloud.tencent.com/playerPlugin/pipEvent"
binaryMessenger
:[
registrar
messenger
]];
[
_eventChannel
setStreamHandler
:
self
];
[
_pipEventChannel
setStreamHandler
:
self
];
[
audioManager
registerVolumeChangeListener
:
self
selector
:
@selector
(
systemVolumeDidChangeNoti
:
)
name
:
@"AVSystemController_SystemVolumeDidChangeNotification"
object
:
nil
];
_FTXDownloadManager
=
[[
FTXDownloadManager
alloc
]
initWithRegistrar
:
registrar
];
...
...
@@ -78,6 +83,7 @@ SuperPlayerPlugin* instance;
result
(
playerId
);
}
else
if
([
@"createVodPlayer"
isEqualToString
:
call
.
method
]){
FTXVodPlayer
*
player
=
[[
FTXVodPlayer
alloc
]
initWithRegistrar
:
self
.
registrar
];
player
.
delegate
=
self
;
NSNumber
*
playerId
=
player
.
playerId
;
_players
[
playerId
]
=
player
;
result
(
playerId
);
...
...
@@ -166,8 +172,11 @@ SuperPlayerPlugin* instance;
int
logLevel
=
[
args
[
@"logLevel"
]
intValue
];
[
TXLiveBase
setLogLevel
:
logLevel
];
result
(
nil
);
}
else
if
([
@"getLiteAVSDKVersion"
isEqualToString
:
call
.
method
])
{
}
else
if
([
@"getLiteAVSDKVersion"
isEqualToString
:
call
.
method
])
{
result
([
TXLiveBase
getSDKVersionStr
]);
}
else
if
([
@"isDeviceSupportPip"
isEqualToString
:
call
.
method
])
{
BOOL
isSupport
=
[
TXVodPlayer
isSupportPictureInPicture
];
result
([
NSNumber
numberWithBool
:
isSupport
]);
}
else
{
result
(
FlutterMethodNotImplemented
);
}
...
...
@@ -194,6 +203,7 @@ SuperPlayerPlugin* instance;
if
([
arguments
isKindOfClass
:
NSString
.
class
])
{
if
([
arguments
isEqualToString
:
@"event"
])
{
[
_eventSink
setDelegate
:
events
];
[
_pipEventSink
setDelegate
:
events
];
}
}
...
...
@@ -205,10 +215,36 @@ SuperPlayerPlugin* instance;
if
([
arguments
isKindOfClass
:
NSString
.
class
])
{
if
([
arguments
isEqualToString
:
@"event"
])
{
[
_eventSink
setDelegate
:
nil
];
[
_pipEventSink
setDelegate
:
nil
];
}
}
return
nil
;
}
#pragma mark - FTXVodPlayerDelegate
-
(
void
)
onPlayerPipRequestStart
{
[
_pipEventSink
success
:@{
@"event"
:
@
(
EVENT_PIP_MODE_REQUEST_START
)}];
}
-
(
void
)
onPlayerPipStateDidStart
{
[
_pipEventSink
success
:@{
@"event"
:
@
(
EVENT_PIP_MODE_ALREADY_ENTER
)}];
}
-
(
void
)
onPlayerPipStateWillStop
{
[
_pipEventSink
success
:@{
@"event"
:
@
(
EVENT_PIP_MODE_WILL_EXIT
)}];
}
-
(
void
)
onPlayerPipStateDidStop
{
[
_pipEventSink
success
:@{
@"event"
:
@
(
EVENT_PIP_MODE_ALREADY_EXIT
)}];
}
-
(
void
)
onPlayerPipStateError
:
(
NSInteger
)
errorId
{
[
_pipEventSink
success
:@{
@"event"
:
@
(
errorId
)}];
}
-
(
void
)
onPlayerPipStateRestoreUI
{
[
_pipEventSink
success
:@{
@"event"
:
@
(
EVENT_PIP_MODE_RESTORE_UI
)}];
}
@end
Flutter/ios/Classes/TXResource/pictureInpicture_en.jpg
0 → 100644
浏览文件 @
cd5e26a0
99.7 KB
Flutter/ios/Classes/TXResource/pictureInpicture_zh.jpg
0 → 100644
浏览文件 @
cd5e26a0
34.7 KB
Flutter/ios/super_player.podspec
浏览文件 @
cd5e26a0
...
...
@@ -4,7 +4,7 @@
#
Pod
::
Spec
.
new
do
|
s
|
s
.
name
=
'super_player'
s
.
version
=
'1.0.
2
'
s
.
version
=
'1.0.
3
'
s
.
summary
=
'player plugin.'
s
.
description
=
<<-
DESC
player plugin.
...
...
@@ -20,6 +20,7 @@ player plugin.
s
.
ios
.
framework
=
[
'MobileCoreServices'
]
s
.
platform
=
:ios
,
'9.0'
s
.
static_framework
=
true
s
.
resources
=
[
'Classes/TXResource/**/*'
]
# Flutter.framework does not contain a i386 slice.
s
.
pod_target_xcconfig
=
{
'DEFINES_MODULE'
=>
'YES'
,
'EXCLUDED_ARCHS[sdk=iphonesimulator*]'
=>
'i386'
}
...
...
Flutter/lib/Core/tools/common_utils.dart
0 → 100644
浏览文件 @
cd5e26a0
// Copyright (c) 2022 Tencent. All rights reserved.
part of
SuperPlayer
;
/// 通用工具类
class
CommonUtils
{
/// 通过分辨率获取下载对应的qualityId
static
int
getDownloadQualityBySize
(
int
width
,
int
height
)
{
if
(
width
==
null
||
height
==
null
)
{
return
DownloadQuality
.
QUALITY_FLU
;
}
int
minValue
=
min
(
width
,
height
);
int
cacheQualityIndex
;
if
(
minValue
==
240
||
minValue
==
180
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_FLU
;
}
else
if
(
minValue
==
480
||
minValue
==
360
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_SD
;
}
else
if
(
minValue
==
540
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_SD
;
}
else
if
(
minValue
==
720
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_HD
;
}
else
if
(
minValue
==
1080
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_FHD
;
}
else
if
(
minValue
==
1440
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_2K
;
}
else
if
(
minValue
==
2160
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_4K
;
}
else
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_UNK
;
}
return
cacheQualityIndex
;
}
}
Flutter/lib/Core/txplayer_define.dart
浏览文件 @
cd5e26a0
...
...
@@ -81,9 +81,9 @@ abstract class TXVodPlayEvent {
static
const
EVT_PLAY_DURATION
=
"EVT_PLAY_DURATION"
;
// 播放总长
static
const
EVT_PLAYABLE_DURATION_MS
=
"EVT_PLAYABLE_DURATION_MS"
;
// 点播可播放时长(毫秒)
static
const
EVT_PLAYABLE_RATE
=
"EVT_PLAYABLE_RATE"
;
//播放速率
static
const
String
EVT_IMAGESPRIT_WEBVTTURL
=
"EVT_IMAGESPRIT_WEBVTTURL"
;
// 雪碧图web vtt描述文件下载URL
static
const
String
EVT_IMAGESPRIT_IMAGEURL_LIST
=
"EVT_IMAGESPRIT_IMAGEURL_LIST"
;
// 雪碧图图片下载URL
static
const
String
EVT_DRM_TYPE
=
"EVT_DRM_TYPE"
;
// 加密类型
static
const
EVT_IMAGESPRIT_WEBVTTURL
=
"EVT_IMAGESPRIT_WEBVTTURL"
;
// 雪碧图web vtt描述文件下载URL
static
const
EVT_IMAGESPRIT_IMAGEURL_LIST
=
"EVT_IMAGESPRIT_IMAGEURL_LIST"
;
// 雪碧图图片下载URL
static
const
EVT_DRM_TYPE
=
"EVT_DRM_TYPE"
;
// 加密类型
/// superplayer plugin volume event
static
const
EVENT_VOLUME_CHANGED
=
1
;
// 音量变化
...
...
@@ -94,15 +94,33 @@ abstract class TXVodPlayEvent {
static
const
EVENT_PIP_MODE_ALREADY_EXIT
=
2
;
// 已经退出画中画模式
static
const
EVENT_PIP_MODE_REQUEST_START
=
3
;
// 开始请求进入画中画模式
static
const
EVENT_PIP_MODE_UI_STATE_CHANGED
=
4
;
// pip UI状态发生变动,only support android > 31
static
const
EVENT_IOS_PIP_MODE_RESTORE_UI
=
5
;
// 重置UI only support iOS
static
const
EVENT_IOS_PIP_MODE_WILL_EXIT
=
6
;
// 将要退出画中画 only support iOS
static
const
NO_ERROR
=
0
;
static
const
ERROR_PIP_LOWER_VERSION
=
-
101
;
// pip 错误,android版本过低
static
const
ERROR_PIP_DENIED_PERMISSION
=
-
102
;
// pip 错误,画中画权限关闭/设备不支持画中画
static
const
ERROR_PIP_ACTIVITY_DESTROYED
=
-
103
;
// pip 错误,当前界面已销毁
static
const
ERROR_PIP_LOWER_VERSION
=
-
101
;
// pip 错误,android版本过低
static
const
ERROR_PIP_DENIED_PERMISSION
=
-
102
;
// pip 错误,画中画权限关闭/设备不支持画中画
static
const
ERROR_PIP_ACTIVITY_DESTROYED
=
-
103
;
// pip 错误,当前界面已销毁
static
const
ERROR_IOS_PIP_DEVICE_NOT_SUPPORT
=
-
104
;
// pip 错误,设备或系统版本不支持(iPad iOS9+ 才支持PIP)
static
const
ERROR_IOS_PIP_PLAYER_NOT_SUPPORT
=
-
105
;
// pip 错误,播放器不支持 only support iOS
static
const
ERROR_IOS_PIP_VIDEO_NOT_SUPPORT
=
-
106
;
// pip 错误,视频不支持 only support iOS
static
const
ERROR_IOS_PIP_IS_NOT_POSSIBLE
=
-
107
;
// pip 错误,PIP控制器不可用 only support iOS
static
const
ERROR_IOS_PIP_FROM_SYSTEM
=
-
108
;
// pip 错误,PIP控制器报错 only support iOS
static
const
ERROR_IOS_PIP_PLAYER_NOT_EXIST
=
-
109
;
// pip 错误,播放器对象不存在 only support iOS
static
const
ERROR_IOS_PIP_IS_RUNNING
=
-
110
;
// pip 错误,PIP功能已经运行 only support iOS
static
const
ERROR_IOS_PIP_NOT_RUNNING
=
-
111
;
// pip 错误,PIP功能没有启动 only support iOS
/// 视频下载相关事件
static
const
int
EVENT_PREDOWNLOAD_ON_COMPLETE
=
200
;
// 视频预下载完成
static
const
int
EVENT_PREDOWNLOAD_ON_ERROR
=
201
;
// 视频预下载出错
static
const
EVENT_PREDOWNLOAD_ON_COMPLETE
=
200
;
// 视频预下载完成
static
const
EVENT_PREDOWNLOAD_ON_ERROR
=
201
;
// 视频预下载出错
static
const
EVENT_DOWNLOAD_START
=
301
;
// 视频下载开始
static
const
EVENT_DOWNLOAD_PROGRESS
=
302
;
// 视频下载进度
static
const
EVENT_DOWNLOAD_STOP
=
303
;
// 视频下载停止
static
const
EVENT_DOWNLOAD_FINISH
=
304
;
// 视频下载完成
static
const
EVENT_DOWNLOAD_ERROR
=
305
;
// 视频下载错误
}
abstract
class
TXVodNetEvent
{
...
...
@@ -159,13 +177,24 @@ enum TXPlayerEvent {
}
class
TXLogLevel
{
static
const
int
LOG_LEVEL_VERBOSE
=
0
;
// 输出所有级别的log
static
const
int
LOG_LEVEL_DEBUG
=
1
;
// 输出 DEBUG,INFO,WARNING,ERROR 和 FATAL 级别的log
static
const
int
LOG_LEVEL_INFO
=
2
;
// 输出 INFO,WARNNING,ERROR 和 FATAL 级别的log
static
const
int
LOG_LEVEL_WARN
=
3
;
// 输出WARNNING,ERROR 和 FATAL 级别的log
static
const
int
LOG_LEVEL_ERROR
=
4
;
// 输出ERROR 和 FATAL 级别的log
static
const
int
LOG_LEVEL_FATAL
=
5
;
// 只输出FATAL 级别的log
static
const
int
LOG_LEVEL_NULL
=
6
;
// 不输出任何sdk log
static
const
LOG_LEVEL_VERBOSE
=
0
;
// 输出所有级别的log
static
const
LOG_LEVEL_DEBUG
=
1
;
// 输出 DEBUG,INFO,WARNING,ERROR 和 FATAL 级别的log
static
const
LOG_LEVEL_INFO
=
2
;
// 输出 INFO,WARNNING,ERROR 和 FATAL 级别的log
static
const
LOG_LEVEL_WARN
=
3
;
// 输出WARNNING,ERROR 和 FATAL 级别的log
static
const
LOG_LEVEL_ERROR
=
4
;
// 输出ERROR 和 FATAL 级别的log
static
const
LOG_LEVEL_FATAL
=
5
;
// 只输出FATAL 级别的log
static
const
LOG_LEVEL_NULL
=
6
;
// 不输出任何sdk log
}
class
DownloadQuality
{
static
const
QUALITY_OD
=
0
;
static
const
QUALITY_FLU
=
1
;
static
const
QUALITY_SD
=
2
;
static
const
QUALITY_HD
=
3
;
static
const
QUALITY_FHD
=
4
;
static
const
QUALITY_2K
=
5
;
static
const
QUALITY_4K
=
6
;
static
const
QUALITY_UNK
=
1000
;
}
class
TXPlayInfoParams
{
...
...
@@ -184,7 +213,82 @@ class TXPlayInfoParams {
}
}
/// fileId存储
class
TXVodDownloadDataSource
{
/// 下载文件对应的appId,fileId下载必填
int
?
appId
;
/// 下载文件Id,fileId下载必填
String
?
fileId
;
/// 加密签名,加密视频必填
String
?
pSign
;
/// 清晰度ID,fileId下载必传,通过[CommonUtils.getDownloadQualityBySize]进行转换
int
?
quality
;
/// 加密token
String
?
token
;
/// 账户名称,用于url下载设置账户名称
String
?
userName
;
Map
<
String
,
dynamic
>
toJson
()
{
Map
<
String
,
dynamic
>
json
=
{};
json
[
"appId"
]
=
appId
;
json
[
"fileId"
]
=
fileId
;
json
[
"pSign"
]
=
pSign
;
json
[
"quality"
]
=
quality
;
json
[
"token"
]
=
token
;
json
[
"userName"
]
=
userName
;
return
json
;
}
}
/// 视频下载信息
class
TXVodDownloadMedialnfo
{
/// 缓存地址
String
?
playPath
;
/// 下载进度
double
?
progress
;
/// 下载状态
int
?
downloadState
;
/// 账户名称,用于url下载设置账户名称
String
?
userName
;
/// 总时长
int
?
duration
;
/// 已下载的可播放时长
int
?
playableDuration
;
/// 文件总大小,单位:byte
int
?
size
;
/// 已下载大小,单位:byte
int
?
downloadSize
;
/// 需要下载的视频url,url下载必填
/// <h1>
/// url下载不支持不支持嵌套m3u8和mp4下载
/// </h1>
String
?
url
;
/// fileId 存储
TXVodDownloadDataSource
?
dataSource
;
Map
<
String
,
dynamic
>
toJson
()
{
Map
<
String
,
dynamic
>
json
=
{};
json
[
"url"
]
=
url
;
json
[
"downloadState"
]
=
downloadState
;
json
[
"progress"
]
=
progress
;
json
[
"playPath"
]
=
playPath
;
json
[
"userName"
]
=
userName
;
json
[
"duration"
]
=
duration
;
json
[
"playableDuration"
]
=
playableDuration
;
json
[
"size"
]
=
size
;
json
[
"downloadSize"
]
=
downloadSize
;
if
(
null
!=
dataSource
)
{
json
.
addAll
(
dataSource
!.
toJson
());
}
return
json
;
}
}
//视频预下载事件回调Listener
typedef
FTXPredownlodOnCompleteListener
=
void
Function
(
int
taskId
,
String
url
);
typedef
FTXPredownlodOnErrorListener
=
void
Function
(
int
taskId
,
String
url
,
int
code
,
String
msg
);
// 视频下载时间回调Listener
typedef
FTXDownlodOnStateChangeListener
=
void
Function
(
int
event
,
TXVodDownloadMedialnfo
info
);
typedef
FTXDownlodOnErrorListener
=
void
Function
(
int
errorCode
,
String
errorMsg
,
TXVodDownloadMedialnfo
info
);
Flutter/lib/Core/txvoddownload_controller.dart
浏览文件 @
cd5e26a0
...
...
@@ -4,34 +4,38 @@ part of SuperPlayer;
/// include features:
/// 1. Video predownlaod
/// 2. Video download
class
TXVodDownl
ao
dController
{
class
TXVodDownl
oa
dController
{
static
const
String
TAG
=
'TXVodDownlaodController'
;
static
TXVodDownlaodController
?
_instance
;
static
TXVodDownlaodController
get
instance
=>
_sharedInstance
();
static
TXVodDownloadController
?
_instance
;
static
TXVodDownloadController
get
instance
=>
_sharedInstance
();
StreamSubscription
?
_downloadEventSubscription
;
final
StreamController
<
Map
<
dynamic
,
dynamic
>>
_downloadEventStreamController
=
StreamController
.
broadcast
();
Stream
<
Map
<
dynamic
,
dynamic
>>
get
onDownlaodEventBroadcast
=>
_downloadEventStreamController
.
stream
;
Stream
<
Map
<
dynamic
,
dynamic
>>
get
onDownloadEventBroadcast
=>
_downloadEventStreamController
.
stream
;
late
MethodChannel
_methodChannel
;
FTXPredownlodOnCompleteListener
?
_onPreDownloadOnCompleteListener
;
FTXPredownlodOnErrorListener
?
_onPreDownloadOnErrorListener
;
static
TXVodDownlaodController
_sharedInstance
()
{
FTXDownlodOnStateChangeListener
?
_downlodOnStateChangeListener
;
FTXDownlodOnErrorListener
?
_downlodOnErrorListener
;
static
TXVodDownloadController
_sharedInstance
()
{
if
(
_instance
==
null
)
{
_instance
=
TXVodDownl
ao
dController
.
_createInsatnce
();
_instance
=
TXVodDownl
oa
dController
.
_createInsatnce
();
}
return
_instance
!;
}
TXVodDownl
ao
dController
.
_createInsatnce
()
{
TXVodDownl
oa
dController
.
_createInsatnce
()
{
EventChannel
eventChannel
=
EventChannel
(
"cloud.tencent.com/txvodplayer/download/event"
);
_downloadEventSubscription
=
eventChannel
.
receiveBroadcastStream
(
'event'
)
.
listen
(
_eventHandler
,
onError:
_errorHandler
);
_downloadEventSubscription
=
eventChannel
.
receiveBroadcastStream
(
'event'
)
.
listen
(
_eventHandler
,
onError:
_errorHandler
);
_methodChannel
=
MethodChannel
(
"cloud.tencent.com/txvodplayer/download/api"
);
}
/// 启动预下载。
/// 【重要】启动预下载前,请先设置好播放引擎的缓存目录[SuperPlayerPlugin.setGlobalCacheFolderPath]和缓存大小[SuperPlayerPlugin.setGlobalMaxCacheSize],这个设置是全局配置需和播放器保持一致,否则会造成播放缓存失效。
/// playUrl: 要预下载的url
...
...
@@ -40,21 +44,19 @@ class TXVodDownlaodController {
/// onCompleteListener:预下载成功回调
/// onErrorListener:预下载失败回调
/// 返回值:任务ID,可用这个任务ID停止预下载 [stopPreload]
Future
<
int
>
startPreLoad
(
final
String
playUrl
,
final
int
preloadSizeMB
,
final
int
preferredResolution
,
{
FTXPredownlodOnCompleteListener
?
onCompleteListener
,
FTXPredownlodOnErrorListener
?
onErrorListener
,
})
async
{
Future
<
int
>
startPreLoad
(
final
String
playUrl
,
final
int
preloadSizeMB
,
final
int
preferredResolution
,
{
FTXPredownlodOnCompleteListener
?
onCompleteListener
,
FTXPredownlodOnErrorListener
?
onErrorListener
,
})
async
{
_onPreDownloadOnCompleteListener
=
onCompleteListener
;
_onPreDownloadOnErrorListener
=
onErrorListener
;
var
map
=
{
"playUrl"
:
playUrl
,
"preloadSizeMB"
:
preloadSizeMB
,
"preferredResolution"
:
preferredResolution
};
var
map
=
{
"playUrl"
:
playUrl
,
"preloadSizeMB"
:
preloadSizeMB
,
"preferredResolution"
:
preferredResolution
};
return
await
_methodChannel
.
invokeMethod
(
"startPreLoad"
,
map
);
}
/// 停止预下载。
/// taskId: 任务id,[startPreLoad]返回值
Future
<
void
>
stopPreLoad
(
final
int
taskId
)
async
{
...
...
@@ -62,6 +64,72 @@ class TXVodDownlaodController {
await
_methodChannel
.
invokeMethod
(
"stopPreLoad"
,
map
);
}
/// 开始下载
/// videoDownloadModel: 下载构造体 [TXVodDownloadMedialnfo]
/// userName: 下载用户,用来区分不同用户的下载,可不传,不传则使用默认值
Future
<
void
>
startDonwload
(
TXVodDownloadMedialnfo
medialnfo
)
async
{
await
_methodChannel
.
invokeMethod
(
"startDownload"
,
medialnfo
.
toJson
());
}
/// 停止下载
/// videoDownloadModel: 下载构造体 [TXVodDownloadMedialnfo]
Future
<
void
>
stopDownload
(
TXVodDownloadMedialnfo
medialnfo
)
async
{
await
_methodChannel
.
invokeMethod
(
"stopDownload"
,
medialnfo
.
toJson
());
}
/// 设置下载请求头
Future
<
void
>
setDownloadHeaders
(
Map
<
String
,
String
>
headers
)
async
{
await
_methodChannel
.
invokeMethod
(
"setDownloadHeaders"
,
{
"headers"
:
headers
});
}
/// 获取所有视频下载列表
/// return [TXVodDownloadMedialnfo]
Future
<
List
<
TXVodDownloadMedialnfo
>>
getDownloadList
()
async
{
List
<
TXVodDownloadMedialnfo
>
outputList
=
[];
List
<
dynamic
>
donwloadOrgList
=
await
_methodChannel
.
invokeMethod
(
"getDownloadList"
);
for
(
dynamic
data
in
donwloadOrgList
)
{
outputList
.
add
(
_getDownloadInfoFromMap
(
data
));
}
return
outputList
;
}
/// 获得指定视频的下载信息
/// return [TXVodDownloadMedialnfo]
Future
<
TXVodDownloadMedialnfo
>
getDownloadInfo
(
TXVodDownloadMedialnfo
medialnfo
)
async
{
Map
<
dynamic
,
dynamic
>
data
=
await
_methodChannel
.
invokeMethod
(
"getDownloadInfo"
,
medialnfo
.
toJson
());
return
_getDownloadInfoFromMap
(
data
);
}
/// 设置下载事件监听,该监听为全局下载监听配置,重复调用,listener会先后覆盖
void
setDownloadObserver
(
FTXDownlodOnStateChangeListener
downlodOnStateChangeListener
,
FTXDownlodOnErrorListener
downlodOnErrorListener
)
{
_downlodOnStateChangeListener
=
downlodOnStateChangeListener
;
_downlodOnErrorListener
=
downlodOnErrorListener
;
}
TXVodDownloadMedialnfo
_getDownloadInfoFromMap
(
Map
<
dynamic
,
dynamic
>
map
)
{
TXVodDownloadMedialnfo
medialnfo
=
TXVodDownloadMedialnfo
();
medialnfo
.
playPath
=
map
[
"playPath"
];
medialnfo
.
progress
=
map
[
"progress"
];
medialnfo
.
downloadState
=
map
[
"downloadState"
];
medialnfo
.
userName
=
map
[
"userName"
];
medialnfo
.
duration
=
map
[
"duration"
];
medialnfo
.
playableDuration
=
map
[
"playableDuration"
];
medialnfo
.
size
=
map
[
"size"
];
medialnfo
.
downloadSize
=
map
[
"downloadSize"
];
medialnfo
.
url
=
map
[
"url"
];
if
(
map
.
keys
.
contains
(
"appId"
))
{
TXVodDownloadDataSource
dataSource
=
TXVodDownloadDataSource
();
dataSource
.
appId
=
map
[
"appId"
];
dataSource
.
fileId
=
map
[
"fileId"
];
dataSource
.
pSign
=
map
[
"pSign"
];
dataSource
.
token
=
map
[
"token"
];
dataSource
.
userName
=
map
[
"userName"
];
dataSource
.
quality
=
map
[
"quality"
];
medialnfo
.
dataSource
=
dataSource
;
}
return
medialnfo
;
}
_eventHandler
(
event
)
{
if
(
null
==
event
)
{
...
...
@@ -69,7 +137,8 @@ class TXVodDownlaodController {
}
LogUtils
.
d
(
TAG
,
'_eventHandler, event=
${event}
'
);
final
Map
<
dynamic
,
dynamic
>
map
=
event
;
switch
(
map
[
"event"
])
{
int
eventCode
=
map
[
"event"
];
switch
(
eventCode
)
{
case
TXVodPlayEvent
.
EVENT_PREDOWNLOAD_ON_COMPLETE
:
int
taskId
=
map
[
'taskId'
]
as
int
;
String
url
=
map
[
'url'
]
as
String
;
...
...
@@ -88,13 +157,23 @@ class TXVodDownlaodController {
_onPreDownloadOnErrorListener
!(
taskId
,
url
,
code
,
msg
);
}
break
;
case
TXVodPlayEvent
.
EVENT_DOWNLOAD_START
:
case
TXVodPlayEvent
.
EVENT_DOWNLOAD_PROGRESS
:
case
TXVodPlayEvent
.
EVENT_DOWNLOAD_STOP
:
case
TXVodPlayEvent
.
EVENT_DOWNLOAD_FINISH
:
_downlodOnStateChangeListener
?.
call
(
eventCode
,
_getDownloadInfoFromMap
(
map
));
break
;
case
TXVodPlayEvent
.
EVENT_DOWNLOAD_ERROR
:
TXVodDownloadMedialnfo
info
=
_getDownloadInfoFromMap
(
map
);
int
errorCode
=
map
[
"errorCode"
];
String
errorMsg
=
map
[
"errorMsg"
];
_downlodOnErrorListener
?.
call
(
errorCode
,
errorMsg
,
info
);
break
;
default
:
break
;
}
_downloadEventStreamController
.
add
(
event
);
}
_errorHandler
(
error
)
{
}
}
\ No newline at end of file
_errorHandler
(
error
)
{}
}
Flutter/lib/super_player.dart
浏览文件 @
cd5e26a0
...
...
@@ -3,6 +3,7 @@ library SuperPlayer;
import
'dart:async'
;
import
'dart:core'
;
import
'dart:math'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/foundation.dart'
;
...
...
@@ -17,4 +18,5 @@ part 'Core/txplayer_define.dart';
part
'Core/txplayer_widget.dart'
;
part
'Core/txvodplayer_config.dart'
;
part
'Core/txvodplayer_controller.dart'
;
part
'Core/txvoddownload_controller.dart'
;
\ No newline at end of file
part
'Core/txvoddownload_controller.dart'
;
part
'Core/tools/common_utils.dart'
;
\ No newline at end of file
Flutter/pubspec.yaml
浏览文件 @
cd5e26a0
name
:
super_player
description
:
player plugin.
version
:
1.0.
2
version
:
1.0.
3
author
:
homepage
:
...
...
Flutter/test/super_player_test.dart
浏览文件 @
cd5e26a0
...
...
@@ -27,7 +27,7 @@ void main() {
await
SuperPlayerPlugin
.
setGlobalMaxCacheSize
(
200
);
String
_url
=
"http://1400329073.vod2.myqcloud.com/d62d88a7vodtranscq1400329073/59c68fe75285890800381567412/adp.10.m3u8"
;
int
taskId
=
await
TXVodDownl
ao
dController
.
instance
.
startPreLoad
(
_url
,
20
,
720
*
1080
,
int
taskId
=
await
TXVodDownl
oa
dController
.
instance
.
startPreLoad
(
_url
,
20
,
720
*
1080
,
onCompleteListener:
(
int
taskId
,
String
url
)
{
print
(
'taskID=
${taskId}
,url=
${url}
'
);
},
onErrorListener:
(
int
taskId
,
String
url
,
int
code
,
String
msg
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论