android 多媒体列表,android – 使用Exoplayer的流媒体视频列表

我想实现流媒体视频列表应用.我使用RecyclerView来显示我的列表项.项目类型包括4种类型:文章,状态,照片和视频.我们应该只关注视频类型.这是我的RecyclerView适配器的代码:

public class FollowedPostAdapter extends RecyclerView.Adapter implements OnFollowTagCallback, OnLikeCallback {

private Context context;

private List newsFeedList;

public RecyclerView recyclerView;

public LinearLayoutManager linearLayoutManager;

private HashMap playerList;

private int visibleThreshold = 5;

// private int previousTotal = 0;

private int visibleItemCount, firstVisibleItem, totalItemCount;

private boolean loading;

private OnRecyclerViewLoadMoreListener loadMoreListener;

private final String text_comment;

private final String mReadMoreHtml;

private long userId;

public FollowedPostAdapter(Context context, RecyclerView recyclerView, List newsFeedList) {

this.context = context;

playerList = new HashMap<>();

this.newsFeedList = newsFeedList;

this.recyclerView = recyclerView;

this.linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();

}

@Override

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

RecyclerView.ViewHolder viewHolder;

if (viewType == Constants.VIEWTYPE_ARTICLE) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_followed_article_item, parent, false);

viewHolder = new ArticleViewHolder(view);

} else if (viewType == Constants.VIEWTYPE_STATUS) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_followed_status_item, parent, false);

viewHolder = new StatusViewHolder(view);

} else if (viewType == Constants.VIEWTYPE_PHOTO) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_followed_photo_item, parent, false);

viewHolder = new PhotoViewHolder(view);

} else if (viewType == Constants.VIEWTYPE_VIDEO) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_followed_video_item, parent, false);

viewHolder = new VideoViewHolder(view);

} else {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.progressbar_item, parent, false);

viewHolder = new ProgressBarViewHolder(view);

}

return viewHolder;

}

@Override

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

if (holder instanceof ArticleViewHolder) {

// code

} else if (holder instanceof StatusViewHolder) {

// code

} else if (holder instanceof PhotoViewHolder) {

// code

} else if (holder instanceof VideoViewHolder) {

PostItem item = newsFeedList.get(position);

VideoViewHolder mHolder = (VideoViewHolder) holder;

LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mHolder.videoView.getLayoutParams();

lp.height = (int) (ScreenHelper.getScreenWidth((Activity) context) * Constants.POST_IMAGE_RATIO);

mHolder.videoView.setLayoutParams(lp);

mHolder.setup(item);

Picasso.with(context).load(item.imageCover).error(R.drawable.ic_user_avatar).placeholder(R.drawable.ic_user_avatar).into(mHolder.iv_avatar);

if (item.tags != null && item.tags.size() > 0) {

// get first tag as main tag

generateTagViews(mHolder.tag_flow_layout, item.tags.subList(0, 1), position);

mHolder.tag_flow_layout.setVisibility(View.VISIBLE);

mHolder.tag_flow_layout.setVisibility(View.VISIBLE);

// mHolder.indicator.setVisibility(View.VISIBLE);

} else {

mHolder.tag_flow_layout.setVisibility(View.GONE);

// mHolder.indicator.setVisibility(View.GONE);

}

if (item.time_created != null) {

mHolder.tv_time.setText(item.time_created);

//mHolder.indicator.setVisibility(View.VISIBLE);

mHolder.tv_time.setVisibility(View.VISIBLE);

} else {

//mHolder.indicator.setVisibility(View.GONE);

mHolder.tv_time.setVisibility(View.GONE);

}

if (item.description_short.isEmpty())

mHolder.tv_description.setVisibility(View.GONE);

else {

mHolder.tv_description.setText(item.description_short);

mHolder.tv_description.setVisibility(View.VISIBLE);

}

mHolder.btn_comment.setText(String.valueOf(item.count_comment));

mHolder.btn_like.setText(String.valueOf(item.count_like));

mHolder.btn_unlike.setText(String.valueOf(item.count_unlike));

mHolder.btn_share.setText(String.valueOf(item.count_share));

if (item.tags.size() != 0) {

int tagId = item.tags.get(0).tag_id;

setFollowButtonActive(mHolder.btn_follow, TagHelper.isTagFollowed(tagId));

} else

setFollowButtonActive(mHolder.btn_follow, false);

}

}

@Override

public void onViewRecycled(RecyclerView.ViewHolder holder) {

super.onViewRecycled(holder);

if (holder instanceof VideoViewHolder) {

DemoPlayer player = playerList.get(holder.getAdapterPosition());

if (player != null) {

player.release();

playerList.remove(holder.getAdapterPosition());

}

}

}

public void pauseAllPlayers() {

for (int i = 0; i <= newsFeedList.size(); i++) {

DemoPlayer player = playerList.get(i);

if (player != null) {

if (player.getPlayerControl().isPlaying())

player.getPlayerControl().pause();

RecyclerView.ViewHolder holder = recyclerView.findViewHolderForLayoutPosition(i);

if (holder != null && holder instanceof VideoViewHolder) {

((VideoViewHolder) holder).btn_play.setVisibility(View.VISIBLE);

}

}

}

}

public void refreshData() {

notifyDataSetChanged();

}

public class ArticleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

//

}

public class StatusViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

// code

}

public class PhotoViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

// code

}

public class VideoViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, SurfaceHolder.Callback, AudioCapabilitiesReceiver.Listener, DemoPlayer.Listener, DemoPlayer.CaptionListener, DemoPlayer.Id3MetadataListener {

@Bind(R.id.iv_avatar)

ImageView iv_avatar;

@Bind(R.id.tag_flow_layout)

FlowLayout tag_flow_layout;

@Bind(R.id.tv_time)

TextView tv_time;

@Bind(R.id.btn_follow)

FancyButton btn_follow;

@Bind(R.id.btn_comment)

FancyButton btn_comment;

@Bind(R.id.btn_like)

FancyButton btn_like;

@Bind(R.id.btn_unlike)

FancyButton btn_unlike;

@Bind(R.id.btn_share)

FancyButton btn_share;

@Bind(R.id.root)

FrameLayout videoView;

@Bind(R.id.btn_play)

ImageView btn_play;

@Bind(R.id.tv_description)

TextView tv_description;

// player's variable

private EventLogger eventLogger;

// private VideoControllerView mediaController;

private View shutterView;

private AspectRatioFrameLayout videoFrame;

private SurfaceView surfaceView;

private SubtitleLayout subtitleLayout;

private DemoPlayer player;

private boolean playerNeedsPrepare;

private long playerPosition = 0;

private Uri contentUri;

private int contentType;

private String contentId;

public static final int TYPE_DASH = 0;

public static final int TYPE_SS = 1;

public static final int TYPE_HLS = 2;

public static final int TYPE_OTHER = 3;

private static final String EXT_DASH = ".mpd";

private static final String EXT_SS = ".ism";

private static final String EXT_HLS = ".m3u8";

private AudioCapabilitiesReceiver audioCapabilitiesReceiver;

public VideoViewHolder(View view) {

super(view);

ButterKnife.bind(this, view);

iv_avatar.setOnClickListener(this);

btn_follow.setOnClickListener(this);

btn_comment.setOnClickListener(this);

btn_like.setOnClickListener(this);

btn_unlike.setOnClickListener(this);

btn_share.setOnClickListener(this);

// player's setup

View root = view.findViewById(R.id.root);

root.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

doPlayResume();

}

});

// root.setOnTouchListener(new View.OnTouchListener() {

// @Override

// public boolean onTouch(View view, MotionEvent motionEvent) {

// if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {

// toggleControlsVisibility();

// } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {

// view.performClick();

// }

// return true;

// }

// });

// root.setOnKeyListener(new View.OnKeyListener() {

// @Override

// public boolean onKey(View v, int keyCode, KeyEvent event) {

// if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE

// || keyCode == KeyEvent.KEYCODE_MENU) {

// return false;

// }

// return mediaController.dispatchKeyEvent(event);

// }

// });

shutterView = view.findViewById(R.id.shutter);

videoFrame = (AspectRatioFrameLayout) view.findViewById(R.id.video_frame);

surfaceView = (SurfaceView) view.findViewById(R.id.surface_view);

surfaceView.getHolder().addCallback(this);

subtitleLayout = (SubtitleLayout) view.findViewById(R.id.subtitles);

// mediaController = new VideoControllerView(context);

// mediaController.setAnchorView((ViewGroup) root);

audioCapabilitiesReceiver = new AudioCapabilitiesReceiver(context, this);

audioCapabilitiesReceiver.register();

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.iv_avatar:

viewTagDetail(getAdapterPosition());

break;

case R.id.btn_follow:

followTag((FancyButton) v, getAdapterPosition());

break;

case R.id.btn_comment:

commentPost(getAdapterPosition());

break;

case R.id.btn_like:

likePost(getAdapterPosition(), btn_like, btn_unlike);

break;

case R.id.btn_unlike:

unlikePost(getAdapterPosition(), btn_like, btn_unlike);

break;

case R.id.btn_share:

sharePost(getAdapterPosition());

break;

case R.id.btn_play:

doPlayResume();

break;

}

}

public void setup(PostItem item) {

releasePlayer();

player = playerList.get(getAdapterPosition());

contentUri = Uri.parse(item.link);

contentType = TYPE_OTHER;

contentId = String.valueOf(item.post_id);

configureSubtitleView();

if (player == null) {

preparePlayer(false);

} else {

player.setBackgrounded(false);

}

}

// public void saveCurrentPosition() {

// if (player != null)

// videoItemList.get(getAdapterPosition()).position = player.getCurrentPosition();

// }

public void doPlayResume() {

if (player == null) {

return;

}

if (player.getPlayerControl().isPlaying()) {

player.getPlayerControl().pause();

} else {

player.getPlayerControl().start();

}

showControls();

}

@Override

public void onAudioCapabilitiesChanged(AudioCapabilities audioCapabilities) {

if (player == null) {

return;

}

boolean backgrounded = player.getBackgrounded();

boolean playWhenReady = player.getPlayWhenReady();

releasePlayer();

preparePlayer(playWhenReady);

player.setBackgrounded(backgrounded);

}

private DemoPlayer.RendererBuilder getRendererBuilder() {

String userAgent = Util.getUserAgent(context, "ExoPlayerDemo");

switch (contentType) {

case TYPE_SS:

return new SmoothStreamingRendererBuilder(context, userAgent, contentUri.toString(),

new SmoothStreamingTestMediaDrmCallback());

case TYPE_DASH:

return new DashRendererBuilder(context, userAgent, contentUri.toString(),

new WidevineTestMediaDrmCallback(contentId));

case TYPE_HLS:

return new HlsRendererBuilder(context, userAgent, contentUri.toString());

case TYPE_OTHER:

return new ExtractorRendererBuilder(context, userAgent, contentUri);

default:

throw new IllegalStateException("Unsupported type: " + contentType);

}

}

private void preparePlayer(boolean playWhenReady) {

if (player == null) {

player = new DemoPlayer(getRendererBuilder());

playerList.put(getAdapterPosition(), player);

player.addListener(this);

player.setCaptionListener(this);

player.setMetadataListener(this);

player.seekTo(playerPosition);

playerNeedsPrepare = true;

// mediaController.setMediaPlayer(player.getPlayerControl());

// mediaController.setEnabled(true);

eventLogger = new EventLogger();

eventLogger.startSession();

player.addListener(eventLogger);

player.setInfoListener(eventLogger);

player.setInternalErrorListener(eventLogger);

}

if (playerNeedsPrepare) {

player.prepare();

playerNeedsPrepare = false;

}

player.setSurface(surfaceView.getHolder().getSurface());

player.setPlayWhenReady(playWhenReady);

}

private void releasePlayer() {

if (player != null) {

player.release();

player = null;

eventLogger.endSession();

eventLogger = null;

btn_play.setVisibility(View.VISIBLE);

}

}

@Override

public void onStateChanged(boolean playWhenReady, int playbackState) {

if (playbackState == ExoPlayer.STATE_ENDED) {

showControls();

}

}

@Override

public void onError(Exception e) {

if (e instanceof UnsupportedDrmException) {

// Special case DRM failures.

UnsupportedDrmException unsupportedDrmException = (UnsupportedDrmException) e;

int stringId = Util.SDK_INT < 18 ? R.string.drm_error_not_supported

: unsupportedDrmException.reason == UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME

? R.string.drm_error_unsupported_scheme : R.string.drm_error_unknown;

Toast.makeText(context, stringId, Toast.LENGTH_LONG).show();

}

playerNeedsPrepare = true;

showControls();

}

@Override

public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {

shutterView.setVisibility(View.GONE);

videoFrame.setAspectRatio(

height == 0 ? 1 : (width * pixelWidthHeightRatio) / height);

}

private boolean haveTracks(int type) {

return player != null && player.getTrackCount(type) > 0;

}

// private void toggleControlsVisibility() {

// if (mediaController.isShowing()) {

// mediaController.hide();

// } else {

// showControls();

// }

// }

private void showControls() {

// mediaController.show(5000);

if (player.getPlayerControl().isPlaying())

btn_play.setVisibility(View.GONE);

else

btn_play.setVisibility(View.VISIBLE);

}

@Override

public void onCues(List cues) {

subtitleLayout.setCues(cues);

}

@Override

public void onId3Metadata(Map metadata) {

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

if (player != null) {

player.setSurface(holder.getSurface());

}

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

if (player != null) {

holder.lockCanvas();

player.blockingClearSurface();

}

}

private void configureSubtitleView() {

CaptionStyleCompat style;

float fontScale;

if (Util.SDK_INT >= 19) {

style = getUserCaptionStyleV19();

fontScale = getUserCaptionFontScaleV19();

} else {

style = CaptionStyleCompat.DEFAULT;

fontScale = 1.0f;

}

subtitleLayout.setStyle(style);

subtitleLayout.setFractionalTextSize(SubtitleLayout.DEFAULT_TEXT_SIZE_FRACTION * fontScale);

}

@TargetApi(19)

private float getUserCaptionFontScaleV19() {

CaptioningManager captioningManager =

(CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);

return captioningManager.getFontScale();

}

@TargetApi(19)

private CaptionStyleCompat getUserCaptionStyleV19() {

CaptioningManager captioningManager =

(CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);

return CaptionStyleCompat.createFromCaptionStyle(captioningManager.getUserStyle());

}

private int inferContentType(Uri uri, String fileExtension) {

String lastPathSegment = !TextUtils.isEmpty(fileExtension) ? "." + fileExtension

: uri.getLastPathSegment();

if (lastPathSegment == null) {

return TYPE_OTHER;

} else if (lastPathSegment.endsWith(EXT_DASH)) {

return TYPE_DASH;

} else if (lastPathSegment.endsWith(EXT_SS)) {

return TYPE_SS;

} else if (lastPathSegment.endsWith(EXT_HLS)) {

return TYPE_HLS;

} else {

return TYPE_OTHER;

}

}

}

public class ProgressBarViewHolder extends RecyclerView.ViewHolder {

public ProgressBarViewHolder(View view) {

super(view);

}

}

public void unregisterEventBus() {

EventBus.getDefault().unregister(this);

}

}

>当项目类型为视频时,我创建一个ExoPlayer实例来播放此视频并将此实例添加到HashMap以供以后使用(键值是项目的位置).如果视频项目正在被回收,我会释放播放器并将其从HashMap中删除.

>一切看起来都很好但是有问题.我想视频项目位于0位置(现在我们可以看到此项目中的视频预览).我向下滚动RecyclerView就足以隐藏项目0.此时,项目0的VideoViewHolder尚未回收.然后,我向上滚动以显示项目0.视图现在为空白,不显示视频预览.我点击第0项播放视频,播放器只播放音频(声音),不播放视频.播放几秒钟后,视频现在可见.

>我调试并发现在我向下滚动以隐藏视频项后,SurfaceView被销毁.向上滚动以显示视频项目时,将创建SurfaceView.我认为这就是VideoViewHolder显示空白视图而不是视频预览的原因.

>这是我的问题:如何在滚动回视频项目后显示视频预览?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值