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:
		
							
								
								
									
										23
									
								
								API.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								API.md
									
									
									
									
									
								
							| @@ -301,6 +301,7 @@ var styles = StyleSheet.create({ | ||||
| | [contentStartTime](#contentstarttime)                                               | Android                   | | ||||
| | [controls](#controls)                                                               | Android, iOS              | | ||||
| | [currentPlaybackTime](#currentplaybacktime)                                         | Android                   | | ||||
| | [debug](#debug)                                                                     | Android                   | | ||||
| | [disableFocus](#disablefocus)                                                       | Android, iOS              | | ||||
| | [disableDisconnectError](#disabledisconnecterror)                                   | Android                   | | ||||
| | [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 | ||||
|  | ||||
| #### 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 | ||||
| Determines whether video audio should override background music/audio in Android devices. | ||||
| * **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.Message; | ||||
| import android.text.TextUtils; | ||||
| import android.util.Log; | ||||
| import android.view.View; | ||||
| import android.view.Window; | ||||
| import android.view.accessibility.CaptioningManager; | ||||
| @@ -28,6 +27,7 @@ import androidx.activity.OnBackPressedCallback; | ||||
|  | ||||
| import com.brentvatne.common.Track; | ||||
| import com.brentvatne.common.VideoTrack; | ||||
| import com.brentvatne.common.toolbox.DebugLog; | ||||
| import com.brentvatne.exoplayer.AudioOutput; | ||||
| import com.brentvatne.react.R; | ||||
| import com.brentvatne.receiver.AudioBecomingNoisyReceiver; | ||||
| @@ -531,7 +531,7 @@ public class ReactExoplayerView extends FrameLayout implements | ||||
|                 return false; | ||||
|             } | ||||
|             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(); | ||||
|                 return false; | ||||
|             } | ||||
| @@ -569,13 +569,13 @@ public class ReactExoplayerView extends FrameLayout implements | ||||
|                                 DrmSessionManager drmSessionManager = initializePlayerDrm(self); | ||||
|                                 if (drmSessionManager == null && self.drmUUID != null) { | ||||
|                                     // 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"); | ||||
|                                     return; | ||||
|                                 } | ||||
|                                      | ||||
|                                 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"); | ||||
|                                     return; | ||||
|                                 } | ||||
| @@ -588,8 +588,8 @@ public class ReactExoplayerView extends FrameLayout implements | ||||
|                                             initializePlayerSource(self, drmSessionManager); | ||||
|                                         } catch (Exception ex) { | ||||
|                                             self.playerNeedsSource = true; | ||||
|                                             Log.e("ExoPlayer Exception", "Failed to initialize Player!"); | ||||
|                                             Log.e("ExoPlayer Exception", ex.toString()); | ||||
|                                             DebugLog.e("ExoPlayer Exception", "Failed to initialize Player!"); | ||||
|                                             DebugLog.e("ExoPlayer Exception", ex.toString()); | ||||
|                                             self.eventEmitter.error(ex.toString(), ex, "1001"); | ||||
|                                         } | ||||
|                                     } | ||||
| @@ -601,8 +601,8 @@ public class ReactExoplayerView extends FrameLayout implements | ||||
|                     } | ||||
|                 } catch (Exception ex) { | ||||
|                     self.playerNeedsSource = true; | ||||
|                     Log.e("ExoPlayer Exception", "Failed to initialize Player!"); | ||||
|                     Log.e("ExoPlayer Exception", ex.toString()); | ||||
|                     DebugLog.e("ExoPlayer Exception", "Failed to initialize Player!"); | ||||
|                     DebugLog.e("ExoPlayer Exception", ex.toString()); | ||||
|                     eventEmitter.error(ex.toString(), ex, "1001"); | ||||
|                 } | ||||
|             } | ||||
| @@ -711,7 +711,7 @@ public class ReactExoplayerView extends FrameLayout implements | ||||
|                 wait(); | ||||
|             } catch (InterruptedException ex) { | ||||
|                 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(); | ||||
|         if (reserveMemory > freeMemory) { | ||||
|             // 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; | ||||
|             return; | ||||
|         } | ||||
| @@ -2027,23 +2027,23 @@ public class ReactExoplayerView extends FrameLayout implements | ||||
|  | ||||
|     @Override | ||||
|     public void onDrmKeysLoaded(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { | ||||
|         Log.d("DRM Info", "onDrmKeysLoaded"); | ||||
|         DebugLog.d("DRM Info", "onDrmKeysLoaded"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     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"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDrmKeysRestored(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { | ||||
|         Log.d("DRM Info", "onDrmKeysRestored"); | ||||
|         DebugLog.d("DRM Info", "onDrmKeysRestored"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     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.net.Uri; | ||||
| 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.facebook.react.bridge.Dynamic; | ||||
| 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_SUBTITLE_STYLE = "subtitleStyle"; | ||||
|     private static final String PROP_SHUTTER_COLOR = "shutterColor"; | ||||
|     private static final String PROP_DEBUG = "debug"; | ||||
|  | ||||
|     private ReactExoplayerConfig config; | ||||
|  | ||||
| @@ -128,9 +132,9 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|     @ReactProp(name = PROP_DRM) | ||||
|     public void setDRM(final ReactExoplayerView videoView, @Nullable ReadableMap drm) { | ||||
|         if (drm != null && drm.hasKey(PROP_DRM_TYPE)) { | ||||
|             String drmType = drm.hasKey(PROP_DRM_TYPE) ? drm.getString(PROP_DRM_TYPE) : null; | ||||
|             String drmLicenseServer = drm.hasKey(PROP_DRM_LICENSESERVER) ? drm.getString(PROP_DRM_LICENSESERVER) : null; | ||||
|             ReadableMap drmHeaders = drm.hasKey(PROP_DRM_HEADERS) ? drm.getMap(PROP_DRM_HEADERS) : null; | ||||
|             String drmType = ReactBridgeUtils.safeGetString(drm, PROP_DRM_TYPE); | ||||
|             String drmLicenseServer = ReactBridgeUtils.safeGetString(drm, PROP_DRM_LICENSESERVER); | ||||
|             ReadableMap drmHeaders = ReactBridgeUtils.safeGetMap(drm, PROP_DRM_HEADERS); | ||||
|             if (drmType != null && drmLicenseServer != null && Util.getDrmUuid(drmType) != null) { | ||||
|                 UUID drmUUID = Util.getDrmUuid(drmType); | ||||
|                 videoView.setDrmType(drmUUID); | ||||
| @@ -153,11 +157,12 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|     @ReactProp(name = PROP_SRC) | ||||
|     public void setSrc(final ReactExoplayerView videoView, @Nullable ReadableMap src) { | ||||
|         Context context = videoView.getContext().getApplicationContext(); | ||||
|         String uriString = src.hasKey(PROP_SRC_URI) ? src.getString(PROP_SRC_URI) : null; | ||||
|         int startTimeMs = src.hasKey(PROP_SRC_START_TIME) ? src.getInt(PROP_SRC_START_TIME) : -1; | ||||
|         int endTimeMs = src.hasKey(PROP_SRC_END_TIME) ? src.getInt(PROP_SRC_END_TIME) : -1; | ||||
|         String extension = src.hasKey(PROP_SRC_TYPE) ? src.getString(PROP_SRC_TYPE) : null; | ||||
|         Map<String, String> headers = src.hasKey(PROP_SRC_HEADERS) ? toStringMap(src.getMap(PROP_SRC_HEADERS)) : null; | ||||
|         String uriString = ReactBridgeUtils.safeGetString(src, PROP_SRC_URI, null); | ||||
|         int startTimeMs = ReactBridgeUtils.safeGetInt(src, PROP_SRC_START_TIME, -1); | ||||
|         int endTimeMs = ReactBridgeUtils.safeGetInt(src, PROP_SRC_END_TIME, -1); | ||||
|         String extension = ReactBridgeUtils.safeGetString(src, PROP_SRC_TYPE, null); | ||||
|  | ||||
|         Map<String, String> headers = src.hasKey(PROP_SRC_HEADERS) ? ReactBridgeUtils.toStringMap(src.getMap(PROP_SRC_HEADERS)) : new HashMap<>(); | ||||
|  | ||||
|         if (TextUtils.isEmpty(uriString)) { | ||||
|             videoView.clearSrc(); | ||||
| @@ -227,10 +232,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|         String typeString = null; | ||||
|         Dynamic value = null; | ||||
|         if (selectedVideoTrack != null) { | ||||
|             typeString = selectedVideoTrack.hasKey(PROP_SELECTED_VIDEO_TRACK_TYPE) | ||||
|                     ? selectedVideoTrack.getString(PROP_SELECTED_VIDEO_TRACK_TYPE) : null; | ||||
|             value = selectedVideoTrack.hasKey(PROP_SELECTED_VIDEO_TRACK_VALUE) | ||||
|                     ? selectedVideoTrack.getDynamic(PROP_SELECTED_VIDEO_TRACK_VALUE) : null; | ||||
|             typeString = ReactBridgeUtils.safeGetString(selectedVideoTrack, PROP_SELECTED_VIDEO_TRACK_TYPE); | ||||
|             value = ReactBridgeUtils.safeGetDynamic(selectedVideoTrack, PROP_SELECTED_VIDEO_TRACK_VALUE); | ||||
|         } | ||||
|         videoView.setSelectedVideoTrack(typeString, value); | ||||
|     } | ||||
| @@ -241,10 +244,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|         String typeString = null; | ||||
|         Dynamic value = null; | ||||
|         if (selectedAudioTrack != null) { | ||||
|             typeString = selectedAudioTrack.hasKey(PROP_SELECTED_AUDIO_TRACK_TYPE) | ||||
|                     ? selectedAudioTrack.getString(PROP_SELECTED_AUDIO_TRACK_TYPE) : null; | ||||
|             value = selectedAudioTrack.hasKey(PROP_SELECTED_AUDIO_TRACK_VALUE) | ||||
|                     ? selectedAudioTrack.getDynamic(PROP_SELECTED_AUDIO_TRACK_VALUE) : null; | ||||
|             typeString = ReactBridgeUtils.safeGetString(selectedAudioTrack, PROP_SELECTED_AUDIO_TRACK_TYPE); | ||||
|             value = ReactBridgeUtils.safeGetDynamic(selectedAudioTrack, PROP_SELECTED_AUDIO_TRACK_VALUE); | ||||
|         } | ||||
|         videoView.setSelectedAudioTrack(typeString, value); | ||||
|     } | ||||
| @@ -255,10 +256,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|         String typeString = null; | ||||
|         Dynamic value = null; | ||||
|         if (selectedTextTrack != null) { | ||||
|             typeString = selectedTextTrack.hasKey(PROP_SELECTED_TEXT_TRACK_TYPE) | ||||
|                     ? selectedTextTrack.getString(PROP_SELECTED_TEXT_TRACK_TYPE) : null; | ||||
|             value = selectedTextTrack.hasKey(PROP_SELECTED_TEXT_TRACK_VALUE) | ||||
|                     ? selectedTextTrack.getDynamic(PROP_SELECTED_TEXT_TRACK_VALUE) : null; | ||||
|             typeString = ReactBridgeUtils.safeGetString(selectedTextTrack, PROP_SELECTED_TEXT_TRACK_TYPE); | ||||
|             value = ReactBridgeUtils.safeGetDynamic(selectedTextTrack, PROP_SELECTED_TEXT_TRACK_VALUE); | ||||
|         } | ||||
|         videoView.setSelectedTextTrack(typeString, value); | ||||
|     } | ||||
| @@ -400,24 +399,29 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|         double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE; | ||||
|  | ||||
|         if (bufferConfig != null) { | ||||
|             minBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BUFFER_MS) | ||||
|                     ? bufferConfig.getInt(PROP_BUFFER_CONFIG_MIN_BUFFER_MS) : minBufferMs; | ||||
|             maxBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MAX_BUFFER_MS) | ||||
|                     ? bufferConfig.getInt(PROP_BUFFER_CONFIG_MAX_BUFFER_MS) : maxBufferMs; | ||||
|             bufferForPlaybackMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS) | ||||
|                     ? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS) : bufferForPlaybackMs; | ||||
|             bufferForPlaybackAfterRebufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS) | ||||
|                     ? 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; | ||||
|             minBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MS, minBufferMs); | ||||
|             maxBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MAX_BUFFER_MS, maxBufferMs); | ||||
|             bufferForPlaybackMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS, bufferForPlaybackMs); | ||||
|             bufferForPlaybackAfterRebufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS, bufferForPlaybackAfterRebufferMs); | ||||
|             maxHeapAllocationPercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MAX_HEAP_ALLOCATION_PERCENT, maxHeapAllocationPercent); | ||||
|             minBackBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT, minBackBufferMemoryReservePercent); | ||||
|             minBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT, 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) { | ||||
|         String lowerCaseUri = uriString.toLowerCase(); | ||||
|         return lowerCaseUri.startsWith("http://") | ||||
| @@ -434,28 +438,4 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|         } | ||||
|         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'; | ||||
|  | ||||
| type DebugConfig = Readonly<{ | ||||
|   enable?: boolean; | ||||
|   thread?: boolean; | ||||
| }>; | ||||
|  | ||||
| type Drm = Readonly<{ | ||||
|   drmType?: DrmType; | ||||
|   licenseServer?: string; | ||||
| @@ -262,6 +267,7 @@ export interface VideoNativeProps extends ViewProps { | ||||
|   progressUpdateInterval?: number; | ||||
|   restoreUserInterfaceForPIPStopCompletionHandler?: boolean; | ||||
|   localSourceEncryptionKeyScheme?: string; | ||||
|   debug?: DebugConfig; | ||||
|  | ||||
|   backBufferDurationMs?: number; // Android | ||||
|   bufferConfig?: BufferConfig; // Android | ||||
|   | ||||
| @@ -39,6 +39,11 @@ export type ReactVideoSource = Readonly<{ | ||||
|   customImageUri?: string; | ||||
| }>; | ||||
|  | ||||
| type DebugConfig = Readonly<{ | ||||
|   enable?: boolean; | ||||
|   thread?: boolean; | ||||
| }>; | ||||
|  | ||||
| export type ReactVideoDrm = Readonly<{ | ||||
|   type?: 'widevine' | 'playready' | 'clearkey' | 'fairplay'; | ||||
|   licenseServer?: string; | ||||
| @@ -153,4 +158,5 @@ export interface ReactVideoProps extends ReactVideoEvents { | ||||
|   useSecureView?: boolean; // Android | ||||
|   volume?: number; | ||||
|   localSourceEncryptionKeyScheme?: string; | ||||
|   debug?: DebugConfig; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user