feat(android): add prop to control debug log level (#3277)
* feat: add prop to allow controlling of debug log level * fix: move props parsing to safeGetters --------- Co-authored-by: olivier <olivier.bouillet@ifeelsmart.com>
This commit is contained in:
parent
0ad2e52499
commit
add87922a6
23
API.md
23
API.md
@ -301,6 +301,7 @@ var styles = StyleSheet.create({
|
|||||||
| [contentStartTime](#contentstarttime) | Android |
|
| [contentStartTime](#contentstarttime) | Android |
|
||||||
| [controls](#controls) | Android, iOS |
|
| [controls](#controls) | Android, iOS |
|
||||||
| [currentPlaybackTime](#currentplaybacktime) | Android |
|
| [currentPlaybackTime](#currentplaybacktime) | Android |
|
||||||
|
| [debug](#debug) | Android |
|
||||||
| [disableFocus](#disablefocus) | Android, iOS |
|
| [disableFocus](#disablefocus) | Android, iOS |
|
||||||
| [disableDisconnectError](#disabledisconnecterror) | Android |
|
| [disableDisconnectError](#disabledisconnecterror) | Android |
|
||||||
| [filter](#filter) | iOS |
|
| [filter](#filter) | iOS |
|
||||||
@ -497,6 +498,28 @@ The start time in ms for SSAI content. This determines at what time to load the
|
|||||||
|
|
||||||
Platforms: Android, iOS
|
Platforms: Android, iOS
|
||||||
|
|
||||||
|
#### debug
|
||||||
|
|
||||||
|
Enable more verbosity in logs.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Do not use this open in production build
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
| ------------------ | ------ | ------------------------------------------------------------------------------------------- |
|
||||||
|
| enable | boolean | when true, display logs with verbosity higher |
|
||||||
|
| thread | boolean | enable thread display |
|
||||||
|
|
||||||
|
|
||||||
|
Example with default values:
|
||||||
|
```
|
||||||
|
debug={{
|
||||||
|
enable: true,
|
||||||
|
thread: true,
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
Platforms: Android
|
||||||
|
|
||||||
#### disableFocus
|
#### disableFocus
|
||||||
Determines whether video audio should override background music/audio in Android devices.
|
Determines whether video audio should override background music/audio in Android devices.
|
||||||
* **false (default)** - Override background audio/music
|
* **false (default)** - Override background audio/music
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
package com.brentvatne.common.toolbox
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
/* log utils
|
||||||
|
* This class allow defining a log level for the package
|
||||||
|
* This is useful for debugging real time issue or tricky use cases
|
||||||
|
*/
|
||||||
|
|
||||||
|
object DebugLog {
|
||||||
|
// log level to display
|
||||||
|
private var level = Log.WARN
|
||||||
|
// enable thread display in logs
|
||||||
|
private var displayThread = true
|
||||||
|
// add a common prefix for easy filtering
|
||||||
|
private const val TAG_PREFIX = "RNV"
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun setConfig(_level: Int, _displayThread: Boolean) {
|
||||||
|
level = _level
|
||||||
|
displayThread = _displayThread
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
private fun getTag(tag: String): String {
|
||||||
|
return TAG_PREFIX + tag
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
private fun getMsg(msg: String): String {
|
||||||
|
return if (displayThread) {
|
||||||
|
"[" + Thread.currentThread().name + "] " + msg
|
||||||
|
} else msg
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun v(tag: String, msg: String) {
|
||||||
|
if (level <= Log.VERBOSE) Log.v(getTag(tag), getMsg(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun d(tag: String, msg: String) {
|
||||||
|
if (level <= Log.DEBUG) Log.d(getTag(tag), getMsg(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun i(tag: String, msg: String) {
|
||||||
|
if (level <= Log.INFO) Log.i(getTag(tag), getMsg(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun w(tag: String, msg: String) {
|
||||||
|
if (level <= Log.WARN) Log.w(getTag(tag), getMsg(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun e(tag: String, msg: String) {
|
||||||
|
if (level <= Log.ERROR) Log.e(getTag(tag), getMsg(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun wtf(tag: String, msg: String) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
|
||||||
|
Log.wtf(getTag(tag), "--------------->" + getMsg(msg))
|
||||||
|
} else {
|
||||||
|
Log.e(getTag(tag), "--------------->" + getMsg(msg))
|
||||||
|
}
|
||||||
|
printCallStack()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun printCallStack() {
|
||||||
|
if (level <= Log.VERBOSE) {
|
||||||
|
val e = Exception()
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additionnal thread safety checkers
|
||||||
|
@JvmStatic
|
||||||
|
fun checkUIThread(tag: String, msg: String) {
|
||||||
|
if (Thread.currentThread().name != "main") {
|
||||||
|
wtf(tag, "------------------------>" + getMsg(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun checkNotUIThread(tag: String, msg: String) {
|
||||||
|
if (Thread.currentThread().name == "main") {
|
||||||
|
wtf(tag, "------------------------>" + getMsg(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
package com.brentvatne.common.toolbox
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.Dynamic
|
||||||
|
import com.facebook.react.bridge.ReadableMap
|
||||||
|
import com.facebook.react.bridge.ReadableArray
|
||||||
|
import java.util.HashMap
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toolbox to safe parsing of <Video props
|
||||||
|
* These are just safe accessors to ReadableMap
|
||||||
|
*/
|
||||||
|
|
||||||
|
object ReactBridgeUtils {
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetString(map: ReadableMap?, key: String?, fallback: String?): String? {
|
||||||
|
return if (map != null && map.hasKey(key!!) && !map.isNull(key)) map.getString(key) else fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetString(map: ReadableMap?, key: String?): String? {
|
||||||
|
return safeGetString(map, key, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetDynamic(map: ReadableMap?, key: String?, fallback: Dynamic?): Dynamic? {
|
||||||
|
return if (map != null && map.hasKey(key!!) && !map.isNull(key)) map.getDynamic(key) else fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetDynamic(map: ReadableMap?, key: String?): Dynamic? {
|
||||||
|
return safeGetDynamic(map, key, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetBool(map: ReadableMap?, key: String?, fallback: Boolean): Boolean {
|
||||||
|
return if (map != null && map.hasKey(key!!) && !map.isNull(key)) map.getBoolean(key) else fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetMap(map: ReadableMap?, key: String?): ReadableMap? {
|
||||||
|
return if (map != null && map.hasKey(key!!) && !map.isNull(key)) map.getMap(key) else null
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetArray(map: ReadableMap?, key: String?): ReadableArray? {
|
||||||
|
return if (map != null && map.hasKey(key!!) && !map.isNull(key)) map.getArray(key) else null
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetInt(map: ReadableMap?, key: String?, fallback: Int): Int {
|
||||||
|
return if (map != null && map.hasKey(key!!) && !map.isNull(key)) map.getInt(key) else fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetInt(map: ReadableMap?, key: String?): Int {
|
||||||
|
return safeGetInt(map, key, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetDouble(map: ReadableMap?, key: String?, fallback: Double): Double {
|
||||||
|
return if (map != null && map.hasKey(key!!) && !map.isNull(key)) map.getDouble(key) else fallback
|
||||||
|
}
|
||||||
|
@JvmStatic
|
||||||
|
fun safeGetDouble(map: ReadableMap?, key: String?): Double {
|
||||||
|
return safeGetDouble(map, key, 0.0);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* toStringMap converts a [ReadableMap] into a HashMap.
|
||||||
|
*
|
||||||
|
* @param readableMap The ReadableMap to be conveted.
|
||||||
|
* @return A HashMap containing the data that was in the ReadableMap.
|
||||||
|
* @see 'Adapted from https://github.com/artemyarulin/react-native-eval/blob/master/android/src/main/java/com/evaluator/react/ConversionUtil.java'
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun toStringMap(readableMap: ReadableMap?): Map<String, String?>? {
|
||||||
|
if (readableMap == null) return null
|
||||||
|
val iterator = readableMap.keySetIterator()
|
||||||
|
if (!iterator.hasNextKey()) return null
|
||||||
|
val result: MutableMap<String, String?> = HashMap()
|
||||||
|
while (iterator.hasNextKey()) {
|
||||||
|
val key = iterator.nextKey()
|
||||||
|
result[key] = readableMap.getString(key)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toIntMap converts a [ReadableMap] into a HashMap.
|
||||||
|
*
|
||||||
|
* @param readableMap The ReadableMap to be conveted.
|
||||||
|
* @return A HashMap containing the data that was in the ReadableMap.
|
||||||
|
* @see 'Adapted from https://github.com/artemyarulin/react-native-eval/blob/master/android/src/main/java/com/evaluator/react/ConversionUtil.java'
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun toIntMap(readableMap: ReadableMap?): Map<String, Int>? {
|
||||||
|
if (readableMap == null) return null
|
||||||
|
val iterator = readableMap.keySetIterator()
|
||||||
|
if (!iterator.hasNextKey()) return null
|
||||||
|
val result: MutableMap<String, Int> = HashMap()
|
||||||
|
while (iterator.hasNextKey()) {
|
||||||
|
val key = iterator.nextKey()
|
||||||
|
result[key] = readableMap.getInt(key)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeStringEquals(str1: String?, str2: String?): Boolean {
|
||||||
|
if (str1 == null && str2 == null) return true // both are null
|
||||||
|
return if (str1 == null || str2 == null) false else str1 == str2 // only 1 is null
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeStringArrayEquals(str1: Array<String>?, str2: Array<String>?): Boolean {
|
||||||
|
if (str1 == null && str2 == null) return true // both are null
|
||||||
|
if (str1 == null || str2 == null) return false // only 1 is null
|
||||||
|
if (str1.size != str2.size) return false // only 1 is null
|
||||||
|
for (i in str1.indices) {
|
||||||
|
if (str1[i] == str2[i]) // standard check
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun safeStringMapEquals(
|
||||||
|
first: Map<String?, String?>?,
|
||||||
|
second: Map<String?, String?>?
|
||||||
|
): Boolean {
|
||||||
|
if (first == null && second == null) return true // both are null
|
||||||
|
if (first == null || second == null) return false // only 1 is null
|
||||||
|
if (first.size != second.size) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for (key in first.keys) {
|
||||||
|
if (!safeStringEquals(first[key], second[key])) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,6 @@ import android.os.Handler;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.accessibility.CaptioningManager;
|
import android.view.accessibility.CaptioningManager;
|
||||||
@ -28,6 +27,7 @@ import androidx.activity.OnBackPressedCallback;
|
|||||||
|
|
||||||
import com.brentvatne.common.Track;
|
import com.brentvatne.common.Track;
|
||||||
import com.brentvatne.common.VideoTrack;
|
import com.brentvatne.common.VideoTrack;
|
||||||
|
import com.brentvatne.common.toolbox.DebugLog;
|
||||||
import com.brentvatne.exoplayer.AudioOutput;
|
import com.brentvatne.exoplayer.AudioOutput;
|
||||||
import com.brentvatne.react.R;
|
import com.brentvatne.react.R;
|
||||||
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
|
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
|
||||||
@ -531,7 +531,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (runtime.freeMemory() == 0) {
|
if (runtime.freeMemory() == 0) {
|
||||||
Log.w("ExoPlayer Warning", "Free memory reached 0, forcing garbage collection");
|
DebugLog.w("ExoPlayer Warning", "Free memory reached 0, forcing garbage collection");
|
||||||
runtime.gc();
|
runtime.gc();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -569,13 +569,13 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
DrmSessionManager drmSessionManager = initializePlayerDrm(self);
|
DrmSessionManager drmSessionManager = initializePlayerDrm(self);
|
||||||
if (drmSessionManager == null && self.drmUUID != null) {
|
if (drmSessionManager == null && self.drmUUID != null) {
|
||||||
// Failed to intialize DRM session manager - cannot continue
|
// Failed to intialize DRM session manager - cannot continue
|
||||||
Log.e("ExoPlayer Exception", "Failed to initialize DRM Session Manager Framework!");
|
DebugLog.e("ExoPlayer Exception", "Failed to initialize DRM Session Manager Framework!");
|
||||||
eventEmitter.error("Failed to initialize DRM Session Manager Framework!", new Exception("DRM Session Manager Framework failure!"), "3003");
|
eventEmitter.error("Failed to initialize DRM Session Manager Framework!", new Exception("DRM Session Manager Framework failure!"), "3003");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activity == null) {
|
if (activity == null) {
|
||||||
Log.e("ExoPlayer Exception", "Failed to initialize Player!");
|
DebugLog.e("ExoPlayer Exception", "Failed to initialize Player!");
|
||||||
eventEmitter.error("Failed to initialize Player!", new Exception("Current Activity is null!"), "1001");
|
eventEmitter.error("Failed to initialize Player!", new Exception("Current Activity is null!"), "1001");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -588,8 +588,8 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
initializePlayerSource(self, drmSessionManager);
|
initializePlayerSource(self, drmSessionManager);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
self.playerNeedsSource = true;
|
self.playerNeedsSource = true;
|
||||||
Log.e("ExoPlayer Exception", "Failed to initialize Player!");
|
DebugLog.e("ExoPlayer Exception", "Failed to initialize Player!");
|
||||||
Log.e("ExoPlayer Exception", ex.toString());
|
DebugLog.e("ExoPlayer Exception", ex.toString());
|
||||||
self.eventEmitter.error(ex.toString(), ex, "1001");
|
self.eventEmitter.error(ex.toString(), ex, "1001");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -601,8 +601,8 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
self.playerNeedsSource = true;
|
self.playerNeedsSource = true;
|
||||||
Log.e("ExoPlayer Exception", "Failed to initialize Player!");
|
DebugLog.e("ExoPlayer Exception", "Failed to initialize Player!");
|
||||||
Log.e("ExoPlayer Exception", ex.toString());
|
DebugLog.e("ExoPlayer Exception", ex.toString());
|
||||||
eventEmitter.error(ex.toString(), ex, "1001");
|
eventEmitter.error(ex.toString(), ex, "1001");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -711,7 +711,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
wait();
|
wait();
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
Log.e("ExoPlayer Exception", ex.toString());
|
DebugLog.e("ExoPlayer Exception", ex.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1905,7 +1905,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
long reserveMemory = (long)minBackBufferMemoryReservePercent * runtime.maxMemory();
|
long reserveMemory = (long)minBackBufferMemoryReservePercent * runtime.maxMemory();
|
||||||
if (reserveMemory > freeMemory) {
|
if (reserveMemory > freeMemory) {
|
||||||
// We don't have enough memory in reserve so we will
|
// We don't have enough memory in reserve so we will
|
||||||
Log.w("ExoPlayer Warning", "Not enough reserve memory, setting back buffer to 0ms to reduce memory pressure!");
|
DebugLog.w("ExoPlayer Warning", "Not enough reserve memory, setting back buffer to 0ms to reduce memory pressure!");
|
||||||
this.backBufferDurationMs = 0;
|
this.backBufferDurationMs = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2027,23 +2027,23 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDrmKeysLoaded(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
|
public void onDrmKeysLoaded(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
|
||||||
Log.d("DRM Info", "onDrmKeysLoaded");
|
DebugLog.d("DRM Info", "onDrmKeysLoaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDrmSessionManagerError(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, Exception e) {
|
public void onDrmSessionManagerError(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, Exception e) {
|
||||||
Log.d("DRM Info", "onDrmSessionManagerError");
|
DebugLog.d("DRM Info", "onDrmSessionManagerError");
|
||||||
eventEmitter.error("onDrmSessionManagerError", e, "3002");
|
eventEmitter.error("onDrmSessionManagerError", e, "3002");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDrmKeysRestored(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
|
public void onDrmKeysRestored(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
|
||||||
Log.d("DRM Info", "onDrmKeysRestored");
|
DebugLog.d("DRM Info", "onDrmKeysRestored");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDrmKeysRemoved(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
|
public void onDrmKeysRemoved(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
|
||||||
Log.d("DRM Info", "onDrmKeysRemoved");
|
DebugLog.d("DRM Info", "onDrmKeysRemoved");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,7 +4,10 @@ import android.graphics.Color;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.brentvatne.common.toolbox.DebugLog;
|
||||||
|
import com.brentvatne.common.toolbox.ReactBridgeUtils;
|
||||||
import com.brentvatne.exoplayer.AudioOutput;
|
import com.brentvatne.exoplayer.AudioOutput;
|
||||||
import com.facebook.react.bridge.Dynamic;
|
import com.facebook.react.bridge.Dynamic;
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
@ -84,6 +87,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
private static final String PROP_CONTROLS = "controls";
|
private static final String PROP_CONTROLS = "controls";
|
||||||
private static final String PROP_SUBTITLE_STYLE = "subtitleStyle";
|
private static final String PROP_SUBTITLE_STYLE = "subtitleStyle";
|
||||||
private static final String PROP_SHUTTER_COLOR = "shutterColor";
|
private static final String PROP_SHUTTER_COLOR = "shutterColor";
|
||||||
|
private static final String PROP_DEBUG = "debug";
|
||||||
|
|
||||||
private ReactExoplayerConfig config;
|
private ReactExoplayerConfig config;
|
||||||
|
|
||||||
@ -128,9 +132,9 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
@ReactProp(name = PROP_DRM)
|
@ReactProp(name = PROP_DRM)
|
||||||
public void setDRM(final ReactExoplayerView videoView, @Nullable ReadableMap drm) {
|
public void setDRM(final ReactExoplayerView videoView, @Nullable ReadableMap drm) {
|
||||||
if (drm != null && drm.hasKey(PROP_DRM_TYPE)) {
|
if (drm != null && drm.hasKey(PROP_DRM_TYPE)) {
|
||||||
String drmType = drm.hasKey(PROP_DRM_TYPE) ? drm.getString(PROP_DRM_TYPE) : null;
|
String drmType = ReactBridgeUtils.safeGetString(drm, PROP_DRM_TYPE);
|
||||||
String drmLicenseServer = drm.hasKey(PROP_DRM_LICENSESERVER) ? drm.getString(PROP_DRM_LICENSESERVER) : null;
|
String drmLicenseServer = ReactBridgeUtils.safeGetString(drm, PROP_DRM_LICENSESERVER);
|
||||||
ReadableMap drmHeaders = drm.hasKey(PROP_DRM_HEADERS) ? drm.getMap(PROP_DRM_HEADERS) : null;
|
ReadableMap drmHeaders = ReactBridgeUtils.safeGetMap(drm, PROP_DRM_HEADERS);
|
||||||
if (drmType != null && drmLicenseServer != null && Util.getDrmUuid(drmType) != null) {
|
if (drmType != null && drmLicenseServer != null && Util.getDrmUuid(drmType) != null) {
|
||||||
UUID drmUUID = Util.getDrmUuid(drmType);
|
UUID drmUUID = Util.getDrmUuid(drmType);
|
||||||
videoView.setDrmType(drmUUID);
|
videoView.setDrmType(drmUUID);
|
||||||
@ -153,11 +157,12 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
@ReactProp(name = PROP_SRC)
|
@ReactProp(name = PROP_SRC)
|
||||||
public void setSrc(final ReactExoplayerView videoView, @Nullable ReadableMap src) {
|
public void setSrc(final ReactExoplayerView videoView, @Nullable ReadableMap src) {
|
||||||
Context context = videoView.getContext().getApplicationContext();
|
Context context = videoView.getContext().getApplicationContext();
|
||||||
String uriString = src.hasKey(PROP_SRC_URI) ? src.getString(PROP_SRC_URI) : null;
|
String uriString = ReactBridgeUtils.safeGetString(src, PROP_SRC_URI, null);
|
||||||
int startTimeMs = src.hasKey(PROP_SRC_START_TIME) ? src.getInt(PROP_SRC_START_TIME) : -1;
|
int startTimeMs = ReactBridgeUtils.safeGetInt(src, PROP_SRC_START_TIME, -1);
|
||||||
int endTimeMs = src.hasKey(PROP_SRC_END_TIME) ? src.getInt(PROP_SRC_END_TIME) : -1;
|
int endTimeMs = ReactBridgeUtils.safeGetInt(src, PROP_SRC_END_TIME, -1);
|
||||||
String extension = src.hasKey(PROP_SRC_TYPE) ? src.getString(PROP_SRC_TYPE) : null;
|
String extension = ReactBridgeUtils.safeGetString(src, PROP_SRC_TYPE, null);
|
||||||
Map<String, String> headers = src.hasKey(PROP_SRC_HEADERS) ? toStringMap(src.getMap(PROP_SRC_HEADERS)) : null;
|
|
||||||
|
Map<String, String> headers = src.hasKey(PROP_SRC_HEADERS) ? ReactBridgeUtils.toStringMap(src.getMap(PROP_SRC_HEADERS)) : new HashMap<>();
|
||||||
|
|
||||||
if (TextUtils.isEmpty(uriString)) {
|
if (TextUtils.isEmpty(uriString)) {
|
||||||
videoView.clearSrc();
|
videoView.clearSrc();
|
||||||
@ -227,10 +232,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
String typeString = null;
|
String typeString = null;
|
||||||
Dynamic value = null;
|
Dynamic value = null;
|
||||||
if (selectedVideoTrack != null) {
|
if (selectedVideoTrack != null) {
|
||||||
typeString = selectedVideoTrack.hasKey(PROP_SELECTED_VIDEO_TRACK_TYPE)
|
typeString = ReactBridgeUtils.safeGetString(selectedVideoTrack, PROP_SELECTED_VIDEO_TRACK_TYPE);
|
||||||
? selectedVideoTrack.getString(PROP_SELECTED_VIDEO_TRACK_TYPE) : null;
|
value = ReactBridgeUtils.safeGetDynamic(selectedVideoTrack, PROP_SELECTED_VIDEO_TRACK_VALUE);
|
||||||
value = selectedVideoTrack.hasKey(PROP_SELECTED_VIDEO_TRACK_VALUE)
|
|
||||||
? selectedVideoTrack.getDynamic(PROP_SELECTED_VIDEO_TRACK_VALUE) : null;
|
|
||||||
}
|
}
|
||||||
videoView.setSelectedVideoTrack(typeString, value);
|
videoView.setSelectedVideoTrack(typeString, value);
|
||||||
}
|
}
|
||||||
@ -241,10 +244,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
String typeString = null;
|
String typeString = null;
|
||||||
Dynamic value = null;
|
Dynamic value = null;
|
||||||
if (selectedAudioTrack != null) {
|
if (selectedAudioTrack != null) {
|
||||||
typeString = selectedAudioTrack.hasKey(PROP_SELECTED_AUDIO_TRACK_TYPE)
|
typeString = ReactBridgeUtils.safeGetString(selectedAudioTrack, PROP_SELECTED_AUDIO_TRACK_TYPE);
|
||||||
? selectedAudioTrack.getString(PROP_SELECTED_AUDIO_TRACK_TYPE) : null;
|
value = ReactBridgeUtils.safeGetDynamic(selectedAudioTrack, PROP_SELECTED_AUDIO_TRACK_VALUE);
|
||||||
value = selectedAudioTrack.hasKey(PROP_SELECTED_AUDIO_TRACK_VALUE)
|
|
||||||
? selectedAudioTrack.getDynamic(PROP_SELECTED_AUDIO_TRACK_VALUE) : null;
|
|
||||||
}
|
}
|
||||||
videoView.setSelectedAudioTrack(typeString, value);
|
videoView.setSelectedAudioTrack(typeString, value);
|
||||||
}
|
}
|
||||||
@ -255,10 +256,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
String typeString = null;
|
String typeString = null;
|
||||||
Dynamic value = null;
|
Dynamic value = null;
|
||||||
if (selectedTextTrack != null) {
|
if (selectedTextTrack != null) {
|
||||||
typeString = selectedTextTrack.hasKey(PROP_SELECTED_TEXT_TRACK_TYPE)
|
typeString = ReactBridgeUtils.safeGetString(selectedTextTrack, PROP_SELECTED_TEXT_TRACK_TYPE);
|
||||||
? selectedTextTrack.getString(PROP_SELECTED_TEXT_TRACK_TYPE) : null;
|
value = ReactBridgeUtils.safeGetDynamic(selectedTextTrack, PROP_SELECTED_TEXT_TRACK_VALUE);
|
||||||
value = selectedTextTrack.hasKey(PROP_SELECTED_TEXT_TRACK_VALUE)
|
|
||||||
? selectedTextTrack.getDynamic(PROP_SELECTED_TEXT_TRACK_VALUE) : null;
|
|
||||||
}
|
}
|
||||||
videoView.setSelectedTextTrack(typeString, value);
|
videoView.setSelectedTextTrack(typeString, value);
|
||||||
}
|
}
|
||||||
@ -400,24 +399,29 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
|
double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
|
||||||
|
|
||||||
if (bufferConfig != null) {
|
if (bufferConfig != null) {
|
||||||
minBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BUFFER_MS)
|
minBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MS, minBufferMs);
|
||||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_MIN_BUFFER_MS) : minBufferMs;
|
maxBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MAX_BUFFER_MS, maxBufferMs);
|
||||||
maxBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MAX_BUFFER_MS)
|
bufferForPlaybackMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS, bufferForPlaybackMs);
|
||||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_MAX_BUFFER_MS) : maxBufferMs;
|
bufferForPlaybackAfterRebufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS, bufferForPlaybackAfterRebufferMs);
|
||||||
bufferForPlaybackMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS)
|
maxHeapAllocationPercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT, maxHeapAllocationPercent);
|
||||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS) : bufferForPlaybackMs;
|
minBackBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT, minBackBufferMemoryReservePercent);
|
||||||
bufferForPlaybackAfterRebufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS)
|
minBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT, minBufferMemoryReservePercent);
|
||||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS) : bufferForPlaybackAfterRebufferMs;
|
|
||||||
maxHeapAllocationPercent = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT)
|
|
||||||
? bufferConfig.getDouble(PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT) : maxHeapAllocationPercent;
|
|
||||||
minBackBufferMemoryReservePercent = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT)
|
|
||||||
? bufferConfig.getDouble(PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT) : minBackBufferMemoryReservePercent;
|
|
||||||
minBufferMemoryReservePercent = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT)
|
|
||||||
? bufferConfig.getDouble(PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT) : minBufferMemoryReservePercent;
|
|
||||||
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, maxHeapAllocationPercent, minBackBufferMemoryReservePercent, minBufferMemoryReservePercent);
|
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, maxHeapAllocationPercent, minBackBufferMemoryReservePercent, minBufferMemoryReservePercent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = PROP_DEBUG, defaultBoolean = false)
|
||||||
|
public void setDebug(final ReactExoplayerView videoView,
|
||||||
|
@Nullable final ReadableMap debugConfig) {
|
||||||
|
boolean enableDebug = ReactBridgeUtils.safeGetBool(debugConfig, "enable", false);
|
||||||
|
boolean enableThreadDebug = ReactBridgeUtils.safeGetBool(debugConfig, "thread", false);
|
||||||
|
if (enableDebug) {
|
||||||
|
DebugLog.setConfig(Log.VERBOSE, enableThreadDebug);
|
||||||
|
} else {
|
||||||
|
DebugLog.setConfig(Log.WARN, enableThreadDebug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean startsWithValidScheme(String uriString) {
|
private boolean startsWithValidScheme(String uriString) {
|
||||||
String lowerCaseUri = uriString.toLowerCase();
|
String lowerCaseUri = uriString.toLowerCase();
|
||||||
return lowerCaseUri.startsWith("http://")
|
return lowerCaseUri.startsWith("http://")
|
||||||
@ -434,28 +438,4 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
}
|
}
|
||||||
return ResizeMode.RESIZE_MODE_FIT;
|
return ResizeMode.RESIZE_MODE_FIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* toStringMap converts a {@link ReadableMap} into a HashMap.
|
|
||||||
*
|
|
||||||
* @param readableMap The ReadableMap to be conveted.
|
|
||||||
* @return A HashMap containing the data that was in the ReadableMap.
|
|
||||||
* @see 'Adapted from https://github.com/artemyarulin/react-native-eval/blob/master/android/src/main/java/com/evaluator/react/ConversionUtil.java'
|
|
||||||
*/
|
|
||||||
public static Map<String, String> toStringMap(@Nullable ReadableMap readableMap) {
|
|
||||||
if (readableMap == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
com.facebook.react.bridge.ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
|
||||||
if (!iterator.hasNextKey())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Map<String, String> result = new HashMap<>();
|
|
||||||
while (iterator.hasNextKey()) {
|
|
||||||
String key = iterator.nextKey();
|
|
||||||
result.put(key, readableMap.getString(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,11 @@ export type Filter =
|
|||||||
|
|
||||||
export type DrmType = 'widevine' | 'playready' | 'clearkey' | 'fairplay';
|
export type DrmType = 'widevine' | 'playready' | 'clearkey' | 'fairplay';
|
||||||
|
|
||||||
|
type DebugConfig = Readonly<{
|
||||||
|
enable?: boolean;
|
||||||
|
thread?: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
type Drm = Readonly<{
|
type Drm = Readonly<{
|
||||||
drmType?: DrmType;
|
drmType?: DrmType;
|
||||||
licenseServer?: string;
|
licenseServer?: string;
|
||||||
@ -262,6 +267,7 @@ export interface VideoNativeProps extends ViewProps {
|
|||||||
progressUpdateInterval?: number;
|
progressUpdateInterval?: number;
|
||||||
restoreUserInterfaceForPIPStopCompletionHandler?: boolean;
|
restoreUserInterfaceForPIPStopCompletionHandler?: boolean;
|
||||||
localSourceEncryptionKeyScheme?: string;
|
localSourceEncryptionKeyScheme?: string;
|
||||||
|
debug?: DebugConfig;
|
||||||
|
|
||||||
backBufferDurationMs?: number; // Android
|
backBufferDurationMs?: number; // Android
|
||||||
bufferConfig?: BufferConfig; // Android
|
bufferConfig?: BufferConfig; // Android
|
||||||
|
@ -39,6 +39,11 @@ export type ReactVideoSource = Readonly<{
|
|||||||
customImageUri?: string;
|
customImageUri?: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
type DebugConfig = Readonly<{
|
||||||
|
enable?: boolean;
|
||||||
|
thread?: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
export type ReactVideoDrm = Readonly<{
|
export type ReactVideoDrm = Readonly<{
|
||||||
type?: 'widevine' | 'playready' | 'clearkey' | 'fairplay';
|
type?: 'widevine' | 'playready' | 'clearkey' | 'fairplay';
|
||||||
licenseServer?: string;
|
licenseServer?: string;
|
||||||
@ -153,4 +158,5 @@ export interface ReactVideoProps extends ReactVideoEvents {
|
|||||||
useSecureView?: boolean; // Android
|
useSecureView?: boolean; // Android
|
||||||
volume?: number;
|
volume?: number;
|
||||||
localSourceEncryptionKeyScheme?: string;
|
localSourceEncryptionKeyScheme?: string;
|
||||||
|
debug?: DebugConfig;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user