I’m trying to implement srt subtitles into my videos but I don’t understand how make them work in the new media3
public class VideoPlayerFragment extends Fragment implements View.OnClickListener {
private PlayerView playerView;
private ExoPlayer exoPlayer;
private MediaFile mediaFile;
@SuppressLint("MissingInflatedId")
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (TextUtils.isEmpty(PrefUtils.PREF))
PrefUtils.with(MainActivity.getInstance()).setSharedPref(getResources().getString(R.string.app_name));
ActivityUtils.with(requireContext()).enableFullscreen(requireActivity().getWindow());
View view = inflater.inflate(R.layout.fragment_video_player, container, false);
playerView = view.findViewById(R.id.videoPlayer);
progressLayout = view.findViewById(R.id.progressLayout);
playerVideoTitle = view.findViewById(R.id.playerVideoTitle);
playerBack = view.findViewById(R.id.playerBack);
unlockLock = view.findViewById(R.id.unlockLock);
rewind = view.findViewById(R.id.rewind);
previous = view.findViewById(R.id.previous);
pausePlay = view.findViewById(R.id.pausePlay);
next = view.findViewById(R.id.next);
forward = view.findViewById(R.id.forward);
rotateDevice = view.findViewById(R.id.rotateDevice);
pipMode = view.findViewById(R.id.pipMode);
playVideo();
subtitles.setOnClickListener(v -> {
useSubtitles = !useSubtitles;
videoData.saveVideoData(mediaFile.getPath(), exoPlayer.getContentPosition());
resetPlayer();
playVideo();
subtitles.setImageResource(useSubtitles ? R.drawable.ic_subtitles_on : R.drawable.ic_subtitles_off);
});
return view;
}
@OptIn(markerClass = UnstableApi.class)
private void playVideo() {
if (mediaFile == null) {
if (intentVideoUri == null) {
mediaFile = videoPlayerViewModel.getMediaFileList().get(position);
} else {
mediaFile = new MediaFile().getMediaFromUri(requireContext(), intentVideoUri);
}
}
databaseVideoData = videoData.getVideoData(mediaFile.getId());
String path = mediaFile.getPath();
playerVideoTitle.setText(mediaFile.getDisplayName());
Uri uri = Uri.parse(path);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(requireContext());
DefaultTrackSelector.Parameters trackSelectorParameters = trackSelector.buildUponParameters().clearOverridesOfType(C.TRACK_TYPE_TEXT).setPreferredTextLanguage(
"en").build();
trackSelector.setParameters(trackSelectorParameters);
exoPlayer = new ExoPlayer.Builder(requireContext()).setTrackSelector(trackSelector).setLoadControl(new DefaultLoadControl()).build();
DefaultDataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(requireContext(), DataSchemeDataSource::new);
exoPlayer.setTrackSelectionParameters(trackSelectorParameters);
playerView.setPlayer(exoPlayer);
// Add subtitle configuration if subtitles are enabled
// if (useSubtitles) {
File file = new File(mediaFile.getPath());
String name = file.getName();
int pos = name.lastIndexOf(".");
if (pos > 0) {
name = name.substring(0, pos);
}
Uri subtitleUri = Uri.fromFile(new File(file.getParent() + "/" + name + ".srt"));
MediaItem.SubtitleConfiguration subtitleConfiguration =
new MediaItem.SubtitleConfiguration.Builder(subtitleUri)
.setMimeType(MimeTypes.APPLICATION_SUBRIP)
.setLanguage("en")
.setSelectionFlags(C.SELECTION_FLAG_DEFAULT)
.build();
MediaItem mediaItem = new MediaItem.Builder().setUri(uri).setSubtitleConfigurations(ImmutableList.of(subtitleConfiguration)).build();
// }
MediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem);
playerView.setKeepScreenOn(true);
exoPlayer.setMediaSource(mediaSource);
exoPlayer.prepare();
exoPlayer.seekTo(exoPlayer.getCurrentMediaItemIndex(), databaseVideoData == null ? C.TIME_UNSET : databaseVideoData.getVideoPosition() <= 0 ? C.TIME_UNSET : databaseVideoData.getVideoPosition());
exoPlayer.play();
exoPlayer.addListener(new Player.Listener() {
@Override
public void onPlaybackStateChanged(int playbackState) {
if (playbackState == ExoPlayer.STATE_ENDED) {
exoPlayer.pause();
pausePlay.setImageResource(R.drawable.ic_play);
exoPlayer.seekTo(exoPlayer.getCurrentMediaItemIndex(), 0);
videoData.saveVideoData(mediaFile.getId(), exoPlayer.getContentPosition());
if (PrefUtils.with(requireContext()).getBoolean("autoplayNext", false)) {
nextVideo();
}
}
}
});
mediaSession = new MediaSession.Builder(requireContext(), exoPlayer).setCallback(new MediaSession.Callback() {
@Override
public boolean onMediaButtonEvent(@NonNull MediaSession session, @NonNull MediaSession.ControllerInfo controllerInfo, @NonNull Intent intent) {
KeyEvent keyEvent = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (keyEvent != null && keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
int keyCode = keyEvent.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_PAUSE:
case KeyEvent.KEYCODE_MEDIA_PLAY:
playPauseVideo();
return true;
case KeyEvent.KEYCODE_MEDIA_NEXT:
nextVideo();
return true;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
previousVideo();
return true;
}
}
return true;
}
}).build();
}
private PendingIntent getMainActivityPendingIntent() {
Intent intent = new Intent(requireContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
return PendingIntent.getActivity(requireContext(), 0, intent, PendingIntent.FLAG_IMMUTABLE);
}
@Override
public void onPause() {
super.onPause();
if (!PrefUtils.with(MainActivity.getInstance()).getBoolean("backgroundPlay", false)) {
exoPlayer.pause();
pausePlay.setImageResource(R.drawable.ic_play);
}
}
@Override
public void onResume() {
super.onResume();
if (TextUtils.isEmpty(PrefUtils.PREF))
PrefUtils.with(MainActivity.getInstance()).setSharedPref(getResources().getString(R.string.app_name));
if (exoPlayer.isPlaying()) {
pausePlay.setImageResource(R.drawable.ic_play);
} else {
if (!PrefUtils.with(MainActivity.getInstance()).getBoolean("backgroundPlay", false)) {
pausePlay.setImageResource(R.drawable.ic_pause);
}
}
}
@Override
public void onDestroy() {
resetPlayer();
super.onDestroy();
}
private void resetPlayer() {
try {
if (exoPlayer != null) {
// MainActivity.getInstance().notificationManager.cancel(MainActivity.NOTIFICATION_ID);
exoPlayer.pause();
videoData.saveVideoData(mediaFile.getId(), exoPlayer.getContentPosition());
exoPlayer.stop();
exoPlayer.release();
mediaSession.release();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
and I use
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragments.VideoPlayerFragment">
<androidx.media3.ui.PlayerView
android:id="@+id/videoPlayer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="false"
android:background="@color/black"
app:controller_layout_id="@layout/custom_playback_view"
app:hide_on_touch="true"
app:resize_mode="fit"
app:show_timeout="3000"
app:shutter_background_color="@color/app_background"
app:surface_type="surface_view" />
</FrameLayout>
Can someone help me? I have tried some things online but they all use exoplayer2.
If you want help me with code improvement I’m open to suggestions.
Also, app:show_timeout="3000"
hides the timebar after 3s and controls after 6 (3s the timebar and 3s for the layout) how can I change it?
P.s. I know fragment is bad for video player, I’ll change it soon