提交 ce393250 authored 作者: dokieyang's avatar dokieyang

init SuperPlayer_Flutter 1.0

上级 05c7fbe7
差异被折叠。
*.iml
.gradle
/local.properties
*.idea/
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
group 'com.example.super_player'
version '1.0'
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
}
}
rootProject.allprojects {
repositories {
google()
jcenter()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
}
// lines skipped
dependencies {
provided rootProject.findProject(":superplayerkit")
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
implementation project(path: ':superplayerkit')
}
\ No newline at end of file
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
rootProject.name = 'super_player'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.super_player">
</manifest>
package com.example.super_player;
import java.util.concurrent.atomic.AtomicInteger;
public class FTXBasePlayer {
private static final AtomicInteger mAtomicId = new AtomicInteger(0);
private final int mPlayerId;
public int getPlayerId() {
return mPlayerId;
}
public FTXBasePlayer() {
mPlayerId = mAtomicId.incrementAndGet();
}
public void destory() {
}
}
package com.example.super_player;
import java.util.LinkedList;
import java.util.Queue;
import io.flutter.plugin.common.EventChannel;
public class FTXPlayerEventSink implements EventChannel.EventSink {
private EventChannel.EventSink eventSink;
private Queue<Object> eventQueue = new LinkedList();
private boolean isEnd = false;
public void setEventSinkProxy(EventChannel.EventSink es) {
this.eventSink = es;
consume();
}
private void enqueue(Object event) {
if (isEnd) return;
eventQueue.offer(event);
}
private void consume() {
if (eventSink == null) return;
while (!eventQueue.isEmpty()){
Object event = eventQueue.poll();
if (event instanceof EndEvent) {
eventSink.endOfStream();
} else if (event instanceof ErrorEvent) {
ErrorEvent errorEvent = (ErrorEvent) event;
eventSink.error(errorEvent.code, errorEvent.message, errorEvent.details);
} else {
eventSink.success(event);
}
}
}
private static class EndEvent {
}
private static class ErrorEvent {
String code;
String message;
Object details;
ErrorEvent(String code, String message, Object details) {
this.code = code;
this.message = message;
this.details = details;
}
}
@Override
public void success(Object event) {
enqueue(event);
consume();
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
enqueue(new ErrorEvent(errorCode, errorMessage, errorDetails));
consume();
}
@Override
public void endOfStream() {
enqueue(new EndEvent());
consume();
isEnd = true;
}
}
package com.example.super_player;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.tencent.liteav.demo.superplayer.SuperPlayerGlobalConfig;
import com.tencent.liteav.demo.superplayer.SuperPlayerModel;
import com.tencent.liteav.demo.superplayer.SuperPlayerVideoId;
import com.tencent.liteav.demo.superplayer.SuperPlayerView;
import com.tencent.liteav.demo.superplayer.model.SuperPlayer;
import com.tencent.liteav.demo.superplayer.model.entity.SuperPlayerVideoIdV2;
import com.tencent.rtmp.TXLiveBase;
import com.tencent.rtmp.TXLiveConstants;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformView;
public class SuperPlatformPlayerView implements PlatformView, MethodChannel.MethodCallHandler, SuperPlayerView.OnSuperPlayerViewCallback {
private SuperPlayerView mSuperPlayerView;
private FlutterPlugin.FlutterPluginBinding mFlutterPluginBinding;
private final MethodChannel mMethodChannel;
private final EventChannel mEventChannel;
private final FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
public SuperPlatformPlayerView(Context context, Map<String, Object> params, int viewId, FlutterPlugin.FlutterPluginBinding flutterPluginBinding) {
super();
mSuperPlayerView = new SuperPlayerView(context);
mSuperPlayerView.setPlayerViewCallback(this);
mMethodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent.com/superPlayer/" + viewId);
mMethodChannel.setMethodCallHandler(this);
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent.com/superPlayer/event/" + viewId);
mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
mEventSink.setEventSinkProxy(eventSink);
}
@Override
public void onCancel(Object o) {
mEventSink.setEventSinkProxy(null);
}
});
//
// if (params.containsKey("playerConfig")){
// Map playerConfig = (Map) params.get("playerConfig");
// SuperPlayerGlobalConfig prefs = SuperPlayerGlobalConfig.getInstance();
// prefs.playShiftDomain = (String) playerConfig.get("playShiftDomain");
// prefs.enableHWAcceleration = (boolean) playerConfig.get("hwAcceleration");
// prefs.renderMode = (int) playerConfig.get("renderMode");
// }
//
// SuperPlayerModel model = new SuperPlayerModel();
// if (params.containsKey("playerModel")) {
// Map playerModel = (Map) params.get("playerModel");
// model.url = (String) playerModel.get("videoURL");
// model.appId = (int) playerModel.get("appId");
// model.playDefaultIndex = (int) playerModel.get("defaultPlayIndex");
// if (playerModel.containsKey("videoId")) {
// Map videoIdMap = (Map) playerModel.get("videoId");
// SuperPlayerVideoId videoId = new SuperPlayerVideoId();
// videoId.fileId = (String) videoIdMap.get("videoId");
// videoId.pSign = (String) videoIdMap.get("psign");
// model.videoId = videoId;
// }
//
// if (playerModel.containsKey("multiVideoURLs")) {
// List<SuperPlayerModel.SuperPlayerURL> multiURLs = new ArrayList<SuperPlayerModel.SuperPlayerURL>();
// List<Map> mapURLs = (List<Map>) playerModel.get("multiVideoURLs");
// for (Map e:mapURLs) {
// SuperPlayerModel.SuperPlayerURL url = new SuperPlayerModel.SuperPlayerURL();
// url.qualityName = (String) e.get("title");
// url.url = (String) e.get("url");
// multiURLs.add(url);
// }
// model.multiURLs = multiURLs;
// }
// }
//
// mPlayerModel = model;
// mSuperPlayerView.playWithModel(model);
}
@Override
public void onStartFullScreenPlay() {
mEventSink.success("onStartFullScreenPlay");
}
@Override
public void onStopFullScreenPlay() {
mEventSink.success("onStopFullScreenPlay");
}
@Override
public void onClickFloatCloseBtn() {
}
@Override
public void onClickSmallReturnBtn() {
}
@Override
public void onStartFloatWindowPlay() {
}
@Override
public View getView() {
return mSuperPlayerView;
}
@Override
public void dispose() {
mSuperPlayerView.resetPlayer();
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (call.method.equals("reloadView")) {
// String url = call.argument("url");
// Integer appId = call.argument("appId");
// String fileId = call.argument("fileId");
// String psign = call.argument("psign");
// reloadView(url, appId, fileId, psign);
result.success(null);
} else if (call.method.equals("play")) {
Map playerModel = call.argument("playerModel");
playWithModel(playerModel);
result.success(null);
} else if (call.method.equals("playConfig")) {
Map playConfig = call.argument("config");
setPlayConfig(playConfig);
result.success(null);
} else {
result.notImplemented();
}
}
// public void reloadView(String url, Integer appId, String fileId, String psign) {
// if (mPlayerModel == null) {
// return;
// }
//
// if (url != null && !url.isEmpty()) {
// mPlayerModel.videoId = null;
// mPlayerModel.url = url;
// }else if (appId > 0 && fileId != null && !fileId.isEmpty()) {
// SuperPlayerVideoId videoId = new SuperPlayerVideoId();
// mPlayerModel.appId = (int) appId;
// videoId.fileId = fileId;
// if (psign != null && !psign.isEmpty()) {
// videoId.pSign = psign;
// }
// mPlayerModel.videoId = videoId;
// mPlayerModel.url = null;
// }
//
// mSuperPlayerView.resetPlayer();
// mSuperPlayerView.playWithModel(mPlayerModel);
// }
public void playWithModel(Map playerModel) {
SuperPlayerModel model = new SuperPlayerModel();
model.url = (String) playerModel.get("videoURL");
model.appId = (int) playerModel.get("appId");
if (model.appId > 0) {
TXLiveBase.setAppID("" + model.appId);
}
model.playDefaultIndex = (int) playerModel.get("defaultPlayIndex");
model.title = (String) playerModel.get("title");
if (playerModel.containsKey("videoId")) {
Map videoIdMap = (Map) playerModel.get("videoId");
SuperPlayerVideoId videoId = new SuperPlayerVideoId();
videoId.fileId = (String) videoIdMap.get("fileId");
videoId.pSign = (String) videoIdMap.get("psign");
model.videoId = videoId;
model.url = null;
}
if (playerModel.containsKey("multiVideoURLs")) {
List<SuperPlayerModel.SuperPlayerURL> multiURLs = new ArrayList<SuperPlayerModel.SuperPlayerURL>();
List<Map> mapURLs = (List<Map>) playerModel.get("multiVideoURLs");
for (Map e:mapURLs) {
SuperPlayerModel.SuperPlayerURL url = new SuperPlayerModel.SuperPlayerURL();
url.qualityName = (String) e.get("title");
url.url = (String) e.get("url");
multiURLs.add(url);
}
model.multiURLs = multiURLs;
}
mSuperPlayerView.resetPlayer();
mSuperPlayerView.playWithModel(model);
}
public void setPlayConfig(Map params) {
SuperPlayerGlobalConfig prefs = SuperPlayerGlobalConfig.getInstance();
prefs.playShiftDomain = (String) params.get("playShiftDomain");
prefs.enableHWAcceleration = (boolean) params.get("hwAcceleration");
prefs.renderMode = (int) params.get("renderMode");
}
public void setIsAutoPlay(boolean b) {
}
public void setStartTime(double startTime) {
}
public void disableGesture(boolean b) {
}
public void setLoop(boolean b) {
}
}
package com.example.super_player;
import android.app.Activity;
import android.content.Context;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.common.MessageCodec;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;
public class SuperPlatformViewFactory extends PlatformViewFactory {
/**
* @param createArgsCodec the codec used to decode the args parameter of {@link #create}.
*/
private FlutterPlugin.FlutterPluginBinding mFlutterPluginBinding;
private Activity mActivity;
public SuperPlatformViewFactory(FlutterPlugin.FlutterPluginBinding flutterPluginBinding, Activity activity) {
super(StandardMessageCodec.INSTANCE);
mFlutterPluginBinding = flutterPluginBinding;
mActivity = activity;
}
@Override
public PlatformView create(Context context, int viewId, Object args) {
if (mActivity == null) {
return null;
}
if (args instanceof Map) {
SuperPlatformPlayerView playerView = new SuperPlatformPlayerView(mActivity, ((Map) args), viewId, mFlutterPluginBinding);
return playerView;
}
return null;
}
}
package com.example.super_player;
import android.app.Activity;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import com.tencent.rtmp.TXLiveBase;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
/** SuperPlayerPlugin */
public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private MethodChannel channel;
private FlutterPluginBinding mFlutterPluginBinding;
private ActivityPluginBinding mActivityPluginBinding;
private SparseArray<FTXBasePlayer> mPlayers;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
mFlutterPluginBinding = flutterPluginBinding;
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "super_player");
channel.setMethodCallHandler(this);
mPlayers = new SparseArray();
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else if(call.method.equals("createVodPlayer")) {
FTXVodPlayer player = new FTXVodPlayer(mFlutterPluginBinding);
int playerId = player.getPlayerId();
mPlayers.append(playerId, player);
result.success(playerId);
} else if(call.method.equals("createLivePlayer")) {
FTXLivePlayer player = new FTXLivePlayer(mFlutterPluginBinding,mActivityPluginBinding.getActivity());
int playerId = player.getPlayerId();
mPlayers.append(playerId, player);
result.success(playerId);
} else if(call.method.equals("releasePlayer")) {
Integer playerId = call.argument("playerId");
FTXBasePlayer player = mPlayers.get(playerId);
if (player!=null){
player.destory();
mPlayers.remove(playerId);
}
result.success(null);
} else if(call.method.equals("setConsoleEnabled")) {
boolean bnabled = call.argument("enabled");
TXLiveBase.setConsoleEnabled(bnabled);
result.success(null);
} else {
result.notImplemented();
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
mFlutterPluginBinding = null;
}
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
mActivityPluginBinding = binding;
mFlutterPluginBinding.getPlatformViewRegistry().registerViewFactory("super_player_view", new SuperPlatformViewFactory(mFlutterPluginBinding, binding.getActivity()));
}
@Override
public void onDetachedFromActivityForConfigChanges() {
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
}
@Override
public void onDetachedFromActivity() {
}
}
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
# super_player_example
Demonstrates how to use the super_player plugin.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.super_player_example"
minSdkVersion 19
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
profile {
}
}
}
flutter {
source '../..'
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keep class com.tencent.** { *; }
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.super_player_example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--点播播放器悬浮窗权限-->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!--存储-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- <android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.super_player_example">
<application
android:label="super_player_example"
android:icon="@mipmap/ic_launcher"
tools:replace="android:label">
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="stateHidden">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
package com.example.super_player_example;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.super_player_example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
compileSdkVersion = 28
buildToolsVersion = "28.0.3"
supportSdkVersion = "26.0.1"
minSdkVersion = 19
targetSdkVersion = 28
liteavSdk="com.tencent.liteav:LiteAVSDK_Player:latest.release"
imSdk = 'com.tencent.imsdk:imsdk:4.9.1'
versionCode = 1
versionName = "v1.0"
ndkAbi = 'armeabi'//,'armeabi-v7a', 'arm64-v8a'
aekit_version = '1.0.10-cloud'
}
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
include ':superplayerkit'
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
}
profile {
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// compile project(':liteav_sdk')
compile rootProject.ext.liteavSdk
compile 'com.github.ctiao:DanmakuFlameMaster:0.5.3'
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keep class com.tencent.** { *; }
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tencent.liteav.demo.superplayer" />
package com.tencent.liteav.demo.superplayer;
public class SuperPlayerCode {
public static final int OK = 0;
public static final int NET_ERROR = 10001;
public static final int PLAY_URL_EMPTY = 20001;
public static final int LIVE_PLAY_END = 30001;
public static final int LIVE_SHIFT_FAIL = 30002;
public static final int VOD_PLAY_FAIL = 40001;
public static final int VOD_REQUEST_FILE_ID_FAIL = 40002;
}
package com.tencent.liteav.demo.superplayer;
public class SuperPlayerDef {
public enum PlayerMode {
WINDOW, // 窗口模式
FULLSCREEN, // 全屏模式
FLOAT // 悬浮窗模式
}
public enum PlayerState {
PLAYING, // 播放中
PAUSE, // 暂停中
LOADING, // 缓冲中
END // 结束播放
}
public enum PlayerType {
VOD, // 点播
LIVE, // 直播
LIVE_SHIFT // 直播会看
}
public enum Orientation {
LANDSCAPE, // 横屏
PORTRAIT // 竖屏
}
}
package com.tencent.liteav.demo.superplayer;
import com.tencent.rtmp.TXLiveConstants;
/**
* Created by yuejiaoli on 2018/7/4.
*
* 超级播放器全局配置类
*/
public class SuperPlayerGlobalConfig {
private static class Singleton {
private static SuperPlayerGlobalConfig sInstance = new SuperPlayerGlobalConfig();
}
public static SuperPlayerGlobalConfig getInstance() {
return Singleton.sInstance;
}
/**
* 默认播放填充模式 ( 默认播放模式为 自适应模式 )
*/
public int renderMode = TXLiveConstants.RENDER_MODE_ADJUST_RESOLUTION;
/**
* 播放器最大缓存个数 ( 默认缓存 5 )
*/
public int maxCacheItem = 5;
/**
* 是否启用悬浮窗 ( 默认开启 true )
*/
public boolean enableFloatWindow = true;
/**
* 是否开启硬件加速 ( 默认开启硬件加速 )
*/
public boolean enableHWAcceleration = true;
/**
* 时移域名 (修改为自己app的时移域名)
*/
public String playShiftDomain = "liteavapp.timeshift.qcloud.com";
/**
* 悬浮窗位置 ( 默认在左上角,初始化一个宽为 810,高为 540的悬浮窗口 )
*/
public TXRect floatViewRect = new TXRect(0, 0, 810, 540);
public final static class TXRect {
public int x;
public int y;
public int width;
public int height;
TXRect(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public TXRect() {
}
}
}
package com.tencent.liteav.demo.superplayer;
import com.tencent.liteav.demo.superplayer.model.entity.SuperPlayerVideoIdV2;
import java.util.List;
/**
* 超级播放器支持三种方式播放视频:
* 1. 视频 URL
* 填写视频 URL, 如需使用直播时移功能,还需填写appId
* 2. 腾讯云点播 File ID 播放
* 填写 appId 及 videoId (如果使用旧版本V2, 请填写videoIdV2)
* 3. 多码率视频播放
* 是URL播放方式扩展,可同时传入多条URL,用于进行码率切换
*/
public class SuperPlayerModel {
public int appId; // AppId 用于腾讯云点播 File ID 播放及腾讯云直播时移功能
/**
* ------------------------------------------------------------------
* 直接使用URL播放
* <p>
* 支持 RTMP、FLV、MP4、HLS 封装格式
* 使用腾讯云直播时移功能则需要填写appId
* ------------------------------------------------------------------
*/
public String url = ""; // 视频URL
/**
* ------------------------------------------------------------------
* 多码率视频 URL
* <p>
* 用于拥有多个播放地址的多清晰度视频播放
* ------------------------------------------------------------------
*/
public List<SuperPlayerURL> multiURLs;
public int playDefaultIndex; // 指定多码率情况下,默认播放的连接Index
/**
* ------------------------------------------------------------------
* 腾讯云点播 File ID 播放参数
* ------------------------------------------------------------------
*/
public SuperPlayerVideoId videoId;
/*
* 用于兼容旧版本(V2)腾讯云点播 File ID 播放参数(即将废弃,不推荐使用)
*/
@Deprecated
public SuperPlayerVideoIdV2 videoIdV2;
public String title = ""; // 视频文件名 (用于显示在UI层);使用file id播放,若未指定title,则使用FileId返回的Title;使用url播放需要指定title,否则title显示为空
public static class SuperPlayerURL {
public SuperPlayerURL(String url, String qualityName) {
this.qualityName = qualityName;
this.url = url;
}
public SuperPlayerURL() {
}
public String qualityName = "原画"; // 清晰度名称(用于显示在UI层)
public String url = ""; // 该清晰度对应的地址
}
}
package com.tencent.liteav.demo.superplayer;
/**
* Created by hans on 2019/3/25.
* 使用腾讯云fileId播放
*/
public class SuperPlayerVideoId {
public String fileId; // 腾讯云视频fileId
public String pSign; // v4 开启防盗链必填
@Override
public String toString() {
return "SuperPlayerVideoId{" +
", fileId='" + fileId + '\'' +
", pSign='" + pSign + '\'' +
'}';
}
}
package com.tencent.liteav.demo.superplayer.model;
import com.tencent.liteav.demo.superplayer.SuperPlayerDef;
import com.tencent.liteav.demo.superplayer.SuperPlayerModel;
import com.tencent.liteav.demo.superplayer.model.entity.VideoQuality;
import com.tencent.rtmp.TXLivePlayer;
import com.tencent.rtmp.ui.TXCloudVideoView;
import java.util.List;
public interface SuperPlayer {
/**
* 开始播放
*
* @param url 视频地址
*/
void play(String url);
/**
* 开始播放
*
* @param appId 腾讯云视频appId
* @param url 直播播放地址
*/
void play(int appId, String url);
/**
* 开始播放
*
* @param appId 腾讯云视频appId
* @param fileId 腾讯云视频fileId
* @param psign 防盗链签名,开启防盗链的视频必填,非防盗链视频可不填
*/
void play(int appId, String fileId, String psign);
/**
* 多分辨率播放
* @param appId 腾讯云视频appId
* @param superPlayerURLS 不同分辨率数据
* @param defaultIndex 默认播放Index
*/
void play(int appId, List<SuperPlayerModel.SuperPlayerURL> superPlayerURLS, int defaultIndex);
/**
* 重播
*/
void reStart();
/**
* 暂停播放
*/
void pause();
/**
* 暂停点播视频
*/
void pauseVod();
/**
* 恢复播放
*/
void resume();
/**
* 恢复直播播放,从直播时移播放中,恢复到直播播放。
*/
void resumeLive();
/**
* 停止播放
*/
void stop();
/**
* 销毁播放器
*/
void destroy();
/**
* 切换播放器模式
*
* @param playerMode {@link SuperPlayerDef.PlayerMode#WINDOW } 窗口模式
* {@link SuperPlayerDef.PlayerMode#FULLSCREEN } 全屏模式
* {@link SuperPlayerDef.PlayerMode#FLOAT } 悬浮窗模式
*/
void switchPlayMode(SuperPlayerDef.PlayerMode playerMode);
void enableHardwareDecode(boolean enable);
void setPlayerView(TXCloudVideoView videoView);
void seek(int position);
void snapshot(TXLivePlayer.ITXSnapshotListener listener);
void setRate(float speedLevel);
void setMirror(boolean isMirror);
void switchStream(VideoQuality quality);
String getPlayURL();
/**
* 获取当前播放器模式
*
* @return {@link SuperPlayerDef.PlayerMode#WINDOW } 窗口模式
* {@link SuperPlayerDef.PlayerMode#FULLSCREEN } 全屏模式
* {@link SuperPlayerDef.PlayerMode#FLOAT } 悬浮窗模式
*/
SuperPlayerDef.PlayerMode getPlayerMode();
/**
* 获取当前播放器状态
*
* @return {@link SuperPlayerDef.PlayerState#PLAYING } 播放中
* {@link SuperPlayerDef.PlayerState#PAUSE } 暂停中
* {@link SuperPlayerDef.PlayerState#LOADING } 缓冲中
* {@link SuperPlayerDef.PlayerState#END } 结束播放
*/
SuperPlayerDef.PlayerState getPlayerState();
/**
* 获取当前播放器类型
*
* @return {@link SuperPlayerDef.PlayerType#LIVE } 直播
* {@link SuperPlayerDef.PlayerType#LIVE_SHIFT } 直播时移
* {@link SuperPlayerDef.PlayerType#VOD } 点播
*/
SuperPlayerDef.PlayerType getPlayerType();
/**
* 设置播放器状态回调
*
* @param observer {@link SuperPlayerObserver}
*/
void setObserver(SuperPlayerObserver observer);
}
package com.tencent.liteav.demo.superplayer.model;
import com.tencent.liteav.demo.superplayer.SuperPlayerDef;
import com.tencent.liteav.demo.superplayer.model.entity.PlayImageSpriteInfo;
import com.tencent.liteav.demo.superplayer.model.entity.PlayKeyFrameDescInfo;
import com.tencent.liteav.demo.superplayer.model.entity.VideoQuality;
import com.tencent.rtmp.TXLivePlayer;
import java.util.List;
public abstract class SuperPlayerObserver {
/**
* 开始播放
* @param name 当前视频名称
*/
public void onPlayBegin(String name) {}
/**
* 播放暂停
*/
public void onPlayPause() {}
/**
* 播放器停止
*/
public void onPlayStop() {}
/**
* 播放器进入Loading状态
*/
public void onPlayLoading() {}
/**
* 播放进度回调
*
* @param current
* @param duration
*/
public void onPlayProgress(long current, long duration) {}
public void onSeek(int position) {}
public void onSwitchStreamStart(boolean success, SuperPlayerDef.PlayerType playerType, VideoQuality quality){}
public void onSwitchStreamEnd(boolean success, SuperPlayerDef.PlayerType playerType, VideoQuality quality){}
public void onError(int code, String message) {}
public void onPlayerTypeChange(SuperPlayerDef.PlayerType playType) {}
public void onPlayTimeShiftLive(TXLivePlayer player, String url) {}
public void onVideoQualityListChange(List<VideoQuality> videoQualities, VideoQuality defaultVideoQuality) {}
public void onVideoImageSpriteAndKeyFrameChanged(PlayImageSpriteInfo info, List<PlayKeyFrameDescInfo> list) {}
}
package com.tencent.liteav.demo.superplayer.model.entity;
/**
* Created by hans on 2019/3/25.
* <p>
* 自适应码流信息
*/
public class EncryptedStreamingInfo {
public String drmType;
public String url;
@Override
public String toString() {
return "TCEncryptedStreamingInfo{" +
", drmType='" + drmType + '\'' +
", url='" + url + '\'' +
'}';
}
}
package com.tencent.liteav.demo.superplayer.model.entity;
import java.util.List;
/**
* 视频雪碧图信息
*/
public class PlayImageSpriteInfo {
public List<String> imageUrls; // 图片链接URL
public String webVttUrl; // web vtt描述文件下载URL
@Override
public String toString() {
return "TCPlayImageSpriteInfo{" +
"imageUrls=" + imageUrls +
", webVttUrl='" + webVttUrl + '\'' +
'}';
}
}
package com.tencent.liteav.demo.superplayer.model.entity;
/**
* Created by annidy on 2017/12/20.
* <p>
* 视频播放信息
*/
public class PlayInfoStream {
public int height;
public int width;
public int size;
public int duration;
public int bitrate;
public int definition;
public String id;
public String name;
public String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getHeight() {
return height;
}
public int getDuration() {
return duration;
}
public int getBitrate() {
return bitrate;
}
public void setHeight(int height) {
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void setDuration(int duration) {
this.duration = duration;
}
public void setBitrate(int bitrate) {
this.bitrate = bitrate;
}
}
package com.tencent.liteav.demo.superplayer.model.entity;
/**
* 视频关键帧信息
*/
public class PlayKeyFrameDescInfo {
public String content; // 描述信息
public float time; // 关键帧时间(秒)
@Override
public String toString() {
return "TCPlayKeyFrameDescInfo{" +
"content='" + content + '\'' +
", time=" + time +
'}';
}
}
package com.tencent.liteav.demo.superplayer.model.entity;
/**
* 自适应码流视频画质别名
*/
public class ResolutionName {
public String name; // 画质名称
public String type; // 类型 可能的取值有 video 和 audio
public int width;
public int height;
@Override
public String toString() {
return "TCResolutionName{" +
"width='" + width + '\'' +
"height='" + height + '\'' +
"type='" + type + '\'' +
", name=" + name +
'}';
}
}
package com.tencent.liteav.demo.superplayer.model.entity;
public class SuperPlayerVideoIdV2 {
public String fileId; // 腾讯云视频fileId
public String timeout; // 【可选】加密链接超时时间戳,转换为16进制小写字符串,腾讯云 CDN 服务器会根据该时间判断该链接是否有效。
public String us; // 【可选】唯一标识请求,增加链接唯一性
public String sign; // 【可选】防盗链签名
public int exper = -1; // 【V2可选】试看时长,单位:秒。可选
@Override
public String toString() {
return "SuperPlayerVideoId{" +
", fileId='" + fileId + '\'' +
", timeout='" + timeout + '\'' +
", exper=" + exper +
", us='" + us + '\'' +
", sign='" + sign + '\'' +
'}';
}
}
package com.tencent.liteav.demo.superplayer.model.entity;
import java.util.List;
/**
* Created by yuejiaoli on 2018/7/6.
*
* 视频画质信息
*/
public class VideoClassification {
private String id;
private String name;
private List<Integer> definitionList;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Integer> getDefinitionList() {
return definitionList;
}
public void setDefinitionList(List<Integer> definitionList) {
this.definitionList = definitionList;
}
}
package com.tencent.liteav.demo.superplayer.model.entity;
/**
* Created by yuejiaoli on 2018/7/7.
* <p>
* 清晰度
*/
public class VideoQuality {
public int index;
public int bitrate;
public String name;
public String title;
public String url;
public VideoQuality() {
}
public VideoQuality(int index, String title, String url) {
this.index = index;
this.title = title;
this.url = url;
}
}
package com.tencent.liteav.demo.superplayer.model.net;
import android.os.AsyncTask;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
/**
* Created by hans on 2018/9/11.
* <p>
* 超级播放器模块由于涉及查询视频信息,所以需要有一个内置的HTTP请求模块
* <p>
* 为了不引入额外的网络请求库,这里使用原生的Java HTTPURLConnection实现
* <p>
* 推荐您修改网络模块,使用您项目中的网络请求库,如okHTTP、Volley等
*/
public class HttpURLClient {
private static class Holder {
static final HttpURLClient INSTANCE = new HttpURLClient();
}
public static HttpURLClient getInstance() {
return Holder.INSTANCE;
}
/**
* get请求
*
* @param urlStr
* @param callback
*/
public void get(final String urlStr, final OnHttpCallback callback) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
BufferedReader bufferedReader = null;
try {
URL url = new URL(urlStr);
URLConnection connection = url.openConnection();
connection.setConnectTimeout(15000);
connection.setReadTimeout(15000);
connection.connect();
InputStream in = connection.getInputStream();
if (in == null) {
if (callback != null)
callback.onError();
return;
}
bufferedReader = new BufferedReader(new InputStreamReader(in));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
if (callback != null)
callback.onSuccess(sb.toString());
} catch (IOException e) {
e.printStackTrace();
if (callback != null)
callback.onError();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
}
/**
* post json数据请求
*
* @param urlStr
* @param callback
*/
public void postJson(final String urlStr, final String json, final OnHttpCallback callback) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
BufferedReader bufferedReader = null;
try {
URL url = new URL(urlStr);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(15000);
connection.setReadTimeout(15000);
connection.setRequestMethod("POST");
connection.addRequestProperty("Content-Type", "application/json; charset=utf-8");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();
OutputStream outputStream = connection.getOutputStream();
outputStream.write(json.getBytes());
outputStream.flush();
outputStream.close();
InputStream in = connection.getInputStream();
if (in == null) {
if (callback != null)
callback.onError();
return;
}
bufferedReader = new BufferedReader(new InputStreamReader(in));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
if (callback != null)
callback.onSuccess(sb.toString());
} catch (IOException e) {
e.printStackTrace();
if (callback != null)
callback.onError();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
}
public interface OnHttpCallback {
void onSuccess(String result);
void onError();
}
}
package com.tencent.liteav.demo.superplayer.model.net;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import com.tencent.liteav.basic.log.TXCLog;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by liyuejiao on 2018/7/19.
*
* 数据上报模块
*/
public class LogReport {
private static final String TAG = "TCLogReport";
private String mAppName;
private String mPackageName;
//ELK上报事件
public static final String ELK_ACTION_CHANGE_RESOLUTION = "change_resolution";
public static final String ELK_ACTION_TIMESHIFT = "timeshift";
public static final String ELK_ACTION_FLOATMOE = "floatmode";
public static final String ELK_ACTION_LIVE_TIME = "superlive";
public static final String ELK_ACTION_VOD_TIME = "supervod";
public static final String ELK_ACTION_CHANGE_SPEED = "change_speed";
public static final String ELK_ACTION_MIRROR = "mirror";
public static final String ELK_ACTION_SOFT_DECODE = "soft_decode";
public static final String ELK_ACTION_HW_DECODE = "hw_decode";
public static final String ELK_ACTION_IMAGE_SPRITE = "image_sprite";
public static final String ELK_ACTION_PLAYER_POINT = "player_point";
private LogReport() {
}
private static class Holder {
private static LogReport instance = new LogReport();
}
public static LogReport getInstance() {
return Holder.instance;
}
public void uploadLogs(String action, long usedtime, int fileid) {
String reqUrl = "https://ilivelog.qcloud.com";
String body = "";
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("action", action);
jsonObject.put("fileid", fileid);
jsonObject.put("type", "log");
jsonObject.put("bussiness", "superplayer");
jsonObject.put("usedtime", usedtime);
jsonObject.put("platform", "android");
if (mAppName != null) {
jsonObject.put("appname", mAppName);
}
if (mPackageName != null) {
jsonObject.put("appidentifier", mPackageName);
}
body = jsonObject.toString();
TXCLog.d(TAG, body);
} catch (JSONException e) {
e.printStackTrace();
}
HttpURLClient.getInstance().postJson(reqUrl, body, new HttpURLClient.OnHttpCallback() {
@Override
public void onSuccess(String result) {
}
@Override
public void onError() {
}
});
}
public void setAppName(Context context) {
if (context == null) {
return;
}
ApplicationInfo applicationInfo = context.getApplicationInfo();
int stringId = applicationInfo.labelRes;
mAppName = stringId == 0 ? applicationInfo.nonLocalizedLabel.toString() : context.getString(stringId);
}
public void setPackageName(Context context) {
if (context == null) {
return;
}
try {
PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
// 当前版本的包名
mPackageName = info.packageName;
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.tencent.liteav.demo.superplayer.model.protocol;
import com.tencent.liteav.demo.superplayer.model.entity.PlayImageSpriteInfo;
import com.tencent.liteav.demo.superplayer.model.entity.PlayKeyFrameDescInfo;
import com.tencent.liteav.demo.superplayer.model.entity.ResolutionName;
import com.tencent.liteav.demo.superplayer.model.entity.VideoQuality;
import java.util.List;
/**
* 视频信息协议解析接口
*/
public interface IPlayInfoParser {
/**
* 获取未加密视频播放url,若没有获取sampleaes url
*
* @return url字符串
*/
String getURL();
/**
* 获取加密视频播放url
*
* @return url字符串
*/
String getEncryptedURL(PlayInfoConstant.EncryptedURLType type);
/**
* 获取加密token
*
* @return token字符串
*/
String getToken();
/**
* 获取视频名称
*
* @return 视频名称字符串
*/
String getName();
/**
* 获取雪碧图信息
*
* @return 雪碧图信息对象
*/
PlayImageSpriteInfo getImageSpriteInfo();
/**
* 获取关键帧信息
*
* @return 关键帧信息数组
*/
List<PlayKeyFrameDescInfo> getKeyFrameDescInfo();
/**
* 获取画质信息
*
* @return 画质信息数组
*/
List<VideoQuality> getVideoQualityList();
/**
* 获取默认画质信息
*
* @return 默认画质信息对象
*/
VideoQuality getDefaultVideoQuality();
/**
* 获取视频画质别名列表
*
* @return 画质别名数组
*/
List<ResolutionName> getResolutionNameList();
/**
* 获取 DRM 加密类型
* @return
*/
String getDRMType();
}
package com.tencent.liteav.demo.superplayer.model.protocol;
import com.tencent.liteav.demo.superplayer.model.entity.PlayImageSpriteInfo;
import com.tencent.liteav.demo.superplayer.model.entity.PlayKeyFrameDescInfo;
import com.tencent.liteav.demo.superplayer.model.entity.ResolutionName;
import com.tencent.liteav.demo.superplayer.model.entity.VideoQuality;
import java.util.List;
/**
* 视频信息协议接口
*/
public interface IPlayInfoProtocol {
/**
* 发送视频信息协议网络请求
*
* @param callback 协议请求回调
*/
void sendRequest(IPlayInfoRequestCallback callback);
/**
* 中途取消请求
*/
void cancelRequest();
/**
* 获取视频播放url
*
* @return 视频播放url字符串
*/
String getUrl();
/**
* 获取加密视频播放url
*
* @return url字符串
*/
String getEncyptedUrl(PlayInfoConstant.EncryptedURLType type);
/**
* 获取加密token
*
* @return token字符串
*/
String getToken();
/**
* 获取视频名称
*
* @return 视频名称字符串
*/
String getName();
/**
* 获取雪碧图信息
*
* @return 雪碧图信息对象
*/
PlayImageSpriteInfo getImageSpriteInfo();
/**
* 获取关键帧信息
*
* @return 关键帧信息数组
*/
List<PlayKeyFrameDescInfo> getKeyFrameDescInfo();
/**
* 获取画质信息
*
* @return 画质信息数组
*/
List<VideoQuality> getVideoQualityList();
/**
* 获取默认画质
*
* @return 默认画质信息对象
*/
VideoQuality getDefaultVideoQuality();
/**
* 获取视频画质别名列表
*
* @return 画质别名数组
*/
List<ResolutionName> getResolutionNameList();
/**
* 透传内容
*
* @return 透传内容
*/
String getPenetrateContext();
/**
* 获取 DRM 加密类型
* @return
*/
String getDRMType();
}
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论