added optional request headers for remote assests (android & ios)
This commit is contained in:
parent
f73b7a0484
commit
270fdfb657
11
Video.js
11
Video.js
@ -24,6 +24,16 @@ export default class Video extends Component {
|
||||
this._root.setNativeProps(nativeProps);
|
||||
}
|
||||
|
||||
stringsOnlyObject(obj) {
|
||||
const strObj = {};
|
||||
|
||||
Object.keys(obj).forEach(x => {
|
||||
strObj[x] = obj[x].toString();
|
||||
});
|
||||
|
||||
return strObj;
|
||||
}
|
||||
|
||||
seek = (time) => {
|
||||
this.setNativeProps({ seek: time });
|
||||
};
|
||||
@ -190,6 +200,7 @@ export default class Video extends Component {
|
||||
type: source.type || '',
|
||||
mainVer: source.mainVer || 0,
|
||||
patchVer: source.patchVer || 0,
|
||||
requestHeaders: source.headers ? this.stringsOnlyObject(source.headers) : {}
|
||||
},
|
||||
onVideoLoadStart: this._onLoadStart,
|
||||
onVideoLoad: this._onLoad,
|
||||
|
@ -1,7 +1,10 @@
|
||||
package com.brentvatne.exoplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableNativeMap;
|
||||
import com.facebook.react.modules.network.OkHttpClientProvider;
|
||||
import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
@ -10,6 +13,10 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DataSourceUtil {
|
||||
|
||||
private DataSourceUtil() {
|
||||
@ -41,9 +48,9 @@ public class DataSourceUtil {
|
||||
DataSourceUtil.rawDataSourceFactory = factory;
|
||||
}
|
||||
|
||||
public static DataSource.Factory getDefaultDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter) {
|
||||
public static DataSource.Factory getDefaultDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter, Map<String, String> requestHeaders) {
|
||||
if (defaultDataSourceFactory == null) {
|
||||
defaultDataSourceFactory = buildDataSourceFactory(context, bandwidthMeter);
|
||||
defaultDataSourceFactory = buildDataSourceFactory(context, bandwidthMeter, requestHeaders);
|
||||
}
|
||||
return defaultDataSourceFactory;
|
||||
}
|
||||
@ -56,14 +63,18 @@ public class DataSourceUtil {
|
||||
return new RawResourceDataSourceFactory(context.getApplicationContext());
|
||||
}
|
||||
|
||||
private static DataSource.Factory buildDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter) {
|
||||
private static DataSource.Factory buildDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter, Map<String, String> requestHeaders) {
|
||||
Context appContext = context.getApplicationContext();
|
||||
return new DefaultDataSourceFactory(appContext, bandwidthMeter,
|
||||
buildHttpDataSourceFactory(appContext, bandwidthMeter));
|
||||
buildHttpDataSourceFactory(appContext, bandwidthMeter, requestHeaders));
|
||||
}
|
||||
|
||||
private static HttpDataSource.Factory buildHttpDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter) {
|
||||
return new OkHttpDataSourceFactory(OkHttpClientProvider.getOkHttpClient(), getUserAgent(context), bandwidthMeter);
|
||||
}
|
||||
private static HttpDataSource.Factory buildHttpDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter, Map<String, String> requestHeaders) {
|
||||
OkHttpDataSourceFactory okHttpDataSourceFactory = new OkHttpDataSourceFactory(OkHttpClientProvider.getOkHttpClient(), getUserAgent(context), bandwidthMeter);
|
||||
|
||||
if (requestHeaders != null)
|
||||
okHttpDataSourceFactory.getDefaultRequestProperties().set(requestHeaders);
|
||||
|
||||
return okHttpDataSourceFactory;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import com.brentvatne.react.R;
|
||||
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
|
||||
import com.brentvatne.receiver.BecomingNoisyListener;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.DefaultLoadControl;
|
||||
@ -52,6 +53,7 @@ import java.net.CookieHandler;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
import java.lang.Math;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
class ReactExoplayerView extends FrameLayout implements
|
||||
@ -96,6 +98,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
private boolean disableFocus;
|
||||
private float mProgressUpdateInterval = 250.0f;
|
||||
private boolean playInBackground = false;
|
||||
private Map<String, String> requestHeaders;
|
||||
// \ End props
|
||||
|
||||
// React
|
||||
@ -353,7 +356,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
* @return A new DataSource factory.
|
||||
*/
|
||||
private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) {
|
||||
return DataSourceUtil.getDefaultDataSourceFactory(getContext(), useBandwidthMeter ? BANDWIDTH_METER : null);
|
||||
return DataSourceUtil.getDefaultDataSourceFactory(getContext(), useBandwidthMeter ? BANDWIDTH_METER : null, requestHeaders);
|
||||
}
|
||||
|
||||
// AudioManager.OnAudioFocusChangeListener implementation
|
||||
@ -537,14 +540,15 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
|
||||
// ReactExoplayerViewManager public api
|
||||
|
||||
public void setSrc(final Uri uri, final String extension) {
|
||||
public void setSrc(final Uri uri, final String extension, Map<String, String> headers) {
|
||||
if (uri != null) {
|
||||
boolean isOriginalSourceNull = srcUri == null;
|
||||
boolean isSourceEqual = uri.equals(srcUri);
|
||||
|
||||
this.srcUri = uri;
|
||||
this.extension = extension;
|
||||
this.mediaDataSourceFactory = DataSourceUtil.getDefaultDataSourceFactory(getContext(), BANDWIDTH_METER);
|
||||
this.requestHeaders = headers;
|
||||
this.mediaDataSourceFactory = DataSourceUtil.getDefaultDataSourceFactory(getContext(), BANDWIDTH_METER, requestHeaders);
|
||||
|
||||
if (!isOriginalSourceNull && !isSourceEqual) {
|
||||
reloadSource();
|
||||
|
@ -11,6 +11,7 @@ import com.facebook.react.uimanager.ViewGroupManager;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.google.android.exoplayer2.upstream.RawResourceDataSource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -22,6 +23,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
private static final String PROP_SRC = "src";
|
||||
private static final String PROP_SRC_URI = "uri";
|
||||
private static final String PROP_SRC_TYPE = "type";
|
||||
private static final String PROP_SRC_HEADERS = "headers";
|
||||
private static final String PROP_RESIZE_MODE = "resizeMode";
|
||||
private static final String PROP_REPEAT = "repeat";
|
||||
private static final String PROP_PAUSED = "paused";
|
||||
@ -72,6 +74,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
Context context = videoView.getContext().getApplicationContext();
|
||||
String uriString = src.hasKey(PROP_SRC_URI) ? src.getString(PROP_SRC_URI) : null;
|
||||
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;
|
||||
|
||||
|
||||
if (TextUtils.isEmpty(uriString)) {
|
||||
return;
|
||||
@ -81,7 +85,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
Uri srcUri = Uri.parse(uriString);
|
||||
|
||||
if (srcUri != null) {
|
||||
videoView.setSrc(srcUri, extension);
|
||||
videoView.setSrc(srcUri, extension, headers);
|
||||
}
|
||||
} else {
|
||||
int identifier = context.getResources().getIdentifier(
|
||||
@ -170,4 +174,28 @@ 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;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import com.android.vending.expansion.zipfile.APKExpansionSupport;
|
||||
import com.android.vending.expansion.zipfile.ZipResourceFile;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
@ -28,6 +29,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.lang.Math;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnPreparedListener, MediaPlayer
|
||||
.OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener, LifecycleEventListener, MediaController.MediaPlayerControl {
|
||||
@ -86,6 +89,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
|
||||
private String mSrcUriString = null;
|
||||
private String mSrcType = "mp4";
|
||||
private ReadableMap mRequestHeaders = null;
|
||||
private boolean mSrcIsNetwork = false;
|
||||
private boolean mSrcIsAsset = false;
|
||||
private ScalableType mResizeMode = ScalableType.LEFT_TOP;
|
||||
@ -201,16 +205,17 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
}
|
||||
}
|
||||
|
||||
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset) {
|
||||
setSrc(uriString,type,isNetwork,isAsset,0,0);
|
||||
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders) {
|
||||
setSrc(uriString, type, isNetwork, isAsset, requestHeaders, 0, 0);
|
||||
}
|
||||
|
||||
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final int expansionMainVersion, final int expansionPatchVersion) {
|
||||
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders, final int expansionMainVersion, final int expansionPatchVersion) {
|
||||
|
||||
mSrcUriString = uriString;
|
||||
mSrcType = type;
|
||||
mSrcIsNetwork = isNetwork;
|
||||
mSrcIsAsset = isAsset;
|
||||
mRequestHeaders = requestHeaders;
|
||||
mMainVer = expansionMainVersion;
|
||||
mPatchVer = expansionPatchVersion;
|
||||
|
||||
@ -239,6 +244,10 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
headers.put("Cookie", cookie);
|
||||
}
|
||||
|
||||
if (mRequestHeaders != null) {
|
||||
headers.putAll(toStringMap(mRequestHeaders));
|
||||
}
|
||||
|
||||
setDataSource(uriString);
|
||||
} else if (isAsset) {
|
||||
if (uriString.startsWith("content://")) {
|
||||
@ -285,8 +294,13 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
}
|
||||
|
||||
WritableMap src = Arguments.createMap();
|
||||
|
||||
WritableMap wRequestHeaders = Arguments.createMap();
|
||||
wRequestHeaders.merge(mRequestHeaders);
|
||||
|
||||
src.putString(ReactVideoViewManager.PROP_SRC_URI, uriString);
|
||||
src.putString(ReactVideoViewManager.PROP_SRC_TYPE, type);
|
||||
src.putMap(ReactVideoViewManager.PROP_SRC_HEADERS, wRequestHeaders);
|
||||
src.putBoolean(ReactVideoViewManager.PROP_SRC_IS_NETWORK, isNetwork);
|
||||
if(mMainVer>0) {
|
||||
src.putInt(ReactVideoViewManager.PROP_SRC_MAINVER, mMainVer);
|
||||
@ -542,10 +556,10 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
super.onAttachedToWindow();
|
||||
|
||||
if(mMainVer>0) {
|
||||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork,mSrcIsAsset,mMainVer,mPatchVer);
|
||||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders, mMainVer, mPatchVer);
|
||||
}
|
||||
else {
|
||||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork,mSrcIsAsset);
|
||||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders);
|
||||
}
|
||||
|
||||
}
|
||||
@ -577,4 +591,28 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
@Override
|
||||
public void onHostDestroy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ public class ReactVideoViewManager extends SimpleViewManager<ReactVideoView> {
|
||||
public static final String PROP_SRC = "src";
|
||||
public static final String PROP_SRC_URI = "uri";
|
||||
public static final String PROP_SRC_TYPE = "type";
|
||||
public static final String PROP_SRC_HEADERS = "headers";
|
||||
public static final String PROP_SRC_IS_NETWORK = "isNetwork";
|
||||
public static final String PROP_SRC_MAINVER = "mainVer";
|
||||
public static final String PROP_SRC_PATCHVER = "patchVer";
|
||||
@ -85,6 +86,7 @@ public class ReactVideoViewManager extends SimpleViewManager<ReactVideoView> {
|
||||
src.getString(PROP_SRC_TYPE),
|
||||
src.getBoolean(PROP_SRC_IS_NETWORK),
|
||||
src.getBoolean(PROP_SRC_IS_ASSET),
|
||||
src.getMap(PROP_SRC_HEADERS),
|
||||
mainVer,
|
||||
patchVer
|
||||
);
|
||||
@ -94,8 +96,9 @@ public class ReactVideoViewManager extends SimpleViewManager<ReactVideoView> {
|
||||
src.getString(PROP_SRC_URI),
|
||||
src.getString(PROP_SRC_TYPE),
|
||||
src.getBoolean(PROP_SRC_IS_NETWORK),
|
||||
src.getBoolean(PROP_SRC_IS_ASSET)
|
||||
);
|
||||
src.getBoolean(PROP_SRC_IS_ASSET),
|
||||
src.getMap(PROP_SRC_HEADERS)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -312,12 +312,17 @@ static NSString *const timedMetadata = @"timedMetadata";
|
||||
bool isAsset = [RCTConvert BOOL:[source objectForKey:@"isAsset"]];
|
||||
NSString *uri = [source objectForKey:@"uri"];
|
||||
NSString *type = [source objectForKey:@"type"];
|
||||
|
||||
NSDictionary *headers = [source objectForKey:@"requestHeaders"];
|
||||
|
||||
NSURL *url = (isNetwork || isAsset) ?
|
||||
[NSURL URLWithString:uri] :
|
||||
[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:uri ofType:type]];
|
||||
|
||||
if (isNetwork) {
|
||||
if ([headers count] > 0) {
|
||||
AVURLAsset* asset = [AVURLAsset URLAssetWithURL:url options:@{@"AVURLAssetHTTPHeaderFieldsKey": headers}];
|
||||
return [AVPlayerItem playerItemWithAsset:asset];
|
||||
}
|
||||
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
|
||||
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:@{AVURLAssetHTTPCookiesKey : cookies}];
|
||||
return [AVPlayerItem playerItemWithAsset:asset];
|
||||
|
Loading…
Reference in New Issue
Block a user