提交 1831072e authored 作者: dokieyang's avatar dokieyang

Update version:1.0.2

1. refactor superPlayer,move it to example
上级 08ad5d2f
差异被折叠。
group 'com.tencent.vod.flutter' group 'com.tencent.vod.flutter'
apply from:'config.gradle' apply from:'config.gradle'
version '1.0.1' version '1.0.2'
buildscript { buildscript {
repositories { repositories {
...@@ -52,16 +52,8 @@ android { ...@@ -52,16 +52,8 @@ android {
} }
} }
/**
* 判断客户是否有自定义liteavSdk版本,如果未定义则默认使用config.gradle配置的最新版本。
* 这里判断,不为null、不为空字符串
*/
def liteavSdk = rootProject.ext.liteavSdk
if(rootProject.ext.liteavSdkCustom) {
liteavSdk = rootProject.ext.liteavSdkCustom
}
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
implementation liteavSdk implementation rootProject.ext.liteavSdk
} }
\ No newline at end of file
...@@ -503,7 +503,11 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC ...@@ -503,7 +503,11 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
void setToken(String token) { void setToken(String token) {
if (mVodPlayer != null) { if (mVodPlayer != null) {
mVodPlayer.setToken(token); if(TextUtils.isEmpty(token)) {
mVodPlayer.setToken(null);
} else {
mVodPlayer.setToken(token);
}
} }
} }
......
...@@ -90,14 +90,6 @@ super_player: ...@@ -90,14 +90,6 @@ super_player:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
``` ```
如果需要更换sdk中依赖的liteav更新包,可以在android的build.gradle中指定rootProject.ext.liteavSdkCustom依赖
```groovy
rootProject.ext.liteavSdkCustom="com.tencent.liteav:LiteAVSDK_Player:latest.release"
```
如果不定义该值,或者赋值为空字符串和null,则默认使用player最新版本
### iOS 配置[](id:iOS_config) ### iOS 配置[](id:iOS_config)
在 iOS 的`Info.plist`中增加如下配置: 在 iOS 的`Info.plist`中增加如下配置:
......
...@@ -19,26 +19,13 @@ SDK 早期版本只有 TXLivePlayer 一个 Class 承载直播和点播功能, ...@@ -19,26 +19,13 @@ SDK 早期版本只有 TXLivePlayer 一个 Class 承载直播和点播功能,
## 对接攻略 ## 对接攻略
### 步骤1:申请视频播放能力License和集成 ### step 1: 创建 Player
集成播放器前,需要[注册腾讯云账户](https://cloud.tencent.com/login),注册成功后申请视频播放能力License, 然后通过下面方式集成,建议在应用启动时进行。
如果没有集成license,播放过程中可能会出现异常。
```dart
String licenceURL = ""; // 获取到的 licence url
String licenceKey = ""; // 获取到的 licence key
SuperPlayerPlugin.setGlobalLicense(licenceURL, licenceKey);
```
### 步骤2: 创建 Player
视频云 SDK 中的 TXLivePlayer 模块负责实现直播播放功能。对应于 Flutter 是 TXLivePlayerController 视频云 SDK 中的 TXLivePlayer 模块负责实现直播播放功能。对应于 Flutter 是 TXLivePlayerController
```dart ```dart
TXLivePlayerController controller = TXLivePlayerController(); TXLivePlayerController controller = TXLivePlayerController();
``` ```
### 步骤3: 渲染 View ### step 2: 渲染 View
接下来我们要给播放器的视频画面找个地方来显示,Flutter 系统中使用 Widget 作为基本的界面渲染单位,所以您只需要准备一个 Widget 并调整好布局就可以了。你可以直接使用 TXPlayerVideo 或者继承它来显示,也可以参考源码实现自定义视图。 接下来我们要给播放器的视频画面找个地方来显示,Flutter 系统中使用 Widget 作为基本的界面渲染单位,所以您只需要准备一个 Widget 并调整好布局就可以了。你可以直接使用 TXPlayerVideo 或者继承它来显示,也可以参考源码实现自定义视图。
```dart ```dart
...@@ -86,7 +73,7 @@ TXLivePlayerController controller = TXLivePlayerController(); ...@@ -86,7 +73,7 @@ TXLivePlayerController controller = TXLivePlayerController();
3. 将该id通过channel机制传递给dart侧,dart侧就能够通过 `Texture` 这个widget来使用纹理了,参数就是id 3. 将该id通过channel机制传递给dart侧,dart侧就能够通过 `Texture` 这个widget来使用纹理了,参数就是id
4. flutter engine调用 `copyPixelBuffer` 拿到具体的纹理数据,然后交由底层进行gpu渲染 4. flutter engine调用 `copyPixelBuffer` 拿到具体的纹理数据,然后交由底层进行gpu渲染
### 步骤4: 启动播放 ### step 3: 启动播放
```dart ```dart
String flvUrl = "http://liteavapp.qcloud.com/live/liteavdemoplayerstreamid_demo1080p.flv"; String flvUrl = "http://liteavapp.qcloud.com/live/liteavdemoplayerstreamid_demo1080p.flv";
await _controller.play("flvUrl", playType: TXPlayType.LIVE_FLV); await _controller.play("flvUrl", playType: TXPlayType.LIVE_FLV);
...@@ -102,7 +89,7 @@ await _controller.play("flvUrl", playType: TXPlayType.LIVE_FLV); ...@@ -102,7 +89,7 @@ await _controller.play("flvUrl", playType: TXPlayType.LIVE_FLV);
> **关于 HLS(m3u8)** > **关于 HLS(m3u8)**
> 在 App 上我们不推荐使用 HLS 这种播放协议播放直播视频源(虽然它很适合用来做点播),因为延迟太高,在 App 上推荐使用 LIVE_FLV 或者 LIVE_RTMP 播放协议。 > 在 App 上我们不推荐使用 HLS 这种播放协议播放直播视频源(虽然它很适合用来做点播),因为延迟太高,在 App 上推荐使用 LIVE_FLV 或者 LIVE_RTMP 播放协议。
### 步骤5: 暂停播放 ### step 5: 暂停播放
对于直播播放而言,并没有真正意义上的暂停,所谓的直播暂停,只是**画面冻结****关闭声音**,而云端的视频源还在不断地更新着,所以当您调用 resume 的时候,会从最新的时间点开始播放,这跟点播是有很大不同的(点播播放器的暂停和继续与播放本地视频文件时的表现相同)。 对于直播播放而言,并没有真正意义上的暂停,所谓的直播暂停,只是**画面冻结****关闭声音**,而云端的视频源还在不断地更新着,所以当您调用 resume 的时候,会从最新的时间点开始播放,这跟点播是有很大不同的(点播播放器的暂停和继续与播放本地视频文件时的表现相同)。
```dart ```dart
...@@ -112,14 +99,13 @@ _controller.pause(); ...@@ -112,14 +99,13 @@ _controller.pause();
_controller.resume(); _controller.resume();
``` ```
### 步骤6: 结束播放 ### step 6: 结束播放
```dart ```dart
// 停止播放 // 停止播放
_controller.stop(); _controller.stop();
``` ```
<h3 id="Message">步骤7: 消息接收</h3> <h3 id="Message">step 7: 消息接收</h3>
此功能可以在推流端将一些自定义 message 随着音视频线路直接下发到观众端,适用场景例如: 此功能可以在推流端将一些自定义 message 随着音视频线路直接下发到观众端,适用场景例如:
(1)冲顶大会:推流端将<strong>题目</strong>下发到观众端,可以做到“音-画-题”完美同步。 (1)冲顶大会:推流端将<strong>题目</strong>下发到观众端,可以做到“音-画-题”完美同步。
(2)秀场直播:推流端将<strong>歌词</strong>下发到观众端,可以在播放端实时绘制出歌词特效,因而不受视频编码的降质影响。 (2)秀场直播:推流端将<strong>歌词</strong>下发到观众端,可以在播放端实时绘制出歌词特效,因而不受视频编码的降质影响。
...@@ -136,7 +122,7 @@ _controller.onPlayerEventBroadcast.listen((event) {//订阅事件分发 ...@@ -136,7 +122,7 @@ _controller.onPlayerEventBroadcast.listen((event) {//订阅事件分发
}); });
``` ```
### 步骤8: 清晰度无缝切换 ### step 7: 清晰度无缝切换
日常使用中,网络情况在不断发生变化。在网络较差的情况下,最好适度降低画质,以减少卡顿;反之,网速比较好,可以观看更高画质。 日常使用中,网络情况在不断发生变化。在网络较差的情况下,最好适度降低画质,以减少卡顿;反之,网速比较好,可以观看更高画质。
传统切流方式一般是重新播放,会导致切换前后画面衔接不上、黑屏、卡顿等问题。使用无缝切换方案,在不中断直播的情况下,能直接切到另条流上。 传统切流方式一般是重新播放,会导致切换前后画面衔接不上、黑屏、卡顿等问题。使用无缝切换方案,在不中断直播的情况下,能直接切到另条流上。
...@@ -150,7 +136,7 @@ _controller.switchStream("http://5815.liveplay.myqcloud.com/live/5815_62fe94d692 ...@@ -150,7 +136,7 @@ _controller.switchStream("http://5815.liveplay.myqcloud.com/live/5815_62fe94d692
>清晰度无缝切换功能需要在后台配置 PTS 对齐,如您需要可 [提交工单](https://console.cloud.tencent.com/workorder) 申请使用。 >清晰度无缝切换功能需要在后台配置 PTS 对齐,如您需要可 [提交工单](https://console.cloud.tencent.com/workorder) 申请使用。
### 步骤9: 直播回看 ### step 8: 直播回看
时移功能是腾讯云推出的特色能力,可以在直播过程中,随时观看回退到任意直播历史时间点,并能在此时间点一直观看直播。非常适合游戏、球赛等互动性不高,但观看连续性较强的场景。 时移功能是腾讯云推出的特色能力,可以在直播过程中,随时观看回退到任意直播历史时间点,并能在此时间点一直观看直播。非常适合游戏、球赛等互动性不高,但观看连续性较强的场景。
```dart ```dart
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
## 通过本文你可以学会 ## 通过本文你可以学会
* 如何集成腾讯云视立方 Flutter 超级播放器SDK * 如何集成腾讯云视立方 Flutter 超级播放器SDK
* 如何使用超级播放器 SDK 进行点播播放 * 如何使用超级播放器组件进行点播播放
## 基础知识 ## 基础知识
...@@ -50,14 +50,6 @@ flutter pub upgrade ...@@ -50,14 +50,6 @@ flutter pub upgrade
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
``` ```
如果需要更换sdk中依赖的liteav更新包,可以在android的build.gradle中指定rootProject.ext.liteavSdkCustom依赖
```groovy
rootProject.ext.liteavSdkCustom="com.tencent.liteav:LiteAVSDK_Player:latest.release"
```
如果不定义该值,或者赋值为空字符串和null,则默认使用player最新版本
### iOS 配置[](id:iOS_config) ### iOS 配置[](id:iOS_config)
在 iOS 的`Info.plist`中增加如下配置: 在 iOS 的`Info.plist`中增加如下配置:
...@@ -129,7 +121,7 @@ _controller.onSimplePlayerEventBroadcast.listen((event) { ...@@ -129,7 +121,7 @@ _controller.onSimplePlayerEventBroadcast.listen((event) {
```dart ```dart
Widget _getPlayArea() { Widget _getPlayArea() {
return Container( return Container(
height: 230, height: 220,
child: SuperPlayerView(_controller), child: SuperPlayerView(_controller),
); );
} }
......
...@@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; ...@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:super_player/super_player.dart'; import 'package:super_player/super_player.dart';
import 'package:super_player_example/ui/demo_inputdialog.dart'; import 'package:super_player_example/ui/demo_inputdialog.dart';
import 'superplayer/demo_superplayer_lib.dart';
/// flutter superplayer demo /// flutter superplayer demo
class DemoSuperplayer extends StatefulWidget { class DemoSuperplayer extends StatefulWidget {
...@@ -12,7 +13,7 @@ class DemoSuperplayer extends StatefulWidget { ...@@ -12,7 +13,7 @@ class DemoSuperplayer extends StatefulWidget {
class _DemoSuperplayerState extends State<DemoSuperplayer> { class _DemoSuperplayerState extends State<DemoSuperplayer> {
List<SuperPlayerModel> videoModels = []; List<SuperPlayerModel> videoModels = [];
bool _isFullScreen = false; bool _isFullScreen = false;
SuperPlayerController _controller; late SuperPlayerController _controller;
@override @override
void initState() { void initState() {
...@@ -78,7 +79,7 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> { ...@@ -78,7 +79,7 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> {
Widget _getPlayArea() { Widget _getPlayArea() {
return Container( return Container(
height: 230, height: 220,
child: SuperPlayerView(_controller), child: SuperPlayerView(_controller),
); );
} }
...@@ -128,7 +129,7 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> { ...@@ -128,7 +129,7 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> {
model.videoURL = url; model.videoURL = url;
} else if (appId != 0 && fileId.isNotEmpty) { } else if (appId != 0 && fileId.isNotEmpty) {
model.videoId = new SuperPlayerVideoId(); model.videoId = new SuperPlayerVideoId();
model.videoId.fileId = fileId; model.videoId!.fileId = fileId;
} else { } else {
EasyLoading.showError("请输入播放地址!"); EasyLoading.showError("请输入播放地址!");
return; return;
...@@ -151,7 +152,7 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> { ...@@ -151,7 +152,7 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> {
SuperPlayerModel model = SuperPlayerModel(); SuperPlayerModel model = SuperPlayerModel();
model.appId = 1500005830; model.appId = 1500005830;
model.videoId = new SuperPlayerVideoId(); model.videoId = new SuperPlayerVideoId();
model.videoId.fileId = "8602268011437356984"; model.videoId!.fileId = "8602268011437356984";
model.title = "云点播"; model.title = "云点播";
model.playAction = playAction; model.playAction = playAction;
models.add(model); models.add(model);
...@@ -159,35 +160,35 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> { ...@@ -159,35 +160,35 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> {
model = SuperPlayerModel(); model = SuperPlayerModel();
model.appId = 1252463788; model.appId = 1252463788;
model.videoId = new SuperPlayerVideoId(); model.videoId = new SuperPlayerVideoId();
model.videoId.fileId = "5285890781763144364"; model.videoId!.fileId = "5285890781763144364";
model.playAction = playAction; model.playAction = playAction;
models.add(model); models.add(model);
model = SuperPlayerModel(); model = SuperPlayerModel();
model.appId = 1252463788; model.appId = 1252463788;
model.videoId = new SuperPlayerVideoId(); model.videoId = new SuperPlayerVideoId();
model.videoId.fileId = "4564972819219071568"; model.videoId!.fileId = "4564972819219071568";
model.playAction = playAction; model.playAction = playAction;
models.add(model); models.add(model);
model = SuperPlayerModel(); model = SuperPlayerModel();
model.appId = 1252463788; model.appId = 1252463788;
model.videoId = new SuperPlayerVideoId(); model.videoId = new SuperPlayerVideoId();
model.videoId.fileId = "4564972819219071668"; model.videoId!.fileId = "4564972819219071668";
model.playAction = playAction; model.playAction = playAction;
models.add(model); models.add(model);
model = SuperPlayerModel(); model = SuperPlayerModel();
model.appId = 1252463788; model.appId = 1252463788;
model.videoId = new SuperPlayerVideoId(); model.videoId = new SuperPlayerVideoId();
model.videoId.fileId = "4564972819219071679"; model.videoId!.fileId = "4564972819219071679";
model.playAction = playAction; model.playAction = playAction;
models.add(model); models.add(model);
model = SuperPlayerModel(); model = SuperPlayerModel();
model.appId = 1252463788; model.appId = 1252463788;
model.videoId = new SuperPlayerVideoId(); model.videoId = new SuperPlayerVideoId();
model.videoId.fileId = "4564972819219081699"; model.videoId!.fileId = "4564972819219081699";
model.playAction = playAction; model.playAction = playAction;
models.add(model); models.add(model);
...@@ -203,7 +204,7 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> { ...@@ -203,7 +204,7 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> {
setState(() { setState(() {
if (videoModels.isNotEmpty) { if (videoModels.isNotEmpty) {
_controller.playWithModel(videoModels[0]); playCurrentModel(videoModels[0]);
} else { } else {
EasyLoading.showError("video list request error"); EasyLoading.showError("video list request error");
} }
......
...@@ -15,7 +15,7 @@ class DemoTXLivePlayer extends StatefulWidget { ...@@ -15,7 +15,7 @@ class DemoTXLivePlayer extends StatefulWidget {
class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingObserver{ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingObserver{
TXLivePlayerController _controller; late TXLivePlayerController _controller;
double _aspectRatio = 0; double _aspectRatio = 0;
double _progress = 0.0; double _progress = 0.0;
int _volume = 100; int _volume = 100;
...@@ -36,7 +36,7 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO ...@@ -36,7 +36,7 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO
if(event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_PROGRESS) { if(event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_PROGRESS) {
_progress = event["EVT_PLAY_PROGRESS"].toDouble(); _progress = event["EVT_PLAY_PROGRESS"].toDouble();
_maxLiveProgressTime = _progress >= _maxLiveProgressTime ? _progress : _maxLiveProgressTime; _maxLiveProgressTime = _progress >= _maxLiveProgressTime ? _progress : _maxLiveProgressTime;
progressSliderKey.currentState.updatePorgess(1, _maxLiveProgressTime); progressSliderKey.currentState?.updatePorgess(1, _maxLiveProgressTime);
}else if (event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_BEGIN || event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) {//首帧出现 }else if (event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_BEGIN || event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) {//首帧出现
_isStop = false; _isStop = false;
...@@ -63,7 +63,7 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO ...@@ -63,7 +63,7 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO
}); });
_controller.onPlayerState.listen((event) {//订阅状态变化 _controller.onPlayerState.listen((event) {//订阅状态变化
debugPrint("播放状态 ${event.name}"); debugPrint("播放状态 ${event!.name}");
}); });
await SuperPlayerPlugin.setConsoleEnabled(true); await SuperPlayerPlugin.setConsoleEnabled(true);
......
...@@ -15,7 +15,7 @@ class DemoTXVodPlayer extends StatefulWidget { ...@@ -15,7 +15,7 @@ class DemoTXVodPlayer extends StatefulWidget {
class _DemoTXVodlayerState extends State<DemoTXVodPlayer> class _DemoTXVodlayerState extends State<DemoTXVodPlayer>
with WidgetsBindingObserver { with WidgetsBindingObserver {
TXVodPlayerController _controller; late TXVodPlayerController _controller;
double _aspectRatio = 0; double _aspectRatio = 0;
double _currentProgress = 0.0; double _currentProgress = 0.0;
bool _isMute = false; bool _isMute = false;
...@@ -37,19 +37,19 @@ class _DemoTXVodlayerState extends State<DemoTXVodPlayer> ...@@ -37,19 +37,19 @@ class _DemoTXVodlayerState extends State<DemoTXVodPlayer>
_controller = TXVodPlayerController(); _controller = TXVodPlayerController();
_controller.onPlayerState.listen((val) { _controller.onPlayerState.listen((val) {
debugPrint("播放状态 ${val.name}"); debugPrint("播放状态 ${val?.name}");
}); });
_controller.onPlayerEventBroadcast.listen((event) async { _controller.onPlayerEventBroadcast.listen((event) async {
//订阅状态变化 //订阅状态变化
if (event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_BEGIN || event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) { if (event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_BEGIN || event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) {
EasyLoading.dismiss(); EasyLoading.dismiss();
_supportedBitrates = await _controller.getSupportedBitrates(); _supportedBitrates = (await _controller.getSupportedBitrates())!;
} else if (event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_PROGRESS) { } else if (event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_PROGRESS) {
_currentProgress = event[TXVodPlayEvent.EVT_PLAY_PROGRESS].toDouble(); _currentProgress = event[TXVodPlayEvent.EVT_PLAY_PROGRESS].toDouble();
double videoDuration = event[TXVodPlayEvent.EVT_PLAY_DURATION].toDouble(); // 总播放时长,转换后的单位 秒 double videoDuration = event[TXVodPlayEvent.EVT_PLAY_DURATION].toDouble(); // 总播放时长,转换后的单位 秒
progressSliderKey.currentState.updatePorgess(_currentProgress/videoDuration, videoDuration); progressSliderKey.currentState?.updatePorgess(_currentProgress/videoDuration, videoDuration);
} }
}); });
...@@ -294,7 +294,7 @@ class _DemoTXVodlayerState extends State<DemoTXVodPlayer> ...@@ -294,7 +294,7 @@ class _DemoTXVodlayerState extends State<DemoTXVodPlayer>
), ),
new GestureDetector( new GestureDetector(
onTap: () async { onTap: () async {
TXPlayerState state = _controller.playState; TXPlayerState? state = _controller.playState;
if (state != TXPlayerState.disposed && if (state != TXPlayerState.disposed &&
state != TXPlayerState.stopped) { state != TXPlayerState.stopped) {
enableHardware = !enableHardware; enableHardware = !enableHardware;
......
...@@ -37,7 +37,7 @@ class _MyAppState extends State<MyApp> { ...@@ -37,7 +37,7 @@ class _MyAppState extends State<MyApp> {
// Platform messages are asynchronous, so we initialize in an async method. // Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async { Future<void> initPlatformState() async {
String platformVersion; String? platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException. // Platform messages may fail, so we use a try/catch PlatformException.
try { try {
platformVersion = await SuperPlayerPlugin.platformVersion; platformVersion = await SuperPlayerPlugin.platformVersion;
...@@ -51,7 +51,7 @@ class _MyAppState extends State<MyApp> { ...@@ -51,7 +51,7 @@ class _MyAppState extends State<MyApp> {
if (!mounted) return; if (!mounted) return;
setState(() { setState(() {
_platformVersion = platformVersion; _platformVersion = platformVersion!;
}); });
} }
......
part of SuperPlayer; part of demo_super_player_lib;
/// v2 request data parser /// v2 request data parser
class PlayInfoParserV2 implements PlayInfoParser { class PlayInfoParserV2 implements PlayInfoParser {
...@@ -64,19 +64,19 @@ class PlayInfoParserV2 implements PlayInfoParser { ...@@ -64,19 +64,19 @@ class PlayInfoParserV2 implements PlayInfoParser {
} }
int version = root['version']; int version = root['version'];
if (version == 2) { if (version == 2) {
coverUrl = root['coverInfo']['coverUrl']; coverUrl = root['coverInfo']['coverUrl'] ?? "";
Map<String, dynamic> videInfoRoot = root['videoInfo']; Map<String, dynamic> videInfoRoot = root['videoInfo'];
defaultVideoClassification = defaultVideoClassification =
root['playerInfo']['defaultVideoClassification']; root['playerInfo']['defaultVideoClassification'] ?? "";
_parseVideoClassificationList(root['playerInfo']); _parseVideoClassificationList(root['playerInfo']);
imageSpriteInfo = _parseImageSpriteInfo(root['imageSpriteInfo']); imageSpriteInfo = _parseImageSpriteInfo(root['imageSpriteInfo']);
keyFrameDescInfo = _parseKeyFrameDescInfo(root['keyFrameDescInfo']); keyFrameDescInfo = _parseKeyFrameDescInfo(root['keyFrameDescInfo']);
duration = videInfoRoot['sourceVideo']['duration']; duration = videInfoRoot['sourceVideo']['duration'] ?? 0;
name = videInfoRoot['basicInfo']['name']; name = videInfoRoot['basicInfo']['name'] ?? "";
_parseMastPlayInfo(videInfoRoot); _parseMastPlayInfo(videInfoRoot);
_parseTranscodeList(videInfoRoot); _parseTranscodeList(videInfoRoot);
...@@ -86,7 +86,7 @@ class PlayInfoParserV2 implements PlayInfoParser { ...@@ -86,7 +86,7 @@ class PlayInfoParserV2 implements PlayInfoParser {
} }
} }
List<PlayKeyFrameDescInfo>? _parseKeyFrameDescInfo(Map<String,dynamic> keyFrameDescInfo) { List<PlayKeyFrameDescInfo>? _parseKeyFrameDescInfo(dynamic keyFrameDescInfo) {
if(null != keyFrameDescInfo && keyFrameDescInfo.isNotEmpty) { if(null != keyFrameDescInfo && keyFrameDescInfo.isNotEmpty) {
List<dynamic> keyFrameDescList = keyFrameDescInfo['keyFrameDescList']; List<dynamic> keyFrameDescList = keyFrameDescInfo['keyFrameDescList'];
if(keyFrameDescList.isNotEmpty) { if(keyFrameDescList.isNotEmpty) {
...@@ -104,7 +104,7 @@ class PlayInfoParserV2 implements PlayInfoParser { ...@@ -104,7 +104,7 @@ class PlayInfoParserV2 implements PlayInfoParser {
return null; return null;
} }
PlayImageSpriteInfo? _parseImageSpriteInfo(Map<String,dynamic> imageSpriteInfo) { PlayImageSpriteInfo? _parseImageSpriteInfo(dynamic imageSpriteInfo) {
if(null != imageSpriteInfo && imageSpriteInfo.isNotEmpty) { if(null != imageSpriteInfo && imageSpriteInfo.isNotEmpty) {
List<dynamic> imageSpriteList = imageSpriteInfo['imageSpriteList']; List<dynamic> imageSpriteList = imageSpriteInfo['imageSpriteList'];
if(imageSpriteList.isNotEmpty) { if(imageSpriteList.isNotEmpty) {
...@@ -124,17 +124,17 @@ class PlayInfoParserV2 implements PlayInfoParser { ...@@ -124,17 +124,17 @@ class PlayInfoParserV2 implements PlayInfoParser {
} }
void _parseVideoClassificationList(Map<String, dynamic> playerInfoRoot) { void _parseVideoClassificationList(Map<String, dynamic> playerInfoRoot) {
List<dynamic> videoClassificationRoot = playerInfoRoot['videoClassification'];
List<VideoClassification> classList = []; List<VideoClassification> classList = [];
if(null != videoClassificationRoot) { if(null != playerInfoRoot['videoClassification']) {
List<dynamic> videoClassificationRoot = playerInfoRoot['videoClassification'];
for(Map<String, dynamic> object in videoClassificationRoot) { for(Map<String, dynamic> object in videoClassificationRoot) {
VideoClassification classification = new VideoClassification(); VideoClassification classification = new VideoClassification();
classification.id =object["id"]; classification.id =object["id"];
classification.name = object["name"]; classification.name = object["name"];
List<int> definitionList = []; List<int> definitionList = [];
List<dynamic> array = object['definitionList']; if(null != object['definitionList']) {
if(null != array) { List<dynamic> array = object['definitionList'];
for(int definition in array) { for(int definition in array) {
definitionList.add(definition); definitionList.add(definition);
} }
...@@ -148,16 +148,16 @@ class PlayInfoParserV2 implements PlayInfoParser { ...@@ -148,16 +148,16 @@ class PlayInfoParserV2 implements PlayInfoParser {
void _parseMastPlayInfo(Map<String, dynamic> videInfoRoot) { void _parseMastPlayInfo(Map<String, dynamic> videInfoRoot) {
Map<String, dynamic> masterPlayRoot = videInfoRoot['masterPlayList']; if (null != videInfoRoot['masterPlayList']) {
if (null != masterPlayRoot) { Map<String, dynamic> masterPlayRoot = videInfoRoot['masterPlayList'];
masterPlayList = PlayInfoStream(); masterPlayList = PlayInfoStream();
masterPlayList?.url = masterPlayRoot['url']; masterPlayList?.url = masterPlayRoot['url'];
} }
} }
void _parseTranscodeList(Map<String, dynamic> videInfoRoot) { void _parseTranscodeList(Map<String, dynamic> videInfoRoot) {
List<dynamic> transcodeListRoot = videInfoRoot['transcodeList']; if (null != videInfoRoot['transcodeList']) {
if (null != transcodeListRoot) { List<dynamic> transcodeListRoot = videInfoRoot['transcodeList'];
List<PlayInfoStream> streamList = _parseStreamList(transcodeListRoot); List<PlayInfoStream> streamList = _parseStreamList(transcodeListRoot);
for(PlayInfoStream stream in streamList) { for(PlayInfoStream stream in streamList) {
if(videoClassificationList.isNotEmpty) { if(videoClassificationList.isNotEmpty) {
......
part of SuperPlayer; part of demo_super_player_lib;
/// v4 request data parser /// v4 request data parser
class PlayInfoParserV4 implements PlayInfoParser { class PlayInfoParserV4 implements PlayInfoParser {
...@@ -50,52 +50,52 @@ class PlayInfoParserV4 implements PlayInfoParser { ...@@ -50,52 +50,52 @@ class PlayInfoParserV4 implements PlayInfoParser {
Map<String, dynamic> media = root['media']; Map<String, dynamic> media = root['media'];
mRequestContext = root['context']; mRequestContext = root['context'];
if (media.isNotEmpty) { if (media.isNotEmpty) {
Map<String, dynamic> basicInfo = media['basicInfo']; if (null != media['basicInfo']) {
if (null != basicInfo) { Map<String, dynamic> basicInfo = media['basicInfo'];
name = basicInfo['name']; name = basicInfo['name'] ?? "";
description = basicInfo['description']; description = basicInfo['description'] ?? "";
coverUrl = basicInfo['coverUrl']; coverUrl = basicInfo['coverUrl'] ?? "";
duration = basicInfo['duration']; duration = basicInfo['duration'] ?? "";
} }
String audioVideoType = media['audioVideoType']; String audioVideoType = media['audioVideoType'];
if (audioVideoType == 'AdaptiveDynamicStream') { if (audioVideoType == 'AdaptiveDynamicStream') {
Map<String, dynamic> streamingInfo = media['streamingInfo']; if (null != media['streamingInfo']) {
if (null != streamingInfo) { Map<String, dynamic> streamingInfo = media['streamingInfo'];
Map<String, dynamic> plainOutputRoot = streamingInfo['plainOutput']; if (null != streamingInfo['plainOutput']) {
if (null != plainOutputRoot) { Map<String, dynamic> plainOutputRoot = streamingInfo['plainOutput'];
_url = plainOutputRoot['url']; _url = plainOutputRoot['url'] ?? "";
_parseSubStreams(plainOutputRoot['subStreams']); _parseSubStreams(plainOutputRoot['subStreams']);
} }
List<dynamic> drmoutInfo = streamingInfo['drmOutput']; if (null != streamingInfo['drmOutput']) {
if (null != drmoutInfo) { List<dynamic> drmoutInfo = streamingInfo['drmOutput'];
encryptedStreamingInfoList = []; encryptedStreamingInfoList = [];
for (Map<String, dynamic> drmout in drmoutInfo) { for (Map<String, dynamic> drmout in drmoutInfo) {
EncryptedStreamingInfo info = new EncryptedStreamingInfo(); EncryptedStreamingInfo info = new EncryptedStreamingInfo();
drmType = drmout['type']; drmType = drmout['type'] ?? "";
info.drmType = drmType; info.drmType = drmType;
info.url = drmout['url']; info.url = drmout['url'];
encryptedStreamingInfoList.add(info); encryptedStreamingInfoList.add(info);
_parseSubStreams(drmout['subStreams']); _parseSubStreams(drmout['subStreams']);
} }
} }
token = streamingInfo["drmToken"]; token = streamingInfo["drmToken"] ?? "";
} }
} else if (audioVideoType == 'Transcode') { } else if (audioVideoType == 'Transcode') {
Map<String, dynamic> transcodeInfo = media['transcodeInfo']; Map<String, dynamic> transcodeInfo = media['transcodeInfo'];
if (transcodeInfo.isNotEmpty) { if (transcodeInfo.isNotEmpty) {
_url = transcodeInfo['url']; _url = transcodeInfo['url'] ?? "";
} }
} else if (audioVideoType == 'Original') { } else if (audioVideoType == 'Original') {
Map<String, dynamic> originalInfo = media['originalInfo']; Map<String, dynamic> originalInfo = media['originalInfo'];
if (originalInfo.isNotEmpty) { if (originalInfo.isNotEmpty) {
_url = originalInfo['url']; _url = originalInfo['url'] ?? "";
} }
} }
Map<String, dynamic> imageSpriteInfoJson = media['imageSpriteInfo']; if (null != media['imageSpriteInfo']) {
if (null != imageSpriteInfoJson) { Map<String, dynamic> imageSpriteInfoJson = media['imageSpriteInfo'];
imageSpriteInfo = PlayImageSpriteInfo(); imageSpriteInfo = PlayImageSpriteInfo();
imageSpriteInfo?.webVttUrl = imageSpriteInfoJson['webVttUrl']; imageSpriteInfo?.webVttUrl = imageSpriteInfoJson['webVttUrl'] ?? "";
List<String> imageUrls = imageSpriteInfoJson['imageUrls']; List<String> imageUrls = imageSpriteInfoJson['imageUrls'];
imageSpriteInfo?.imageUrls = imageUrls; imageSpriteInfo?.imageUrls = imageUrls;
} }
...@@ -104,10 +104,11 @@ class PlayInfoParserV4 implements PlayInfoParser { ...@@ -104,10 +104,11 @@ class PlayInfoParserV4 implements PlayInfoParser {
} }
} }
_parseSubStreams(List<dynamic> substreams) { _parseSubStreams(dynamic substreams) {
if (null != substreams) { if (null != substreams) {
List<dynamic> substreamList = substreams;
resolutionNameList = []; resolutionNameList = [];
for (Map<String, dynamic> substream in substreams) { for (Map<String, dynamic> substream in substreamList) {
ResolutionName resolutionName = ResolutionName(); ResolutionName resolutionName = ResolutionName();
resolutionName.width = substream['width']; resolutionName.width = substream['width'];
resolutionName.height = substream['height']; resolutionName.height = substream['height'];
...@@ -119,8 +120,8 @@ class PlayInfoParserV4 implements PlayInfoParser { ...@@ -119,8 +120,8 @@ class PlayInfoParserV4 implements PlayInfoParser {
} }
_parseKeyFrameDescList(Map<String, dynamic> media) { _parseKeyFrameDescList(Map<String, dynamic> media) {
Map<String, dynamic> keyFrameDescInfoJson = media['keyFrameDescInfo']; if (null != media['keyFrameDescInfo']) {
if (null != keyFrameDescInfoJson) { Map<String, dynamic> keyFrameDescInfoJson = media['keyFrameDescInfo'];
keyFrameDescInfo = []; keyFrameDescInfo = [];
List<Map<String, dynamic>> keyFrameDescList = keyFrameDescInfoJson['keyFrameDescList']; List<Map<String, dynamic>> keyFrameDescList = keyFrameDescInfoJson['keyFrameDescList'];
for (Map<String, dynamic> keyFrameDesc in keyFrameDescList) { for (Map<String, dynamic> keyFrameDesc in keyFrameDescList) {
......
part of SuperPlayer; part of demo_super_player_lib;
/// play info parser interface /// play info parser interface
abstract class PlayInfoParser { abstract class PlayInfoParser {
......
part of SuperPlayer; part of demo_super_player_lib;
/// request handler with tencent fileId /// request handler with tencent fileId
class PlayInfoProtocol { class PlayInfoProtocol {
......
part of SuperPlayer; part of demo_super_player_lib;
/// request data handler /// request data handler
class SuperVodDataLoader { class SuperVodDataLoader {
......
part of SuperPlayer; part of demo_super_player_lib;
/// colors resource /// colors resource
class ColorResource { class ColorResource {
static const COLOR_MAIN_THEME = 0xFFFF4C58; static const COLOR_MAIN_THEME = 0xFFFF4C58;
......
part of SuperPlayer; part of demo_super_player_lib;
/// string resource /// string resource
class StringResource { class StringResource {
......
library demo_super_player_lib;
import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'dart:io';
import 'dart:math';
import 'package:auto_orientation/auto_orientation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:super_player/super_player.dart';
part 'superplayer_observer.dart';
part 'superplayer_controller.dart';
part 'cgi/play_info_parser_v2.dart';
part 'cgi/play_info_parser_v4.dart';
part 'cgi/playinfo_parser.dart';
part 'cgi/playinfo_protocol.dart';
part 'cgi/super_vod_data_loader.dart';
part 'model/superplayer_define.dart';
part 'model/superplayer_model.dart';
part 'tools/video_quality_utils.dart';
part 'ui/superplayer_bottom_view.dart';
part 'ui/superplayer_quality_view.dart';
part 'ui/superplayer_title_view.dart';
part 'ui/superplayer_widget.dart';
part 'common/color_resource.dart';
part 'common/string_resource.dart';
\ No newline at end of file
part of SuperPlayer; part of demo_super_player_lib;
enum SuperPlayerState { enum SuperPlayerState {
INIT, // 初始状态 INIT, // 初始状态
......
part of SuperPlayer; part of demo_super_player_lib;
class PlayInfoStream { class PlayInfoStream {
int height = 0; int height = 0;
......
part of SuperPlayer; part of demo_super_player_lib;
/// superplayer play controller /// superplayer play controller
class SuperPlayerController { class SuperPlayerController {
static const TAG = "SuperPlayerController"; static const TAG = "SuperPlayerController";
...@@ -51,7 +50,7 @@ class SuperPlayerController { ...@@ -51,7 +50,7 @@ class SuperPlayerController {
void _initVodPlayer() async { void _initVodPlayer() async {
_vodPlayerController = new TXVodPlayerController(); _vodPlayerController = new TXVodPlayerController();
await _vodPlayerController?.initialize(); await _vodPlayerController?.initialize();
_vodPlayerController?.onPlayerEventBroadcast.listen((event) async { _vodPlayerController?.onPlayerEventBroadcast?.listen((event) async {
int eventCode = event['event']; int eventCode = event['event'];
switch (eventCode) { switch (eventCode) {
case TXVodPlayEvent.PLAY_EVT_VOD_PLAY_PREPARED: // vodPrepared case TXVodPlayEvent.PLAY_EVT_VOD_PLAY_PREPARED: // vodPrepared
......
part of SuperPlayer; part of demo_super_player_lib;
/// superplayer's bridge between widget and controller /// superplayer's bridge between widget and controller
class _SuperPlayerObserver { class _SuperPlayerObserver {
......
part of SuperPlayer; part of demo_super_player_lib;
/// video quality utils /// video quality utils
class VideoQualityUtils { class VideoQualityUtils {
......
part of SuperPlayer; part of demo_super_player_lib;
/// slider /// slider
class VideoBottomView extends StatefulWidget { class VideoBottomView extends StatefulWidget {
......
part of SuperPlayer; part of demo_super_player_lib;
class QualityListView extends StatefulWidget { class QualityListView extends StatefulWidget {
final List<VideoQuality>? _qualityList; final List<VideoQuality>? _qualityList;
......
part of SuperPlayer; part of demo_super_player_lib;
class _VideoTitleView extends StatefulWidget { class _VideoTitleView extends StatefulWidget {
......
part of SuperPlayer; part of demo_super_player_lib;
final double topBottomOffset = -2; final double topBottomOffset = -2;
...@@ -493,7 +493,9 @@ class SuperPlayerFullScreenState extends State<SuperPlayerFullScreenView> { ...@@ -493,7 +493,9 @@ class SuperPlayerFullScreenState extends State<SuperPlayerFullScreenView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return WillPopScope( return WillPopScope(
child: SuperPlayerView(widget._playController, viewKey: widget.key), child: Scaffold(
body: SuperPlayerView(widget._playController, viewKey: widget.key),
),
onWillPop: _onFullScreenWillPop, onWillPop: _onFullScreenWillPop,
); );
} }
......
...@@ -36,12 +36,12 @@ class _DemoBitrateCheckboxState extends State<DemoBitrateCheckbox> { ...@@ -36,12 +36,12 @@ class _DemoBitrateCheckboxState extends State<DemoBitrateCheckbox> {
Text("码率$s", style: TextStyle(color: Colors.white),), Text("码率$s", style: TextStyle(color: Colors.white),),
Theme(data: ThemeData( Theme(data: ThemeData(
unselectedWidgetColor: Colors.white,), unselectedWidgetColor: Colors.white,),
child: Radio( child: Radio<int> (
value: e["index"], value: e["index"],
groupValue: this.widget.index, groupValue: this.widget.index,
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
this.widget.index = value; this.widget.index = value!;
}); });
}, },
), ),
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'demo_define.dart'; import 'demo_define.dart';
class DemoExpansionPanelList extends StatefulWidget { class DemoExpansionPanelList extends StatefulWidget {
...@@ -8,13 +7,11 @@ class DemoExpansionPanelList extends StatefulWidget { ...@@ -8,13 +7,11 @@ class DemoExpansionPanelList extends StatefulWidget {
} }
class _DemoExpansionPanelListState extends State<DemoExpansionPanelList> { class _DemoExpansionPanelListState extends State<DemoExpansionPanelList> {
List<int> mList; //组成一个int类型数组,用来控制索引 List<int> mList = []; //组成一个int类型数组,用来控制索引
List<ExpandStateBean> expandStateList; //开展开的状态列表,ExpandStateBean是自定义的类 List<ExpandStateBean> expandStateList = []; //开展开的状态列表,ExpandStateBean是自定义的类
//构造方法,调用这个类的时候自动执行 //构造方法,调用这个类的时候自动执行
_DemoExpansionPanelListState(){ _DemoExpansionPanelListState(){
mList=new List();
expandStateList=new List();
//遍历两个List进行赋值 //遍历两个List进行赋值
for(int i=0;i<1;i++){ for(int i=0;i<1;i++){
mList.add(i); mList.add(i);
......
...@@ -9,7 +9,7 @@ class DemoInputDialog extends StatefulWidget { ...@@ -9,7 +9,7 @@ class DemoInputDialog extends StatefulWidget {
int appId = 0; int appId = 0;
String fileId = ""; String fileId = "";
DemoInputDialogFinishCallback callback; DemoInputDialogFinishCallback callback;
bool showFileEdited; bool showFileEdited = true;
DemoInputDialog(this.url, this.appId, this.fileId, this.callback, {bool showFileEdited = true}) : super () {this.showFileEdited = showFileEdited;} DemoInputDialog(this.url, this.appId, this.fileId, this.callback, {bool showFileEdited = true}) : super () {this.showFileEdited = showFileEdited;}
...@@ -18,9 +18,9 @@ class DemoInputDialog extends StatefulWidget { ...@@ -18,9 +18,9 @@ class DemoInputDialog extends StatefulWidget {
} }
class _DemoInputDialogState extends State<DemoInputDialog> { class _DemoInputDialogState extends State<DemoInputDialog> {
TextEditingController _urlController; late TextEditingController _urlController;
TextEditingController _appIdController; late TextEditingController _appIdController;
TextEditingController _fileIdController; late TextEditingController _fileIdController;
@override @override
void initState() { void initState() {
......
...@@ -49,10 +49,10 @@ class VideoSliderState extends State<VideoSliderView> { ...@@ -49,10 +49,10 @@ class VideoSliderState extends State<VideoSliderView> {
isSliding = false; isSliding = false;
_currentProgress = value; _currentProgress = value;
if (widget._controller is TXVodPlayerController) { if (widget._controller is TXVodPlayerController) {
TXVodPlayerController controller = widget._controller; TXVodPlayerController controller = widget._controller as TXVodPlayerController;
controller.seek(_currentProgress * _videoDuration); controller.seek(_currentProgress * _videoDuration);
} else if (widget._controller is TXLivePlayerController) { } else if (widget._controller is TXLivePlayerController) {
TXLivePlayerController controller = widget._controller; TXLivePlayerController controller = widget._controller as TXLivePlayerController;
controller.seek(_currentProgress * _videoDuration); controller.seek(_currentProgress * _videoDuration);
} }
......
...@@ -15,7 +15,7 @@ class TreePage extends StatefulWidget { ...@@ -15,7 +15,7 @@ class TreePage extends StatefulWidget {
} }
class _TreePageState extends State<TreePage> { class _TreePageState extends State<TreePage> {
List<TreeData> _datas = List(); List<TreeData> _datas = [];
ScrollController _scrollController = ScrollController(); ScrollController _scrollController = ScrollController();
int _panelIndex = 0; //展开下标 int _panelIndex = 0; //展开下标
List<IconData> _icons = [ List<IconData> _icons = [
...@@ -153,7 +153,7 @@ class _TreePageState extends State<TreePage> { ...@@ -153,7 +153,7 @@ class _TreePageState extends State<TreePage> {
return DemoTXLivePlayer(); return DemoTXLivePlayer();
}else if (i == 1) { }else if (i == 1) {
return DemoTXVodPlayer(); return DemoTXVodPlayer();
} else if(i == 2) { } else {
return DemoSuperplayer(); return DemoSuperplayer();
} }
} }
......
...@@ -75,7 +75,7 @@ packages: ...@@ -75,7 +75,7 @@ packages:
name: flutter_easyloading name: flutter_easyloading
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.3" version: "3.0.5"
flutter_spinkit: flutter_spinkit:
dependency: transitive dependency: transitive
description: description:
...@@ -148,7 +148,7 @@ packages: ...@@ -148,7 +148,7 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "1.0.1" version: "1.0.2"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
......
...@@ -6,7 +6,8 @@ description: Demonstrates how to use the super_player plugin. ...@@ -6,7 +6,8 @@ description: Demonstrates how to use the super_player plugin.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
environment: environment:
sdk: ">=2.7.0 <3.0.0" sdk: '>=2.12.0 <3.0.0'
flutter: ">=1.20.0"
dependencies: dependencies:
flutter: flutter:
......
...@@ -19,7 +19,7 @@ void main() { ...@@ -19,7 +19,7 @@ void main() {
expect( expect(
find.byWidgetPredicate( find.byWidgetPredicate(
(Widget widget) => widget is Text && (Widget widget) => widget is Text &&
widget.data.startsWith('Running on:'), widget.data!.startsWith('Running on:'),
), ),
findsOneWidget, findsOneWidget,
); );
......
...@@ -578,7 +578,11 @@ static const int uninitialized = -1; ...@@ -578,7 +578,11 @@ static const int uninitialized = -1;
- (void)setToken:(NSString *)token - (void)setToken:(NSString *)token
{ {
if(_txVodPlayer != nil) { if(_txVodPlayer != nil) {
_txVodPlayer.token = token; if(token && token.length > 0) {
_txVodPlayer.token = token;
} else {
_txVodPlayer.token = nil;
}
} }
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'super_player' s.name = 'super_player'
s.version = '1.0.1' s.version = '1.0.2'
s.summary = 'player plugin.' s.summary = 'player plugin.'
s.description = <<-DESC s.description = <<-DESC
player plugin. player plugin.
...@@ -17,7 +17,7 @@ player plugin. ...@@ -17,7 +17,7 @@ player plugin.
s.public_header_files = 'Classes/**/*.h' s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter' s.dependency 'Flutter'
s.dependency 'TXLiteAVSDK_Player' s.dependency 'TXLiteAVSDK_Player'
s.platform = :ios, '8.0' s.platform = :ios, '9.0'
s.static_framework = true s.static_framework = true
# Flutter.framework does not contain a i386 slice. # Flutter.framework does not contain a i386 slice.
......
...@@ -2,37 +2,17 @@ ...@@ -2,37 +2,17 @@
library SuperPlayer; library SuperPlayer;
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:core'; import 'dart:core';
import 'dart:io';
import 'dart:math';
import 'dart:ui';
import 'package:auto_orientation/auto_orientation.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
part 'Core/superplayer_plugin.dart';
part 'Core/tools/log_utils.dart';
part 'Core/txliveplayer_controller.dart'; part 'Core/txliveplayer_controller.dart';
part 'Core/txvodplayer_controller.dart'; part 'Core/txplayer_controller.dart';
part 'Core/txplayer_define.dart'; part 'Core/txplayer_define.dart';
part 'Core/superplayer_plugin.dart';
part 'Core/txplayer_widget.dart'; part 'Core/txplayer_widget.dart';
part 'Core/txplayer_controller.dart';
part 'Core/txvodplayer_config.dart'; part 'Core/txvodplayer_config.dart';
part 'Core/tools/video_quality_utils.dart'; part 'Core/txvodplayer_controller.dart';
part 'Core/tools/log_utils.dart'; \ No newline at end of file
part 'Core/superplayer/cgi/super_vod_data_loader.dart';
part 'Core/superplayer/cgi/play_info_parser_v2.dart';
part 'Core/superplayer/cgi/play_info_parser_v4.dart';
part 'Core/superplayer/cgi/playinfo_parser.dart';
part 'Core/superplayer/cgi/playinfo_protocol.dart';
part 'Core/superplayer/superplater_observer.dart';
part 'Core/superplayer/superplayer_controller.dart';
part 'Core/superplayer/model/superplayer_define.dart';
part 'Core/superplayer/model/superplayer_model.dart';
part 'Core/superplayer/ui/superplayer_widget.dart';
part 'Core/superplayer/ui/superplayer_bottom_view.dart';
part 'Core/superplayer/ui/superplayer_quality_view.dart';
part 'Core/superplayer/ui/superplayer_title_view.dart';
part 'Core/common/string_resource.dart';
part 'Core/common/color_resource.dart';
\ No newline at end of file
...@@ -8,13 +8,6 @@ packages: ...@@ -8,13 +8,6 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.8.2" version: "2.8.2"
auto_orientation:
dependency: "direct main"
description:
name: auto_orientation
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.1"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
......
name: super_player name: super_player
description: player plugin. description: player plugin.
version: 1.0.1 version: 1.0.2
author: author:
homepage: homepage:
...@@ -12,8 +12,6 @@ dependencies: ...@@ -12,8 +12,6 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
auto_orientation: ^2.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论