Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(android): implement asset folder playback #3733

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 19 additions & 25 deletions android/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.brentvatne.exoplayer;

import android.net.Uri;

import androidx.annotation.NonNull;
import androidx.media3.common.util.Util;
import androidx.media3.datasource.AssetDataSource;
import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DataSpec;
import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.datasource.HttpDataSource;
import androidx.media3.datasource.okhttp.OkHttpDataSource;
import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter;

import com.brentvatne.common.toolbox.DebugLog;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.CookieJarContainer;
import com.facebook.react.modules.network.ForwardingCookieHandler;
Expand All @@ -23,7 +29,6 @@ public class DataSourceUtil {
private DataSourceUtil() {
}

private static DataSource.Factory rawDataSourceFactory = null;
private static DataSource.Factory defaultDataSourceFactory = null;
private static HttpDataSource.Factory defaultHttpDataSourceFactory = null;
private static String userAgent = null;
Expand All @@ -39,44 +44,20 @@ public static String getUserAgent(ReactContext context) {
return userAgent;
}

public static DataSource.Factory getRawDataSourceFactory(ReactContext context) {
if (rawDataSourceFactory == null) {
rawDataSourceFactory = buildRawDataSourceFactory(context);
}
return rawDataSourceFactory;
}

public static void setRawDataSourceFactory(DataSource.Factory factory) {
DataSourceUtil.rawDataSourceFactory = factory;
}


public static DataSource.Factory getDefaultDataSourceFactory(ReactContext context, DefaultBandwidthMeter bandwidthMeter, Map<String, String> requestHeaders) {
if (defaultDataSourceFactory == null || (requestHeaders != null && !requestHeaders.isEmpty())) {
defaultDataSourceFactory = buildDataSourceFactory(context, bandwidthMeter, requestHeaders);
}
return defaultDataSourceFactory;
}

public static void setDefaultDataSourceFactory(DataSource.Factory factory) {
DataSourceUtil.defaultDataSourceFactory = factory;
}

public static HttpDataSource.Factory getDefaultHttpDataSourceFactory(ReactContext context, DefaultBandwidthMeter bandwidthMeter, Map<String, String> requestHeaders) {
if (defaultHttpDataSourceFactory == null || (requestHeaders != null && !requestHeaders.isEmpty())) {
defaultHttpDataSourceFactory = buildHttpDataSourceFactory(context, bandwidthMeter, requestHeaders);
}
return defaultHttpDataSourceFactory;
}

public static void setDefaultHttpDataSourceFactory(HttpDataSource.Factory factory) {
DataSourceUtil.defaultHttpDataSourceFactory = factory;
}

private static DataSource.Factory buildRawDataSourceFactory(ReactContext context) {
return new RawResourceDataSourceFactory(context.getApplicationContext());
}

private static DataSource.Factory buildDataSourceFactory(ReactContext context, DefaultBandwidthMeter bandwidthMeter, Map<String, String> requestHeaders) {
return new DefaultDataSource.Factory(context, buildHttpDataSourceFactory(context, bandwidthMeter, requestHeaders));
}
Expand All @@ -100,4 +81,17 @@ private static HttpDataSource.Factory buildHttpDataSourceFactory(ReactContext co

return okHttpDataSourceFactory;
}

public static DataSource.Factory buildAssetDataSourceFactory(ReactContext context, Uri srcUri) throws AssetDataSource.AssetDataSourceException {
DataSpec dataSpec = new DataSpec(srcUri);
final AssetDataSource rawResourceDataSource = new AssetDataSource(context);
rawResourceDataSource.open(dataSpec);
return new DataSource.Factory() {
@NonNull
@Override
public DataSource createDataSource() {
return rawResourceDataSource;
}
};
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import static androidx.media3.common.C.CONTENT_TYPE_SS;
import static androidx.media3.common.C.TIME_END_OF_SOURCE;

import static com.brentvatne.exoplayer.DataSourceUtil.buildAssetDataSourceFactory;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
Expand Down Expand Up @@ -841,7 +843,14 @@ private MediaSource buildMediaSource(Uri uri, String overrideExtension, DrmSessi
);
break;
case CONTENT_TYPE_OTHER:
if (uri.toString().startsWith("file://") ||
if ("asset".equals(srcUri.getScheme())) {
try {
DataSource.Factory assetDataSourceFactory = buildAssetDataSourceFactory(themedReactContext, srcUri);
mediaSourceFactory = new ProgressiveMediaSource.Factory(assetDataSourceFactory);
} catch (Exception e) {
throw new IllegalStateException("cannot open input file" + srcUri);
}
} else if ("file".equals(srcUri.getScheme()) ||
cacheDataSourceFactory == null) {
mediaSourceFactory = new ProgressiveMediaSource.Factory(
mediaDataSourceFactory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import com.facebook.react.uimanager.common.UIManagerType
import kotlin.math.roundToInt

class VideoManagerModule(reactContext: ReactApplicationContext?) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String {
return REACT_CLASS
}
override fun getName(): String = REACT_CLASS

private fun performOnPlayerView(reactTag: Int, callback: (ReactExoplayerView?) -> Unit) {
UiThreadUtil.runOnUiThread {
Expand Down
12 changes: 12 additions & 0 deletions docs/pages/component/props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,18 @@ source={{ uri: 'file:///sdcard/Movies/sintel.mp4' }}

Note: Your app will need to request permission to read external storage if you're accessing a file outside your app.

##### File from asset folder (asset://)

<PlatformsList types={['Android']} />

Allows to play a video file from the asset folder from the application

Example:

```javascript
source={{ uri: 'asset:///sintel.mp4' }}
```

##### iPod Library (ipod-library://)

<PlatformsList types={['iOS']} />
Expand Down
Binary file not shown.
4 changes: 4 additions & 0 deletions examples/basic/src/VideoPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ class VideoPlayer extends Component {
description: 'Another live sample',
uri: 'https://live.forstreet.cl/live/livestream.m3u8',
},
{
description: 'asset file',
uri: 'asset:///broadchurch.mp4',
},
{
description: '(dash) sintel subtitles',
uri: 'https://bitmovin-a.akamaihd.net/content/sintel/sintel.mpd',
Expand Down
Loading