Open sharmadev419 opened 7 years ago
@sharmadev419 Can you give me more information on how can you reproduce this? And which version of Android you use? Thanks.
I also facing the same issue. Its a random exception thrown somewhere. I am not even able to trace the problem when it comes. My log is :
05-11 11:40:10.843 11747-11747/com.hiddenug E/AndroidRuntime: FATAL EXCEPTION: main Process: com.hiddenug, PID: 11747 java.lang.IllegalStateException: Player is playing while it is not in managed state: ViewHolder{6ad59c3 position=8 id=-1, oldPos=-1, pLpos:-1} at im.ene.toro.widget.Container.onChildDetachedFromWindow(Container.java:205) at android.support.v7.widget.RecyclerView.dispatchChildDetached(RecyclerView.java:7145) at android.support.v7.widget.RecyclerView$5.removeViewAt(RecyclerView.java:794) at android.support.v7.widget.ChildHelper.removeViewAt(ChildHelper.java:168) at android.support.v7.widget.RecyclerView$LayoutManager.removeViewAt(RecyclerView.java:8260) at android.support.v7.widget.RecyclerView$LayoutManager.removeAndRecycleViewAt(RecyclerView.java:8532) at android.support.v7.widget.LinearLayoutManager.recycleChildren(LinearLayoutManager.java:1371) at android.support.v7.widget.LinearLayoutManager.recycleViewsFromStart(LinearLayoutManager.java:1417) at android.support.v7.widget.LinearLayoutManager.recycleByLayoutState(LinearLayoutManager.java:1486) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1510) at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1333) at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1077) at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1815) at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:3076) at android.view.View.dispatchTouchEvent(View.java:9297) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2549) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2240) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403) at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737) at android.app.Activity.dispatchTouchEvent(Activity.java:2769) at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:68) at co
@Shakir4u I have updated the player and used ExoPlayerHelper instead of ToroPlayerHelper. I was using it with Exoplayer Please check if this is the same issue with your code.
it reproduces in android 7.1.1 samsung device. toro player implement in recycler view nested ways
Toro version 3.2.0 Exo player version 2.5.3
java.lang.IllegalStateException: Player is playing while it is not in managed state: ViewHolder{2340423 position=8 id=-1, oldPos=-1, pLpos:-1} at im.ene.toro.widget.Container.onChildDetachedFromWindow(Container.java:182) at android.support.v7.widget.RecyclerView.dispatchChildDetached(RecyclerView.java:7145) at android.support.v7.widget.RecyclerView$5.removeViewAt(RecyclerView.java:794) at android.support.v7.widget.ChildHelper.removeViewAt(ChildHelper.java:168) at android.support.v7.widget.RecyclerView$LayoutManager.removeViewAt(RecyclerView.java:8260) at android.support.v7.widget.RecyclerView$LayoutManager.removeAndRecycleViewAt(RecyclerView.java:8532) at android.support.v7.widget.LinearLayoutManager.recycleChildren(LinearLayoutManager.java:1371) at android.support.v7.widget.LinearLayoutManager.recycleViewsFromStart(LinearLayoutManager.java:1417) at android.support.v7.widget.LinearLayoutManager.recycleByLayoutState(LinearLayoutManager.java:1486) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1510) at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1333) at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1077) at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:4960) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:930) at android.view.Choreographer.doCallbacks(Choreographer.java:705) at android.view.Choreographer.doFrame(Choreographer.java:637) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:916) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154)
Application is crash because of this. #bug
@Shakir4u For me, it was also happening in some specific android device. I just updated the player at my end. After updating the player, not only this issue gets resolved but its performance has also increased. You can share your code with me or I will share mine. I think this is the only way to get it resolved.
@Anilugale can you share with me the code of your ViewHolder? Both the ViewHolder that is a nested RecyclerView, and the ViewHolder that is a Player.
There are some cases this issue were found but I could never reproduce them easily. If I can have some clue from your code it can be eliminated. Also, I guess 3.4.2 improve this a lot, though migration may be non-trivial, but please consider the latest version.
Dear all , I have added these dependencies version implementation 'im.ene.toro3:toro:3.4.1' implementation 'im.ene.toro3:toro-ext-exoplayer:3.4.1'
My ViewHolder is -
public class VideoViewHolder extends RecyclerView.ViewHolder implements ToroPlayer {
private final RowPopularVideoBinding binding;
@Nullable
View imageTobeSaved;
@Nullable
private Uri mediaUri;
VideoViewHolder(View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
// Create the player
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
binding.exoPlayer.setPlayer(player);
}
void bind(@NonNull RecyclerView.Adapter adapter, Uri item, List<Object> payloads) {
if (item != null) {
mediaUri = item;
}
}
void bind(Uri media) {
this.mediaUri = media;
}
@NonNull
@Override
public View getPlayerView() {
return binding.exoPlayer;
}
@NonNull
@Override
public PlaybackInfo getCurrentPlaybackInfo() {
return helper != null ? helper.getLatestPlaybackInfo() : new PlaybackInfo();
}
@Override
public void initialize(@NonNull Container container, @Nullable PlaybackInfo playbackInfo) {
if (helper == null) {
assert mediaUri != null;
helper = new SimpleExoPlayerViewHelper(container, this, mediaUri);
muteListener.isMute(player, 0, helper);
}
helper.initialize(playbackInfo);
}
@Override
public void release() {
if (helper != null) {
helper.release();
helper = null;
}
}
@Override
public void play() {
if (helper != null) try {
helper.play();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void pause() {
if (helper != null) helper.pause();
}
@Override
public boolean isPlaying() {
boolean isPlaying = false;
try {
isPlaying = helper != null && helper.isPlaying();
} catch (Exception e) {
e.printStackTrace();
}
return isPlaying;
}
@Override
public boolean wantsToPlay() {
isVideoShow = ToroUtil.visibleAreaOffset(this, itemView.getParent()) >= 0.50;
if (isVideoShow) {
if (HomeFragment.isMute) {
binding.exoMute.setImageResource(R.mipmap.mute_music);
} else {
binding.exoMute.setImageResource(R.mipmap.unmute_music);
}
} else {
if (binding.exoPlayer.getPlayer() != null) {
binding.exoPlayer.getPlayer().setPlayWhenReady(false);
}
}
return ToroUtil.visibleAreaOffset(this, itemView.getParent()) >= 0.85;
}
@Override
public int getPlayerOrder() {
return getAdapterPosition();
}
@Override
public void onSettled(Container container) {
}
}
I have used a toro player on a fragment inside viewPager. I actually throws exception randomly on every devices.
@Shakir4u You have setup both the helper and exoplayer ... what does it mean? And in term of user interaction, at what timing your app throws exception?
sorry dear , Its a mistake of naming variable. exoPlayer is SimpleExoPlayerView which is a view from com.google.android.exoplayer2.ui.SimpleExoPlayerView and on this view I am setting a player as
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
binding.exoPlayer.setPlayer(player);
Helper is object of SimpleExoPlayerViewHelper which is being used for managing state of player.
if I am not using right approch , please suggest the right one.
@Shakir4u Well, when you create a SimpleExoPlayerViewHelper, you give it the ToroPlayer and there it will request for the same SimpleExoPlayerView instance. So all the setup is handled by SimpleExoPlayerViewHelper already. Do don't need the part using ExoPlayerFactory.newSimpleInstance above.
@Shakir4u And I wonder which kind of user interaction (swipe the ViewPager? scroll the RecyclerView?) could reproduce the issue?
Hello , It is random crash ,When i scroll the recycler view.
Let me take a look ...
java.lang.IllegalStateException: Player is playing while it is not in managed state: ViewHolder{2b10cca position=11 id=-1, oldPos=-1, pLpos:-1 not recyclable(1)}
faced same issue @sharmadev419 @Shakir4u
@harshbhavsar011 Could you post your adapter class here.
I think it occurs during my NestedPlayerViewholder
ready to play then immediately changed to another viewholder
that time this occurs. (Happends during onDetached
viewholder
)
`static class Adapter extends RecyclerView.Adapter<BaseViewHolder> {
static final int TYPE_VIDEO = 10;
static final int TYPE_TEXT = 20;
static final int TYPE_IMAGE = 30;
private LayoutInflater inflater;
final PostList mediaList;
Context mContext;
private int position;
Adapter(Context context, PostList mediaList) {
this.mediaList = mediaList;
this.mContext = context;
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (inflater == null || inflater.getContext() != parent.getContext()) {
inflater = LayoutInflater.from(parent.getContext());
}
final View view;
final BaseViewHolder viewHolder;
switch (viewType) {
case TYPE_VIDEO:
view = inflater.inflate(NestedPlayerViewHolder.LAYOUT_RES, parent, false);
viewHolder = new NestedPlayerViewHolder(view);
viewHolder.setIsRecyclable(true);
break;
case TYPE_IMAGE:
view = inflater.inflate(ImageViewHolder.LAYOUT_RES, parent, false);
viewHolder = new ImageViewHolder(view);
break;
default:
view = inflater.inflate(HorizontalTextViewHolder.LAYOUT_RES, parent, false);
viewHolder = new HorizontalTextViewHolder(view);
break;
}
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder baseViewHolder, int position) {
this.position = position;
if (CommonUtils.isVideoFile(mediaList.getMedia_content().get(position).getMedia_url())) {
int required_height = 1, required_width = 1;
String videoWidth;
String videoHeight = null;
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) baseViewHolder.itemView.getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int device_height = displayMetrics.heightPixels;
int device_width = displayMetrics.widthPixels;
if (mediaList.getMedia_height() == null || mediaList.getMedia_height() == null) {
videoWidth = String.valueOf(device_width);
videoHeight = "800";
} else {
videoWidth = mediaList.getMedia_width();
videoHeight = mediaList.getMedia_height();
}
if (Integer.parseInt(videoWidth) == 0 && Integer.parseInt(videoHeight) == 0) {
videoWidth = String.valueOf(device_width);
videoHeight = "800";
}
required_width = device_width;
required_height = ((Integer.parseInt(videoHeight) * device_width) / Integer.parseInt(videoWidth));
ViewGroup.LayoutParams params = baseViewHolder.itemView.getLayoutParams();
params.width = required_width;
params.height = required_height;
} else {
// scaleImage(baseViewHolder.itemView);
}
baseViewHolder.bind(position, mediaList.getMedia_content().get(position));
}
@Override
public int getItemViewType(int position) {
if (CommonUtils.isVideoFile(mediaList.getMedia_content().get(position).getMedia_url())) {
return TYPE_VIDEO;
} else if (CommonUtils.isImageFile(mediaList.getMedia_content().get(position).getMedia_url())) {
return TYPE_IMAGE;
} else {
return TYPE_TEXT;
}
}
@Override
public int getItemCount() {
return mediaList.getMedia_content().size();
}
}
static class StateManager implements CacheManager {
final PostList mediaList;
StateManager(PostList mediaList) {
this.mediaList = mediaList;
}
@NonNull
@Override
public Object getKeyForOrder(int order) {
if (this.mediaList.getMedia_content().size() > 0 && order <= this.mediaList.getMedia_content().size())
return this.mediaList.getMedia_content().get(order);
else
return null;
}
@Nullable
@Override
public Integer getOrderForKey(@NonNull Object key) {
return key instanceof Content.Media ? this.mediaList.getMedia_content().indexOf(key) : null;
}
}`
` @SuppressWarnings("WeakerAccess") // public class NestedPlayerViewHolder extends BaseViewHolder implements ToroPlayer {
static final int LAYOUT_RES = R.layout.view_holder_exoplayer_nested;
ExoPlayerViewHelper helper;
Uri mediaUri;
@BindView(R.id.player)
PlayerView playerView;
@BindView(R.id.progress_bar)
ProgressBar progress_bar;
public NestedPlayerViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@Override
void bind(int position, Object object) {
try {
PostList.MediaContentBean media = (PostList.MediaContentBean) object;
this.mediaUri = (Uri.parse(String.valueOf(media.getMedia_url())));
} catch (Exception e) {
e.printStackTrace();
}
}
@NonNull
@Override
public View getPlayerView() {
return playerView;
}
@NonNull
@Override
public PlaybackInfo getCurrentPlaybackInfo() {
return helper != null ? helper.getLatestPlaybackInfo() : new PlaybackInfo();
}
private ToroPlayer.EventListener toroPlayerEventListener = new EventListener() {
@Override
public void onBuffering() {
// do something
progress_bar.setVisibility(View.VISIBLE);
}
@Override
public void onPlaying() {
// do something
progress_bar.setVisibility(View.GONE);
}
@Override
public void onPaused() {
// do something
}
@Override
public void onCompleted() {
// do something
progress_bar.setVisibility(View.GONE);
}
};
@Override
public void initialize(@NonNull Container container, @NonNull PlaybackInfo playbackInfo) {
try {
if (helper == null) {
helper = new ExoPlayerViewHelper(this, mediaUri);
}
helper.initialize(container, playbackInfo);
playerView.getPlayer().setRepeatMode(1);
helper.addPlayerEventListener(toroPlayerEventListener);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void play() {
try {
if (helper != null && !helper.isPlaying()) {
helper.play();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void pause() {
try {
if (helper != null && helper.isPlaying()) {
helper.pause();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean isPlaying() {
try {
return helper != null && helper.isPlaying();
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public void release() {
try {
if (helper != null) {
helper.addPlayerEventListener(null);
helper.release();
helper = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean wantsToPlay() {
try {
return ToroUtil.visibleAreaOffset(this, itemView.getParent()) >= 0.50;
} catch (Exception e) {
e.printStackTrace();
release();
return false;
}
}
@Override
public int getPlayerOrder() {
return getAdapterPosition();
}
@Override
public String toString() {
return "ExoPlayer{" + hashCode() + " " + getAdapterPosition() + "}";
}
}`
@harshbhavsar011 Is your holder global to the adapter or its local to the viewholder?
Are you talking about NestedPlayerView
Holder and ImageViewHolder
? Right ?
Its Local viewholder i Can not access to MediaViewHolder
Pardon. I was asking about helper.
I am using ExoPlayerViewHelper as per library . Should i change into that?
class ViewHolderVideo extends RecyclerView.ViewHolder implements ToroPlayer, ExoPlayer.EventListener {
private ExoPlayerHelper helper;
private SimpleExoPlayerView dialogPlayerView;
ViewHolderVideo(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@NonNull
@Override
public View getDialogPlayerView() {
return videoView;
}
@NonNull
@Override
public PlaybackInfo getCurrentPlaybackInfo() {
return helper != null ? helper.getPlaybackInfo() : new PlaybackInfo();
}
@Override
public void initialize(@NonNull Container container, @Nullable PlaybackInfo playbackInfo) {
if (helper == null) {
if (getAdapterPosition() > -1) {
if (helper == null) {
isPlayAgain = true;
helper = new ExoPlayerHelper(videoView, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON, false);
try {
MediaSourceBuilder sourceBuilder;
if (arrayListCommonOne.get(getAdapterPosition()).getType() == 2) {
sourceBuilder = new MediaSourceBuilder(contextUri.parse(arrayListCommonOne.get(getAdapterPosition()).getListVideos().get(0).getUserWorkoutVideo()));
} else {
sourceBuilder = new MediaSourceBuilder(contextUri.parse(arrayListCommonOne.get(getAdapterPosition()).getListVideos().get(0).getUserWorkoutVideo()));
}
helper.prepare(sourceBuilder);
helper.setVolume(1f);
} catch (ParserException e) {
e.printStackTrace();
}
}
}
if (playbackInfo != null && helper != null) {
helper.setPlaybackInfo(playbackInfo);
}
if (helper != null) {
helper.addEventListener(this);
}
}
}
@Override
public void play() {
if (helper != null) {
helper.play();
}
}
@Override
public void pause() {
if (helper != null) helper.pause();
}
@Override
public boolean isPlaying() {
return helper != null && helper.isPlaying();
}
@Override
public void release() {
if (helper != null) {
ivThumbNail.setVisibility(View.VISIBLE);
try {
helper.release();
} catch (Exception e) {
e.printStackTrace();
}
helper = null;
}
}
@Override
public boolean wantsToPlay() {
return ToroUtil.visibleAreaOffset(this, itemView.getParent()) >= 0.50;
}
@Override
public int getPlayerOrder() {
return getAdapterPosition();
}
@Override
public void onContainerScrollStateChange(Container container, int newState) {
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int i) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
@Override
public void onPositionDiscontinuity() {
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
}
This is my code. See if there is anything you are missing.
Please provide ExoplayerHelper Class.
/*
package im.ene.toro.exoplayer;
import android.content.Context; import android.os.Handler; import android.os.Looper; import android.support.annotation.FloatRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.widget.Toast; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.DefaultRenderersFactory.ExtensionRendererMode; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; import com.google.android.exoplayer2.drm.FrameworkMediaDrm; import com.google.android.exoplayer2.drm.HttpMediaDrmCallback; import com.google.android.exoplayer2.drm.UnsupportedDrmException; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; import com.google.android.exoplayer2.source.BehindLiveWindowException; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.ui.SimpleExoPlayerView; import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; import com.google.android.exoplayer2.util.Util; import im.ene.toro.R; import im.ene.toro.ToroUtil; import im.ene.toro.media.DrmMedia; import im.ene.toro.media.PlaybackInfo; import java.net.CookieManager; import java.net.CookiePolicy; import java.util.ArrayList; import java.util.UUID;
import static com.google.android.exoplayer2.drm.UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME;
/**
@SuppressWarnings({ "WeakerAccess", "unused" }) // public final class ExoPlayerHelper {
private static final String TAG = "ToroLib:ExoPlayer";
// instance is unchanged, but inner fields are changeable. @NonNull final PlaybackInfo playbackInfo = new PlaybackInfo();
final Context context; // Application context, will obtain from playerView context. @NonNull final SimpleExoPlayerView playerView; @ExtensionRendererMode final int extensionMode; final Handler mainHandler;
SimpleExoPlayer player; ComponentListener componentListener; DefaultTrackSelector trackSelector;
MediaSourceBuilder mediaSourceBuilder; BandwidthMeter bandwidthMeter;
boolean shouldAutoPlay; boolean needRetrySource;
ArrayList
public ExoPlayerHelper(@NonNull SimpleExoPlayerView playerView, @ExtensionRendererMode int extensionMode, boolean playWhenReady) { this.playerView = playerView; this.context = playerView.getContext().getApplicationContext(); this.extensionMode = extensionMode; this.shouldAutoPlay = playWhenReady; this.mainHandler = new Handler(Looper.myLooper()); }
public ExoPlayerHelper(@NonNull SimpleExoPlayerView playerView, @ExtensionRendererMode int extensionMode) { this(playerView, extensionMode, false); }
public ExoPlayerHelper(@NonNull SimpleExoPlayerView playerView) { this(playerView, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF); }
public void setPlaybackInfo(@Nullable PlaybackInfo playbackInfo) { if (playbackInfo != null) { this.playbackInfo.setResumeWindow(playbackInfo.getResumeWindow()); this.playbackInfo.setResumePosition(playbackInfo.getResumePosition()); }
if (player != null) {
boolean haveResumePosition = this.playbackInfo.getResumeWindow() != C.INDEX_UNSET;
if (haveResumePosition) {
player.seekTo(this.playbackInfo.getResumeWindow(), this.playbackInfo.getResumePosition());
}
}
}
public void prepare(@NonNull MediaSourceBuilder mediaSourceBuilder) throws ParserException { prepare(mediaSourceBuilder, new DefaultBandwidthMeter(mainHandler, null)); }
public void prepare(@NonNull MediaSourceBuilder mediaSourceBuilder,
@Nullable BandwidthMeter bandwidthMeter) throws ParserException {
//noinspection ConstantConditions
if (mediaSourceBuilder == null) {
throw new IllegalArgumentException("MediaSourceBuilder must not be null.");
}
this.mediaSourceBuilder = mediaSourceBuilder;
DrmSessionManager
UUID drmSchemeUuid = getDrmUuid(drmMedia.getType());
if (drmSchemeUuid != null) {
String drmLicenseUrl = drmMedia.getLicenseUrl();
String[] keyRequestPropertiesArray = drmMedia.getKeyRequestPropertiesArray();
try {
drmSessionManager = buildDrmSessionManager(drmSchemeUuid, drmLicenseUrl, //
keyRequestPropertiesArray, mainHandler);
} catch (UnsupportedDrmException e) {
int errorStringId = Util.SDK_INT < 18 ? R.string.error_drm_not_supported
: (e.reason == REASON_UNSUPPORTED_SCHEME ? //
R.string.error_drm_unsupported_scheme : R.string.error_drm_unknown);
Toast.makeText(context, errorStringId, Toast.LENGTH_SHORT).show();
return;
}
}
}
prepare(mediaSourceBuilder.build(bandwidthMeter), bandwidthMeter, drmSessionManager);
}
@SuppressWarnings("ConstantConditions") //
void prepare(@NonNull MediaSource mediaSource, BandwidthMeter bandwidthMeter,
DrmSessionManager
this.bandwidthMeter = bandwidthMeter;
if (componentListener == null) {
componentListener = new ComponentListener();
}
this.player = playerView.getPlayer();
boolean needNewPlayer = player == null;
if (needNewPlayer) {
TrackSelection.Factory adaptiveTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
RenderersFactory renderersFactory =
new DefaultRenderersFactory(context, drmSessionManager, extensionMode);
player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector);
player.addListener(componentListener);
player.setPlayWhenReady(shouldAutoPlay);
needRetrySource = true;
}
if (needNewPlayer || needRetrySource) {
playerView.setPlayer(player);
boolean haveResumePosition = playbackInfo.getResumeWindow() != C.INDEX_UNSET;
if (haveResumePosition) {
player.seekTo(playbackInfo.getResumeWindow(), playbackInfo.getResumePosition());
}
player.prepare(mediaSource, !haveResumePosition, false);
needRetrySource = false;
}
}
public void release() { mainHandler.removeCallbacksAndMessages(null);
if (player != null) {
shouldAutoPlay = player.getPlayWhenReady();
updateResumePosition();
player.removeListener(componentListener);
player.release();
playerView.setPlayer(null);
player = null;
}
trackSelector = null;
mediaSourceBuilder = null;
bandwidthMeter = null;
componentListener = null;
}
@NonNull public PlaybackInfo getPlaybackInfo() { updateResumePosition(); // return a copy only. return new PlaybackInfo(playbackInfo.getResumeWindow(), playbackInfo.getResumePosition()); }
public void addEventListener(@NonNull ExoPlayer.EventListener eventListener) { if (this.eventListeners == null) { this.eventListeners = new ArrayList<>(); }
//noinspection ConstantConditions
if (eventListener != null) this.eventListeners.add(eventListener);
}
public void removeEventListener(ExoPlayer.EventListener eventListener) { if (this.eventListeners != null && eventListener != null) { this.eventListeners.remove(eventListener); } }
public void play() { if (player != null) player.setPlayWhenReady(true);
}
public void pause() { if (player != null) player.setPlayWhenReady(false); }
public boolean isPlaying() { return this.player != null && this.player.getPlayWhenReady(); }
public void setVolume(@FloatRange(from = 0.0, to = 1.0) float volume) { if (player != null) player.setVolume(volume); }
public float getVolume() { return player != null ? player.getVolume() : 1 / unity gain, default value /; }
void updateResumePosition() { if (player == null || player.getPlaybackState() == 1) return; playbackInfo.setResumeWindow(player.getCurrentWindowIndex()); playbackInfo.setResumePosition( player.isCurrentWindowSeekable() ? Math.max(0, player.getCurrentPosition()) : C.TIME_UNSET); }
void clearResumePosition() { playbackInfo.reset(); }
private class ComponentListener implements ExoPlayer.EventListener {
ComponentListener() {
}
@Override public void onTimelineChanged(Timeline timeline, Object manifest) {
int count;
if (eventListeners != null && (count = eventListeners.size()) > 0) {
for (int i = count - 1; i >= 0; i--) {
eventListeners.get(i).onTimelineChanged(timeline, manifest);
}
}
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
MappedTrackInfo mappedTrackInfo =
trackSelector != null ? trackSelector.getCurrentMappedTrackInfo() : null;
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_VIDEO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
Toast.makeText(context, R.string.error_unsupported_video, Toast.LENGTH_SHORT).show();
}
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_AUDIO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
Toast.makeText(context, R.string.error_unsupported_audio, Toast.LENGTH_SHORT).show();
}
}
int count;
if (eventListeners != null && (count = eventListeners.size()) > 0) {
for (int i = count - 1; i >= 0; i--) {
eventListeners.get(i).onTracksChanged(trackGroups, trackSelections);
}
}
}
@Override public void onLoadingChanged(boolean isLoading) {
int count;
if (eventListeners != null && (count = eventListeners.size()) > 0) {
for (int i = count - 1; i >= 0; i--) {
eventListeners.get(i).onLoadingChanged(isLoading);
}
}
}
@Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
boolean screenOn = isPlaying() && (playbackState >= 2 || playbackState <= 3);
playerView.setKeepScreenOn(screenOn);
if (playbackState == ExoPlayer.STATE_ENDED) {
if (player != null) {
player.setPlayWhenReady(false);
player.seekTo(0); // reset playback position for current window
}
}
int count;
if (eventListeners != null && (count = eventListeners.size()) > 0) {
for (int i = count - 1; i >= 0; i--) {
eventListeners.get(i).onPlayerStateChanged(playWhenReady, playbackState);
}
}
}
@Override public void onPlayerError(ExoPlaybackException e) {
String errorString = null;
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
Exception cause = e.getRendererException();
if (cause instanceof MediaCodecRenderer.DecoderInitializationException) {
// Special case for decoder initialization failures.
MediaCodecRenderer.DecoderInitializationException decoderInitializationException =
(MediaCodecRenderer.DecoderInitializationException) cause;
if (decoderInitializationException.decoderName == null) {
if (decoderInitializationException.getCause() instanceof MediaCodecUtil.DecoderQueryException) {
errorString = context.getString(R.string.error_querying_decoders);
} else if (decoderInitializationException.secureDecoderRequired) {
errorString = context.getString(R.string.error_no_secure_decoder,
decoderInitializationException.mimeType);
} else {
errorString = context.getString(R.string.error_no_decoder,
decoderInitializationException.mimeType);
}
} else {
errorString = context.getString(R.string.error_instantiating_decoder,
decoderInitializationException.decoderName);
}
}
}
if (errorString != null) {
Toast.makeText(context, errorString, Toast.LENGTH_SHORT).show();
}
needRetrySource = true;
if (isBehindLiveWindow(e)) {
clearResumePosition();
try {
prepare(ExoPlayerHelper.this.mediaSourceBuilder, ExoPlayerHelper.this.bandwidthMeter);
} catch (ParserException e1) {
e1.printStackTrace();
}
} else {
updateResumePosition();
}
int count;
if (eventListeners != null && (count = eventListeners.size()) > 0) {
for (int i = count - 1; i >= 0; i--) {
eventListeners.get(i).onPlayerError(e);
}
}
}
@Override public void onPositionDiscontinuity() {
if (needRetrySource) {
// This will only occur if the user has performed a seek whilst in the error playerState. Update the
// resume position so that if the user then retries, playback will resume from the position to
// which they seek.
updateResumePosition();
}
int count;
if (eventListeners != null && (count = eventListeners.size()) > 0) {
for (int i = count - 1; i >= 0; i--) {
eventListeners.get(i).onPositionDiscontinuity();
}
}
}
@Override public void onPlaybackParametersChanged(PlaybackParameters parameters) {
int count;
if (eventListeners != null && (count = eventListeners.size()) > 0) {
for (int i = count - 1; i >= 0; i--) {
eventListeners.get(i).onPlaybackParametersChanged(parameters);
}
}
}
}
//// static methods
private static final CookieManager DEFAULT_COOKIE_MANAGER;
static { DEFAULT_COOKIE_MANAGER = new CookieManager(); DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); }
static boolean isBehindLiveWindow(ExoPlaybackException e) { if (e.type != ExoPlaybackException.TYPE_SOURCE) { return false; } Throwable cause = e.getSourceException(); while (cause != null) { if (cause instanceof BehindLiveWindowException) { return true; } cause = cause.getCause(); } return false; }
@Nullable DrmSessionManager
private static UUID getDrmUuid(String typeString) throws ParserException { switch (typeString.toLowerCase()) { case "widevine": return C.WIDEVINE_UUID; case "playready": return C.PLAYREADY_UUID; default: try { return UUID.fromString(typeString); } catch (RuntimeException e) { throw new ParserException("Unsupported drm type: " + typeString); } } }
// Adapter for original EventListener public static class EventListener implements ExoPlayer.EventListener {
private ExoPlayer.EventListener delegate;
public EventListener(ExoPlayer.EventListener delegate) {
this.delegate = delegate;
}
public EventListener() {
this.delegate = null;
}
public void setDelegate(ExoPlayer.EventListener delegate) {
this.delegate = delegate;
}
@Override public void onTimelineChanged(Timeline timeline, Object manifest) {
if (this.delegate != null) this.delegate.onTimelineChanged(timeline, manifest);
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
if (this.delegate != null) this.delegate.onTracksChanged(trackGroups, trackSelections);
}
@Override public void onLoadingChanged(boolean isLoading) {
if (this.delegate != null) this.delegate.onLoadingChanged(isLoading);
}
@Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (this.delegate != null) this.delegate.onPlayerStateChanged(playWhenReady, playbackState);
}
@Override public void onPlayerError(ExoPlaybackException error) {
if (this.delegate != null) this.delegate.onPlayerError(error);
}
@Override public void onPositionDiscontinuity() {
if (this.delegate != null) this.delegate.onPositionDiscontinuity();
}
@Override public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
if (this.delegate != null) this.delegate.onPlaybackParametersChanged(playbackParameters);
}
} }
i have the same issue , any solutions ?
above comments didn't work for you?
/*
- Copyright (c) 2017 Nam Nguyen, nam@ene.im
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License. */
package im.ene.toro.exoplayer;
import android.content.Context; import android.os.Handler; import android.os.Looper; import android.support.annotation.FloatRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.widget.Toast; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.DefaultRenderersFactory.ExtensionRendererMode; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; import com.google.android.exoplayer2.drm.FrameworkMediaDrm; import com.google.android.exoplayer2.drm.HttpMediaDrmCallback; import com.google.android.exoplayer2.drm.UnsupportedDrmException; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; import com.google.android.exoplayer2.source.BehindLiveWindowException; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.ui.SimpleExoPlayerView; import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; import com.google.android.exoplayer2.util.Util; import im.ene.toro.R; import im.ene.toro.ToroUtil; import im.ene.toro.media.DrmMedia; import im.ene.toro.media.PlaybackInfo; import java.net.CookieManager; import java.net.CookiePolicy; import java.util.ArrayList; import java.util.UUID;
import static com.google.android.exoplayer2.drm.UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME;
/**
- @author eneim | 6/5/17.
A helper class, dedicated to {@link SimpleExoPlayerView}.
*/
@SuppressWarnings({ "WeakerAccess", "unused" }) // public final class ExoPlayerHelper {
private static final String TAG = "ToroLib:ExoPlayer";
// instance is unchanged, but inner fields are changeable. @nonnull final PlaybackInfo playbackInfo = new PlaybackInfo();
final Context context; // Application context, will obtain from playerView context. @nonnull final SimpleExoPlayerView playerView; @ExtensionRendererMode final int extensionMode; final Handler mainHandler;
SimpleExoPlayer player; ComponentListener componentListener; DefaultTrackSelector trackSelector;
MediaSourceBuilder mediaSourceBuilder; BandwidthMeter bandwidthMeter;
boolean shouldAutoPlay; boolean needRetrySource;
ArrayList
eventListeners; public ExoPlayerHelper(@nonnull SimpleExoPlayerView playerView, @ExtensionRendererMode int extensionMode, boolean playWhenReady) { this.playerView = playerView; this.context = playerView.getContext().getApplicationContext(); this.extensionMode = extensionMode; this.shouldAutoPlay = playWhenReady; this.mainHandler = new Handler(Looper.myLooper()); }
public ExoPlayerHelper(@nonnull SimpleExoPlayerView playerView, @ExtensionRendererMode int extensionMode) { this(playerView, extensionMode, false); }
public ExoPlayerHelper(@nonnull SimpleExoPlayerView playerView) { this(playerView, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF); }
public void setPlaybackInfo(@nullable PlaybackInfo playbackInfo) { if (playbackInfo != null) { this.playbackInfo.setResumeWindow(playbackInfo.getResumeWindow()); this.playbackInfo.setResumePosition(playbackInfo.getResumePosition()); }
if (player != null) { boolean haveResumePosition = this.playbackInfo.getResumeWindow() != C.INDEX_UNSET; if (haveResumePosition) { player.seekTo(this.playbackInfo.getResumeWindow(), this.playbackInfo.getResumePosition()); } }
}
public void prepare(@nonnull MediaSourceBuilder mediaSourceBuilder) throws ParserException { prepare(mediaSourceBuilder, new DefaultBandwidthMeter(mainHandler, null)); }
public void prepare(@nonnull MediaSourceBuilder mediaSourceBuilder, @nullable BandwidthMeter bandwidthMeter) throws ParserException { //noinspection ConstantConditions if (mediaSourceBuilder == null) { throw new IllegalArgumentException("MediaSourceBuilder must not be null."); } this.mediaSourceBuilder = mediaSourceBuilder; DrmSessionManager drmSessionManager = null; if (mediaSourceBuilder instanceof DrmMediaProvider) { DrmMedia drmMedia = ((DrmMediaProvider) mediaSourceBuilder).getDrmMedia(); //noinspection ConstantConditions if (drmMedia == null) { throw new IllegalArgumentException("DrmMediaProvider must provide a non-null DrmMedia."); }
UUID drmSchemeUuid = getDrmUuid(drmMedia.getType()); if (drmSchemeUuid != null) { String drmLicenseUrl = drmMedia.getLicenseUrl(); String[] keyRequestPropertiesArray = drmMedia.getKeyRequestPropertiesArray(); try { drmSessionManager = buildDrmSessionManager(drmSchemeUuid, drmLicenseUrl, // keyRequestPropertiesArray, mainHandler); } catch (UnsupportedDrmException e) { int errorStringId = Util.SDK_INT < 18 ? R.string.error_drm_not_supported : (e.reason == REASON_UNSUPPORTED_SCHEME ? // R.string.error_drm_unsupported_scheme : R.string.error_drm_unknown); Toast.makeText(context, errorStringId, Toast.LENGTH_SHORT).show(); return; } } } prepare(mediaSourceBuilder.build(bandwidthMeter), bandwidthMeter, drmSessionManager);
}
@SuppressWarnings("ConstantConditions") // void prepare(@nonnull MediaSource mediaSource, BandwidthMeter bandwidthMeter, DrmSessionManager drmSessionManager) throws ParserException { if (mediaSource == null) { throw new IllegalStateException("MediaSource must not be null."); }
this.bandwidthMeter = bandwidthMeter; if (componentListener == null) { componentListener = new ComponentListener(); } this.player = playerView.getPlayer(); boolean needNewPlayer = player == null; if (needNewPlayer) { TrackSelection.Factory adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory); RenderersFactory renderersFactory = new DefaultRenderersFactory(context, drmSessionManager, extensionMode); player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector); player.addListener(componentListener); player.setPlayWhenReady(shouldAutoPlay); needRetrySource = true; } if (needNewPlayer || needRetrySource) { playerView.setPlayer(player); boolean haveResumePosition = playbackInfo.getResumeWindow() != C.INDEX_UNSET; if (haveResumePosition) { player.seekTo(playbackInfo.getResumeWindow(), playbackInfo.getResumePosition()); } player.prepare(mediaSource, !haveResumePosition, false); needRetrySource = false; }
}
public void release() { mainHandler.removeCallbacksAndMessages(null);
if (player != null) { shouldAutoPlay = player.getPlayWhenReady(); updateResumePosition(); player.removeListener(componentListener); player.release(); playerView.setPlayer(null); player = null; } trackSelector = null; mediaSourceBuilder = null; bandwidthMeter = null; componentListener = null;
}
@nonnull public PlaybackInfo getPlaybackInfo() { updateResumePosition(); // return a copy only. return new PlaybackInfo(playbackInfo.getResumeWindow(), playbackInfo.getResumePosition()); }
public void addEventListener(@nonnull ExoPlayer.EventListener eventListener) { if (this.eventListeners == null) { this.eventListeners = new ArrayList<>(); }
//noinspection ConstantConditions if (eventListener != null) this.eventListeners.add(eventListener);
}
public void removeEventListener(ExoPlayer.EventListener eventListener) { if (this.eventListeners != null && eventListener != null) { this.eventListeners.remove(eventListener); } }
public void play() { if (player != null) player.setPlayWhenReady(true);
}
public void pause() { if (player != null) player.setPlayWhenReady(false); }
public boolean isPlaying() { return this.player != null && this.player.getPlayWhenReady(); }
public void setVolume(@FloatRange(from = 0.0, to = 1.0) float volume) { if (player != null) player.setVolume(volume); }
public float getVolume() { return player != null ? player.getVolume() : 1 / unity gain, default value /; }
void updateResumePosition() { if (player == null || player.getPlaybackState() == 1) return; playbackInfo.setResumeWindow(player.getCurrentWindowIndex()); playbackInfo.setResumePosition( player.isCurrentWindowSeekable() ? Math.max(0, player.getCurrentPosition()) : C.TIME_UNSET); }
void clearResumePosition() { playbackInfo.reset(); }
private class ComponentListener implements ExoPlayer.EventListener {
ComponentListener() { } @Override public void onTimelineChanged(Timeline timeline, Object manifest) { int count; if (eventListeners != null && (count = eventListeners.size()) > 0) { for (int i = count - 1; i >= 0; i--) { eventListeners.get(i).onTimelineChanged(timeline, manifest); } } } @Override public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { MappedTrackInfo mappedTrackInfo = trackSelector != null ? trackSelector.getCurrentMappedTrackInfo() : null; if (mappedTrackInfo != null) { if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_VIDEO) == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) { Toast.makeText(context, R.string.error_unsupported_video, Toast.LENGTH_SHORT).show(); } if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_AUDIO) == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) { Toast.makeText(context, R.string.error_unsupported_audio, Toast.LENGTH_SHORT).show(); } } int count; if (eventListeners != null && (count = eventListeners.size()) > 0) { for (int i = count - 1; i >= 0; i--) { eventListeners.get(i).onTracksChanged(trackGroups, trackSelections); } } } @Override public void onLoadingChanged(boolean isLoading) { int count; if (eventListeners != null && (count = eventListeners.size()) > 0) { for (int i = count - 1; i >= 0; i--) { eventListeners.get(i).onLoadingChanged(isLoading); } } } @Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { boolean screenOn = isPlaying() && (playbackState >= 2 || playbackState <= 3); playerView.setKeepScreenOn(screenOn); if (playbackState == ExoPlayer.STATE_ENDED) { if (player != null) { player.setPlayWhenReady(false); player.seekTo(0); // reset playback position for current window } } int count; if (eventListeners != null && (count = eventListeners.size()) > 0) { for (int i = count - 1; i >= 0; i--) { eventListeners.get(i).onPlayerStateChanged(playWhenReady, playbackState); } } } @Override public void onPlayerError(ExoPlaybackException e) { String errorString = null; if (e.type == ExoPlaybackException.TYPE_RENDERER) { Exception cause = e.getRendererException(); if (cause instanceof MediaCodecRenderer.DecoderInitializationException) { // Special case for decoder initialization failures. MediaCodecRenderer.DecoderInitializationException decoderInitializationException = (MediaCodecRenderer.DecoderInitializationException) cause; if (decoderInitializationException.decoderName == null) { if (decoderInitializationException.getCause() instanceof MediaCodecUtil.DecoderQueryException) { errorString = context.getString(R.string.error_querying_decoders); } else if (decoderInitializationException.secureDecoderRequired) { errorString = context.getString(R.string.error_no_secure_decoder, decoderInitializationException.mimeType); } else { errorString = context.getString(R.string.error_no_decoder, decoderInitializationException.mimeType); } } else { errorString = context.getString(R.string.error_instantiating_decoder, decoderInitializationException.decoderName); } } } if (errorString != null) { Toast.makeText(context, errorString, Toast.LENGTH_SHORT).show(); } needRetrySource = true; if (isBehindLiveWindow(e)) { clearResumePosition(); try { prepare(ExoPlayerHelper.this.mediaSourceBuilder, ExoPlayerHelper.this.bandwidthMeter); } catch (ParserException e1) { e1.printStackTrace(); } } else { updateResumePosition(); } int count; if (eventListeners != null && (count = eventListeners.size()) > 0) { for (int i = count - 1; i >= 0; i--) { eventListeners.get(i).onPlayerError(e); } } } @Override public void onPositionDiscontinuity() { if (needRetrySource) { // This will only occur if the user has performed a seek whilst in the error playerState. Update the // resume position so that if the user then retries, playback will resume from the position to // which they seek. updateResumePosition(); } int count; if (eventListeners != null && (count = eventListeners.size()) > 0) { for (int i = count - 1; i >= 0; i--) { eventListeners.get(i).onPositionDiscontinuity(); } } } @Override public void onPlaybackParametersChanged(PlaybackParameters parameters) { int count; if (eventListeners != null && (count = eventListeners.size()) > 0) { for (int i = count - 1; i >= 0; i--) { eventListeners.get(i).onPlaybackParametersChanged(parameters); } } }
}
//// static methods
private static final CookieManager DEFAULT_COOKIE_MANAGER;
static { DEFAULT_COOKIE_MANAGER = new CookieManager(); DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); }
static boolean isBehindLiveWindow(ExoPlaybackException e) { if (e.type != ExoPlaybackException.TYPE_SOURCE) { return false; } Throwable cause = e.getSourceException(); while (cause != null) { if (cause instanceof BehindLiveWindowException) { return true; } cause = cause.getCause(); } return false; }
@nullable DrmSessionManager buildDrmSessionManager(UUID uuid, String licenseUrl, String[] keyRequestPropertiesArray, Handler mainHandler) throws UnsupportedDrmException { if (Util.SDK_INT < 18) { return null; } HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl, new DefaultHttpDataSourceFactory(Util.getUserAgent(context, ToroUtil.LIB_NAME), null)); if (keyRequestPropertiesArray != null) { for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) { drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i], keyRequestPropertiesArray[i + 1]); } } return new DefaultDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, null); }
private static UUID getDrmUuid(String typeString) throws ParserException { switch (typeString.toLowerCase()) { case "widevine": return C.WIDEVINE_UUID; case "playready": return C.PLAYREADY_UUID; default: try { return UUID.fromString(typeString); } catch (RuntimeException e) { throw new ParserException("Unsupported drm type: " + typeString); } } }
// Adapter for original EventListener public static class EventListener implements ExoPlayer.EventListener {
private ExoPlayer.EventListener delegate; public EventListener(ExoPlayer.EventListener delegate) { this.delegate = delegate; } public EventListener() { this.delegate = null; } public void setDelegate(ExoPlayer.EventListener delegate) { this.delegate = delegate; } @Override public void onTimelineChanged(Timeline timeline, Object manifest) { if (this.delegate != null) this.delegate.onTimelineChanged(timeline, manifest); } @Override public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { if (this.delegate != null) this.delegate.onTracksChanged(trackGroups, trackSelections); } @Override public void onLoadingChanged(boolean isLoading) { if (this.delegate != null) this.delegate.onLoadingChanged(isLoading); } @Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { if (this.delegate != null) this.delegate.onPlayerStateChanged(playWhenReady, playbackState); } @Override public void onPlayerError(ExoPlaybackException error) { if (this.delegate != null) this.delegate.onPlayerError(error); } @Override public void onPositionDiscontinuity() { if (this.delegate != null) this.delegate.onPositionDiscontinuity(); } @Override public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { if (this.delegate != null) this.delegate.onPlaybackParametersChanged(playbackParameters); }
} }
where i can use "player.seekTo()" because i can not find seekTo() in my toroplayer
I am facing this issue while scrolling after using your updated library 3.0.0-B1.
logcat- Player is playing while it is not in managed state: ViewHolder{11638295 position=11 id=-1, oldPos=-1, pLpos:-1} java.lang.IllegalStateException: Player is playing while it is not in managed state: ViewHolder{11638295 position=11 id=-1, oldPos=-1, pLpos:-1} at im.ene.toro.widget.Container.onChildDetachedFromWindow(Container.java:185) at android.support.v7.widget.RecyclerView.dispatchChildDetached(RecyclerView.java:6819) at android.support.v7.widget.RecyclerView$5.removeViewAt(RecyclerView.java:727) at android.support.v7.widget.ChildHelper.removeViewAt(ChildHelper.java:168) at android.support.v7.widget.RecyclerView$LayoutManager.removeViewAt(RecyclerView.java:7915) at android.support.v7.widget.RecyclerView$LayoutManager.removeAndRecycleViewAt(RecyclerView.java:8187) at android.support.v7.widget.LinearLayoutManager.recycleChildren(LinearLayoutManager.java:1367) at android.support.v7.widget.LinearLayoutManager.recycleViewsFromEnd(LinearLayoutManager.java:1453) at android.support.v7.widget.LinearLayoutManager.recycleByLayoutState(LinearLayoutManager.java:1476) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1502) at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1325) at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1061) at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1695) at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2883) at android.view.View.dispatchTouchEvent(View.java:8489) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2432) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2103) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2438) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2132) at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2386) at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1730) at android.app.Activity.dispatchTouchEvent(Activity.java:2757) at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71) at com.android.internal.policy.impl.PhoneWindow$DecorView.disp