提交 3cdf0ab2 authored 作者: kongdywang's avatar kongdywang

fix bug

上级 a5db668c
...@@ -172,6 +172,7 @@ class _TestState extends State<Test> { ...@@ -172,6 +172,7 @@ class _TestState extends State<Test> {
Future<void> initPlayer() async { Future<void> initPlayer() async {
await _controller.initialize(); await _controller.initialize();
await _controller.setConfig(FTXVodPlayConfig());
await _controller.startPlay(_url); await _controller.startPlay(_url);
} }
...@@ -320,6 +321,117 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> { ...@@ -320,6 +321,117 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> {
} }
``` ```
## 视频下载能力的使用
### 预下载
视频预下载能力依赖于`TXVodDownloadController`,使用其可对视频进行预下载和监听
**接口**
- 预下载视频
```dart
int taskId = await TXVodDownloadController.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) {
print('taskID=${taskId} ,url=${url}, code=${code} , msg=${msg}');
} );
```
- 停止预下载
```dart
TXVodDownloadController.instance.stopPreLoad(taskId);
```
taskId从启动预下载的接口获得
### 视频下载
视频下载能力依赖于`TXVodDownloadController`,使用其可对视频进行下载和监听
**接口**
- 下载视频
```dart
TXVodDownloadMedialnfo downloadMedialnfo = TXVodDownloadMedialnfo();
TXVodDownloadDataSource dataSource = TXVodDownloadDataSource();
dataSource.appId = appId;
dataSource.fileId = fileId;
dataSource.pSign = pSign;
downloadMedialnfo.dataSource = dataSource;
TXVodDownloadController.instance.startDonwload(downloadMedialnfo);
```
也可以使用url下载。
```dart
TXVodDownloadMedialnfo downloadMedialnfo = TXVodDownloadMedialnfo();
downloadMedialnfo.url = videoUrl;
TXVodDownloadController.instance.startDonwload(downloadMedialnfo);
```
视频url下载不支持嵌套m3u8和mp4下载。
下载也可以指定username,用来区分不同用户的下载,不传递的话,默认为default
```dart
downloadMedialnfo.userName = username;
```
- 停止下载
```dart
TXVodDownloadController.instance.stopDownload(downloadMedialnfo);
```
- 设置下载请求头
针对部分视频下载的时候,需要设置额外的请求头
```dart
TXVodDownloadController.instance.setDownloadHeaders(headers);
```
- 获得视频的下载信息
该接口可以获得下载中或者已经下载视频的下载信息,可以获得视频的当前缓存地址
```dart
TXVodDownloadController.instance.getDownloadInfo(downloadMedialnfo);
```
- 获得所有视频的下载信息
```dart
TXVodDownloadController.instance.getDownloadList();
```
- 设置视频下载监听
该接口设置的视频下载监听为全局监听,所有视频的下载进度都会在该方法中回调,重复调用的话会前后覆盖
```dart
TXVodDownloadController.instance.setDownloadObserver((event, info) {
// donwload state $event ,donwload info $info
}, (errorCode, errorMsg, info) {
// donwload error code $errorCode,error msg $errorMsg
});
```
- 视频下载事件
| 参数名 | 值 | 描述 |
| ------ | ------ | ------------------ |
| NO_ERROR | 301 | 视频下载开始 |
| EVENT_DOWNLOAD_PROGRESS | 302 | 视频下载中,进度回调 |
| EVENT_DOWNLOAD_STOP | 303 | 视频下载停止 |
| EVENT_DOWNLOAD_FINISH | 304 | 视频下载完成 |
| EVENT_DOWNLOAD_ERROR | 305 | 视频下载错误 |
## 深度定制开发指引 ## 深度定制开发指引
腾讯云播放器SDK Flutter插件对原生播放器能力进行了封装, 如果您要进行深度定制开发,建议采用如下方法: 腾讯云播放器SDK Flutter插件对原生播放器能力进行了封装, 如果您要进行深度定制开发,建议采用如下方法:
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter; package com.tencent.vod.flutter;
import android.os.Bundle; import android.os.Bundle;
import com.tencent.rtmp.downloader.TXVodDownloadDataSource;
import com.tencent.rtmp.downloader.TXVodDownloadMediaInfo;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
/**
* 通用工具类
*/
public class CommonUtil { 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) { public static Map<String, Object> getParams(int event, Bundle bundle) {
Map<String, Object> param = new HashMap<>(); Map<String, Object> param = new HashMap<>();
if (event != 0) { if (event != 0) {
...@@ -24,4 +39,35 @@ public class CommonUtil { ...@@ -24,4 +39,35 @@ public class CommonUtil {
return param; 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;
}
} }
...@@ -24,6 +24,17 @@ public class FTXEvent { ...@@ -24,6 +24,17 @@ public class FTXEvent {
// 视频预下载出错 // 视频预下载出错
public static final int EVENT_PREDOWNLOAD_ON_ERROR = 201; 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; public static final int NO_ERROR = 0;
/** /**
* pip 事件 * pip 事件
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
package com.tencent.vod.flutter; package com.tencent.vod.flutter;
import android.app.Activity; import android.app.Activity;
import android.app.AppOpsManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.PictureInPictureParams; import android.app.PictureInPictureParams;
import android.app.RemoteAction; import android.app.RemoteAction;
...@@ -110,7 +111,10 @@ public class FTXPIPManager { ...@@ -110,7 +111,10 @@ public class FTXPIPManager {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
params.mPipParams = new PictureInPictureParams.Builder(); params.mPipParams = new PictureInPictureParams.Builder();
updatePipActions(isPlaying, params); updatePipActions(isPlaying, params);
mActivity.enterPictureInPictureMode(params.mPipParams.build()); boolean enterResult = mActivity.enterPictureInPictureMode(params.mPipParams.build());
if(!enterResult) {
pipResult = FTXEvent.ERROR_PIP_DENIED_PERMISSION;
}
} else { } else {
mActivity.enterPictureInPictureMode(); mActivity.enterPictureInPictureMode();
} }
...@@ -129,6 +133,9 @@ public class FTXPIPManager { ...@@ -129,6 +133,9 @@ public class FTXPIPManager {
if (!isSuccess) { if (!isSuccess) {
pipResult = FTXEvent.ERROR_PIP_DENIED_PERMISSION; pipResult = FTXEvent.ERROR_PIP_DENIED_PERMISSION;
Log.e(TAG, "enterPip failed,because PIP feature is disabled"); Log.e(TAG, "enterPip failed,because PIP feature is disabled");
} else if(!hasPipPermission()) {
pipResult = FTXEvent.ERROR_PIP_DENIED_PERMISSION;
Log.e(TAG, "enterPip failed,because PIP has no permission");
} }
} else { } else {
pipResult = FTXEvent.ERROR_PIP_LOWER_VERSION; pipResult = FTXEvent.ERROR_PIP_LOWER_VERSION;
...@@ -142,6 +149,17 @@ public class FTXPIPManager { ...@@ -142,6 +149,17 @@ public class FTXPIPManager {
return pipResult; return pipResult;
} }
private boolean hasPipPermission() {
AppOpsManager appOpsManager = (AppOpsManager) mActivity.getSystemService(Context.APP_OPS_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int permissionResult = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
android.os.Process.myUid(),mActivity.getPackageName());
return permissionResult == AppOpsManager.MODE_ALLOWED;
} else {
return false;
}
}
public boolean isInPipMode() { public boolean isInPipMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return mActivity.isInPictureInPictureMode(); return mActivity.isInPictureInPictureMode();
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="com.example.super_player_example"> 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 <application
android:label="super_player_example" android:label="super_player_example"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true"
tools:replace="android:label"> tools:replace="android:label">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
......
...@@ -122,10 +122,11 @@ public class FTXFlutterPipActivity extends FlutterActivity { ...@@ -122,10 +122,11 @@ public class FTXFlutterPipActivity extends FlutterActivity {
@Override @Override
public boolean enterPictureInPictureMode(@NonNull PictureInPictureParams params) { public boolean enterPictureInPictureMode(@NonNull PictureInPictureParams params) {
if (null != mEventSink) { boolean enterResult = super.enterPictureInPictureMode(params);
if (enterResult && null != mEventSink) {
mEventSink.success(getParams(EVENT_PIP_MODE_REQUEST_START, null)); mEventSink.success(getParams(EVENT_PIP_MODE_REQUEST_START, null));
} }
return super.enterPictureInPictureMode(params); return enterResult;
} }
private Map<String, Object> getParams(int event, Bundle bundle) { private Map<String, Object> getParams(int event, Bundle bundle) {
......
...@@ -56,8 +56,11 @@ class _DemoTXVodlayerState extends State<DemoTXVodPlayer> ...@@ -56,8 +56,11 @@ class _DemoTXVodlayerState extends State<DemoTXVodPlayer>
} 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(); // 总播放时长,转换后的单位 秒
if (videoDuration == 0.0) {
progressSliderKey.currentState?.updatePorgess(_currentProgress / videoDuration, videoDuration); progressSliderKey.currentState?.updatePorgess(0.0, 0.0);
} else {
progressSliderKey.currentState?.updatePorgess(_currentProgress / videoDuration, videoDuration);
}
} else if (event["event"] == TXVodPlayEvent.PLAY_EVT_GET_PLAYINFO_SUCC) { } else if (event["event"] == TXVodPlayEvent.PLAY_EVT_GET_PLAYINFO_SUCC) {
String? playUrl = event[TXVodPlayEvent.EVT_PLAY_URL]?.toString(); String? playUrl = event[TXVodPlayEvent.EVT_PLAY_URL]?.toString();
} }
......
...@@ -67,6 +67,12 @@ class VideoSliderState extends State<VideoSliderView> { ...@@ -67,6 +67,12 @@ class VideoSliderState extends State<VideoSliderView> {
void updatePorgess(double progress,double totalDuration) { void updatePorgess(double progress,double totalDuration) {
if(!isSliding) { if(!isSliding) {
setState(() { setState(() {
if(progress > 1.0) {
progress = 1.0;
}
if(progress < 0) {
progress = 0;
}
_currentProgress = progress; _currentProgress = progress;
_videoDuration = totalDuration; _videoDuration = totalDuration;
}); });
......
// Copyright (c) 2022 Tencent. All rights reserved.
#import <TXLiteAVSDK_Professional/TXVodDownloadManager.h>
#import <Foundation/Foundation.h>
#import "FTXEvent.h"
@interface CommonUtil : NSObject
+(int)getCacheVideoQuality:(int)width height:(int)pHeight;
+(int)getDownloadEventByState:(int)downloadState;
@end
// 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
...@@ -5,9 +5,11 @@ ...@@ -5,9 +5,11 @@
#import "FTXEvent.h" #import "FTXEvent.h"
#import "FTXDownloadManager.h" #import "FTXDownloadManager.h"
#import <TXLiteAVSDK_Professional/TXVodPreloadManager.h> #import <TXLiteAVSDK_Professional/TXVodPreloadManager.h>
#import <TXLiteAVSDK_Professional/TXVodDownloadManager.h>
#import "FTXEvent.h" #import "FTXEvent.h"
#import "CommonUtil.h"
@interface FTXDownloadManager ()<FlutterStreamHandler, TXVodPreloadManagerDelegate> @interface FTXDownloadManager ()<FlutterStreamHandler, TXVodPreloadManagerDelegate, TXVodDownloadDelegate>
@end @end
...@@ -30,6 +32,11 @@ ...@@ -30,6 +32,11 @@
_eventChannel = [FlutterEventChannel eventChannelWithName:@"cloud.tencent.com/txvodplayer/download/event" binaryMessenger:[registrar messenger]]; _eventChannel = [FlutterEventChannel eventChannelWithName:@"cloud.tencent.com/txvodplayer/download/event" binaryMessenger:[registrar messenger]];
[_eventChannel setStreamHandler:self]; [_eventChannel setStreamHandler:self];
NSLog(@"dokie initWithRegistrar"); 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; return self;
} }
...@@ -61,6 +68,53 @@ ...@@ -61,6 +68,53 @@
int taskId = [args[@"taskId"] intValue]; int taskId = [args[@"taskId"] intValue];
[[TXVodPreloadManager sharedManager] stopPreload:taskId]; [[TXVodPreloadManager sharedManager] stopPreload:taskId];
result(nil); 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 @@ ...@@ -120,4 +174,94 @@
[_eventSink success:[FTXDownloadManager getParamsWithEvent:EVENT_PREDOWNLOAD_ON_ERROR withParams:dict]]; [_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 @end
...@@ -3,9 +3,30 @@ ...@@ -3,9 +3,30 @@
#define FTXEvent_h #define FTXEvent_h
// 音频变化事件code // 音频变化事件code
#define EVENT_VOLUME_CHANGED 0x01 #define EVENT_VOLUME_CHANGED 1
#define EVENT_AUDIO_FOCUS_PAUSE 0x02 #define EVENT_AUDIO_FOCUS_PAUSE 2
#define EVENT_AUDIO_FOCUS_PLAY 0x03 #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功能没有启动
// 画中画事件code // 画中画事件code
#define EVENT_PIP_MODE_ALREADY_ENTER 1 #define EVENT_PIP_MODE_ALREADY_ENTER 1
...@@ -32,4 +53,16 @@ ...@@ -32,4 +53,16 @@
#define EVENT_PREDOWNLOAD_ON_COMPLETE 200 #define EVENT_PREDOWNLOAD_ON_COMPLETE 200
// 视频预下载出错 // 视频预下载出错
#define EVENT_PREDOWNLOAD_ON_ERROR 201 #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 */ #endif /* FTXEvent_h */
...@@ -66,11 +66,20 @@ BOOL volatile isStop = false; ...@@ -66,11 +66,20 @@ BOOL volatile isStop = false;
_netStatusChannel = [FlutterEventChannel eventChannelWithName:[@"cloud.tencent.com/txvodplayer/net/" stringByAppendingString:[self.playerId stringValue]] binaryMessenger:[registrar messenger]]; _netStatusChannel = [FlutterEventChannel eventChannelWithName:[@"cloud.tencent.com/txvodplayer/net/" stringByAppendingString:[self.playerId stringValue]] binaryMessenger:[registrar messenger]];
[_netStatusChannel setStreamHandler:self]; [_netStatusChannel setStreamHandler:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onApplicationTerminateClick) name:UIApplicationWillTerminateNotification object:nil];
} }
return self; return self;
} }
- (void)onApplicationTerminateClick {
[_txVodPlayer removeVideoWidget];
_txVodPlayer = nil;
_txVodPlayer.videoProcessDelegate = nil;
_textureId = -1;
}
- (void)destory - (void)destory
{ {
[self stopPlay]; [self stopPlay];
......
// 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;
}
}
...@@ -81,9 +81,9 @@ abstract class TXVodPlayEvent { ...@@ -81,9 +81,9 @@ abstract class TXVodPlayEvent {
static const EVT_PLAY_DURATION = "EVT_PLAY_DURATION"; // 播放总长 static const EVT_PLAY_DURATION = "EVT_PLAY_DURATION"; // 播放总长
static const EVT_PLAYABLE_DURATION_MS = "EVT_PLAYABLE_DURATION_MS"; // 点播可播放时长(毫秒) static const EVT_PLAYABLE_DURATION_MS = "EVT_PLAYABLE_DURATION_MS"; // 点播可播放时长(毫秒)
static const EVT_PLAYABLE_RATE = "EVT_PLAYABLE_RATE"; //播放速率 static const EVT_PLAYABLE_RATE = "EVT_PLAYABLE_RATE"; //播放速率
static const String EVT_IMAGESPRIT_WEBVTTURL = "EVT_IMAGESPRIT_WEBVTTURL"; // 雪碧图web vtt描述文件下载URL static const EVT_IMAGESPRIT_WEBVTTURL = "EVT_IMAGESPRIT_WEBVTTURL"; // 雪碧图web vtt描述文件下载URL
static const String EVT_IMAGESPRIT_IMAGEURL_LIST = "EVT_IMAGESPRIT_IMAGEURL_LIST"; // 雪碧图图片下载URL static const EVT_IMAGESPRIT_IMAGEURL_LIST = "EVT_IMAGESPRIT_IMAGEURL_LIST"; // 雪碧图图片下载URL
static const String EVT_DRM_TYPE = "EVT_DRM_TYPE"; // 加密类型 static const EVT_DRM_TYPE = "EVT_DRM_TYPE"; // 加密类型
/// superplayer plugin volume event /// superplayer plugin volume event
static const EVENT_VOLUME_CHANGED = 1; // 音量变化 static const EVENT_VOLUME_CHANGED = 1; // 音量变化
...@@ -113,8 +113,14 @@ abstract class TXVodPlayEvent { ...@@ -113,8 +113,14 @@ abstract class TXVodPlayEvent {
/// 视频下载相关事件 /// 视频下载相关事件
static const int EVENT_PREDOWNLOAD_ON_COMPLETE = 200; // 视频预下载完成 static const EVENT_PREDOWNLOAD_ON_COMPLETE = 200; // 视频预下载完成
static const int EVENT_PREDOWNLOAD_ON_ERROR = 201; // 视频预下载出错 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 { abstract class TXVodNetEvent {
...@@ -171,13 +177,24 @@ enum TXPlayerEvent { ...@@ -171,13 +177,24 @@ enum TXPlayerEvent {
} }
class TXLogLevel { class TXLogLevel {
static const int LOG_LEVEL_VERBOSE = 0; // 输出所有级别的log static const LOG_LEVEL_VERBOSE = 0; // 输出所有级别的log
static const int LOG_LEVEL_DEBUG = 1; // 输出 DEBUG,INFO,WARNING,ERROR 和 FATAL 级别的log static const LOG_LEVEL_DEBUG = 1; // 输出 DEBUG,INFO,WARNING,ERROR 和 FATAL 级别的log
static const int LOG_LEVEL_INFO = 2; // 输出 INFO,WARNNING,ERROR 和 FATAL 级别的log static const LOG_LEVEL_INFO = 2; // 输出 INFO,WARNNING,ERROR 和 FATAL 级别的log
static const int LOG_LEVEL_WARN = 3; // 输出WARNNING,ERROR 和 FATAL 级别的log static const LOG_LEVEL_WARN = 3; // 输出WARNNING,ERROR 和 FATAL 级别的log
static const int LOG_LEVEL_ERROR = 4; // 输出ERROR 和 FATAL 级别的log static const LOG_LEVEL_ERROR = 4; // 输出ERROR 和 FATAL 级别的log
static const int LOG_LEVEL_FATAL = 5; // 只输出FATAL 级别的log static const LOG_LEVEL_FATAL = 5; // 只输出FATAL 级别的log
static const int LOG_LEVEL_NULL = 6; // 不输出任何sdk 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 { class TXPlayInfoParams {
...@@ -196,7 +213,82 @@ class TXPlayInfoParams { ...@@ -196,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 //视频预下载事件回调Listener
typedef FTXPredownlodOnCompleteListener = void Function(int taskId, String url); typedef FTXPredownlodOnCompleteListener = void Function(int taskId, String url);
typedef FTXPredownlodOnErrorListener = void Function(int taskId, String url, int code, String msg); 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);
...@@ -4,34 +4,38 @@ part of SuperPlayer; ...@@ -4,34 +4,38 @@ part of SuperPlayer;
/// include features: /// include features:
/// 1. Video predownlaod /// 1. Video predownlaod
/// 2. Video download /// 2. Video download
class TXVodDownlaodController { class TXVodDownloadController {
static const String TAG = 'TXVodDownlaodController'; static const String TAG = 'TXVodDownlaodController';
static TXVodDownlaodController? _instance; static TXVodDownloadController? _instance;
static TXVodDownlaodController get instance => _sharedInstance();
static TXVodDownloadController get instance => _sharedInstance();
StreamSubscription? _downloadEventSubscription; StreamSubscription? _downloadEventSubscription;
final StreamController<Map<dynamic, dynamic>> _downloadEventStreamController = StreamController.broadcast(); 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; late MethodChannel _methodChannel;
FTXPredownlodOnCompleteListener? _onPreDownloadOnCompleteListener; FTXPredownlodOnCompleteListener? _onPreDownloadOnCompleteListener;
FTXPredownlodOnErrorListener? _onPreDownloadOnErrorListener; FTXPredownlodOnErrorListener? _onPreDownloadOnErrorListener;
static TXVodDownlaodController _sharedInstance() { FTXDownlodOnStateChangeListener? _downlodOnStateChangeListener;
FTXDownlodOnErrorListener? _downlodOnErrorListener;
static TXVodDownloadController _sharedInstance() {
if (_instance == null) { if (_instance == null) {
_instance = TXVodDownlaodController._createInsatnce(); _instance = TXVodDownloadController._createInsatnce();
} }
return _instance!; return _instance!;
} }
TXVodDownlaodController._createInsatnce() { TXVodDownloadController._createInsatnce() {
EventChannel eventChannel = EventChannel("cloud.tencent.com/txvodplayer/download/event"); EventChannel eventChannel = EventChannel("cloud.tencent.com/txvodplayer/download/event");
_downloadEventSubscription = eventChannel.receiveBroadcastStream('event') _downloadEventSubscription =
.listen(_eventHandler, onError: _errorHandler); eventChannel.receiveBroadcastStream('event').listen(_eventHandler, onError: _errorHandler);
_methodChannel = MethodChannel("cloud.tencent.com/txvodplayer/download/api"); _methodChannel = MethodChannel("cloud.tencent.com/txvodplayer/download/api");
} }
/// 启动预下载。 /// 启动预下载。
/// 【重要】启动预下载前,请先设置好播放引擎的缓存目录[SuperPlayerPlugin.setGlobalCacheFolderPath]和缓存大小[SuperPlayerPlugin.setGlobalMaxCacheSize],这个设置是全局配置需和播放器保持一致,否则会造成播放缓存失效。 /// 【重要】启动预下载前,请先设置好播放引擎的缓存目录[SuperPlayerPlugin.setGlobalCacheFolderPath]和缓存大小[SuperPlayerPlugin.setGlobalMaxCacheSize],这个设置是全局配置需和播放器保持一致,否则会造成播放缓存失效。
/// playUrl: 要预下载的url /// playUrl: 要预下载的url
...@@ -40,21 +44,19 @@ class TXVodDownlaodController { ...@@ -40,21 +44,19 @@ class TXVodDownlaodController {
/// onCompleteListener:预下载成功回调 /// onCompleteListener:预下载成功回调
/// onErrorListener:预下载失败回调 /// onErrorListener:预下载失败回调
/// 返回值:任务ID,可用这个任务ID停止预下载 [stopPreload] /// 返回值:任务ID,可用这个任务ID停止预下载 [stopPreload]
Future<int> startPreLoad(final String playUrl, Future<int> startPreLoad(
final int preloadSizeMB, final String playUrl,
final int preferredResolution, final int preloadSizeMB,
{ FTXPredownlodOnCompleteListener? onCompleteListener, final int preferredResolution, {
FTXPredownlodOnErrorListener? onErrorListener, FTXPredownlodOnCompleteListener? onCompleteListener,
}) async { FTXPredownlodOnErrorListener? onErrorListener,
}) async {
_onPreDownloadOnCompleteListener = onCompleteListener; _onPreDownloadOnCompleteListener = onCompleteListener;
_onPreDownloadOnErrorListener = onErrorListener; _onPreDownloadOnErrorListener = onErrorListener;
var map = {"playUrl": playUrl, var map = {"playUrl": playUrl, "preloadSizeMB": preloadSizeMB, "preferredResolution": preferredResolution};
"preloadSizeMB": preloadSizeMB,
"preferredResolution": preferredResolution };
return await _methodChannel.invokeMethod("startPreLoad", map); return await _methodChannel.invokeMethod("startPreLoad", map);
} }
/// 停止预下载。 /// 停止预下载。
/// taskId: 任务id,[startPreLoad]返回值 /// taskId: 任务id,[startPreLoad]返回值
Future<void> stopPreLoad(final int taskId) async { Future<void> stopPreLoad(final int taskId) async {
...@@ -62,6 +64,72 @@ class TXVodDownlaodController { ...@@ -62,6 +64,72 @@ class TXVodDownlaodController {
await _methodChannel.invokeMethod("stopPreLoad", map); 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) { _eventHandler(event) {
if (null == event) { if (null == event) {
...@@ -69,7 +137,8 @@ class TXVodDownlaodController { ...@@ -69,7 +137,8 @@ class TXVodDownlaodController {
} }
LogUtils.d(TAG, '_eventHandler, event= ${event}'); LogUtils.d(TAG, '_eventHandler, event= ${event}');
final Map<dynamic, dynamic> map = event; final Map<dynamic, dynamic> map = event;
switch (map["event"]) { int eventCode = map["event"];
switch (eventCode) {
case TXVodPlayEvent.EVENT_PREDOWNLOAD_ON_COMPLETE: case TXVodPlayEvent.EVENT_PREDOWNLOAD_ON_COMPLETE:
int taskId = map['taskId'] as int; int taskId = map['taskId'] as int;
String url = map['url'] as String; String url = map['url'] as String;
...@@ -88,13 +157,23 @@ class TXVodDownlaodController { ...@@ -88,13 +157,23 @@ class TXVodDownlaodController {
_onPreDownloadOnErrorListener!(taskId, url, code, msg); _onPreDownloadOnErrorListener!(taskId, url, code, msg);
} }
break; 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: default:
break; break;
} }
_downloadEventStreamController.add(event); _downloadEventStreamController.add(event);
} }
_errorHandler(error) { _errorHandler(error) {}
}
}
}
\ No newline at end of file
...@@ -3,6 +3,7 @@ library SuperPlayer; ...@@ -3,6 +3,7 @@ library SuperPlayer;
import 'dart:async'; import 'dart:async';
import 'dart:core'; import 'dart:core';
import 'dart:math';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
...@@ -17,4 +18,5 @@ part 'Core/txplayer_define.dart'; ...@@ -17,4 +18,5 @@ part 'Core/txplayer_define.dart';
part 'Core/txplayer_widget.dart'; part 'Core/txplayer_widget.dart';
part 'Core/txvodplayer_config.dart'; part 'Core/txvodplayer_config.dart';
part 'Core/txvodplayer_controller.dart'; part 'Core/txvodplayer_controller.dart';
part 'Core/txvoddownload_controller.dart'; part 'Core/txvoddownload_controller.dart';
\ No newline at end of file part 'Core/tools/common_utils.dart';
\ No newline at end of file
...@@ -27,7 +27,7 @@ void main() { ...@@ -27,7 +27,7 @@ void main() {
await SuperPlayerPlugin.setGlobalMaxCacheSize(200); await SuperPlayerPlugin.setGlobalMaxCacheSize(200);
String _url = String _url =
"http://1400329073.vod2.myqcloud.com/d62d88a7vodtranscq1400329073/59c68fe75285890800381567412/adp.10.m3u8"; "http://1400329073.vod2.myqcloud.com/d62d88a7vodtranscq1400329073/59c68fe75285890800381567412/adp.10.m3u8";
int taskId = await TXVodDownlaodController.instance.startPreLoad(_url, 20, 720*1080, int taskId = await TXVodDownloadController.instance.startPreLoad(_url, 20, 720*1080,
onCompleteListener:(int taskId,String url) { onCompleteListener:(int taskId,String url) {
print('taskID=${taskId} ,url=${url}'); print('taskID=${taskId} ,url=${url}');
}, onErrorListener: (int taskId, String url, int code, String msg) { }, onErrorListener: (int taskId, String url, int code, String msg) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论