Commit f8c24ce4 authored by jyx's avatar jyx

添加视频播放页

parent 33e6c686
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_15" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
......
......@@ -230,7 +230,6 @@ dependencies {
// umeng 接入
// 穿山甲聚合 接入【穿山甲、快手】
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
......
......@@ -116,6 +116,11 @@
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".video.VideoActivity"
android:exported="false"
android:screenOrientation="portrait" />
<service
android:name=".ui.service.UpdateService"
android:exported="true" />
......
package com.mints.wisdomclean.video;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import com.mints.wisdomclean.R;
import cn.jzvd.JzvdStd;
public class JzvdStdTikTok extends JzvdStd {
public JzvdStdTikTok(Context context) {
super(context);
}
public JzvdStdTikTok(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void init(Context context) {
super.init(context);
bottomContainer.setVisibility(GONE);
topContainer.setVisibility(GONE);
bottomProgressBar.setVisibility(GONE);
posterImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
}
//changeUiTo 真能能修改ui的方法
@Override
public void changeUiToNormal() {
super.changeUiToNormal();
bottomContainer.setVisibility(GONE);
topContainer.setVisibility(GONE);
}
@Override
public void setAllControlsVisiblity(int topCon, int bottomCon, int startBtn, int loadingPro,
int posterImg, int bottomPro, int retryLayout) {
topContainer.setVisibility(INVISIBLE);
bottomContainer.setVisibility(INVISIBLE);
startButton.setVisibility(startBtn);
loadingProgressBar.setVisibility(loadingPro);
posterImageView.setVisibility(posterImg);
bottomProgressBar.setVisibility(GONE);
mRetryLayout.setVisibility(retryLayout);
}
@Override
public void dissmissControlView() {
if (state != STATE_NORMAL
&& state != STATE_ERROR
&& state != STATE_AUTO_COMPLETE) {
post(() -> {
bottomContainer.setVisibility(View.INVISIBLE);
topContainer.setVisibility(View.INVISIBLE);
startButton.setVisibility(View.INVISIBLE);
if (clarityPopWindow != null) {
clarityPopWindow.dismiss();
}
if (screen != SCREEN_TINY) {
bottomProgressBar.setVisibility(View.GONE);
}
});
}
}
@Override
public void onClickUiToggle() {
super.onClickUiToggle();
Log.i(TAG, "click blank");
startButton.performClick();
bottomContainer.setVisibility(GONE);
topContainer.setVisibility(GONE);
}
public void updateStartImage() {
if (state == STATE_PLAYING) {
startButton.setVisibility(VISIBLE);
startButton.setImageResource(R.drawable.tiktok_play_tiktok);
replayTextView.setVisibility(GONE);
} else if (state == STATE_ERROR) {
startButton.setVisibility(INVISIBLE);
replayTextView.setVisibility(GONE);
} else if (state == STATE_AUTO_COMPLETE) {
startButton.setVisibility(VISIBLE);
startButton.setImageResource(R.drawable.tiktok_play_tiktok);
replayTextView.setVisibility(VISIBLE);
} else {
startButton.setImageResource(R.drawable.tiktok_play_tiktok);
replayTextView.setVisibility(GONE);
}
}
@Override
public void onCompletion() {
super.onCompletion();
this.onVideoCompletion.onVideoCompletion();
}
public void setOnVideoCompletion(OnVideoCompletion onVideoCompletion) {
this.onVideoCompletion = onVideoCompletion;
}
private OnVideoCompletion onVideoCompletion;
public interface OnVideoCompletion {
void onVideoCompletion();
}
}
package com.mints.wisdomclean.video;
/**
* Created by 钉某人
* github: https://github.com/DingMouRen
* email: naildingmouren@gmail.com
* 用于ViewPagerLayoutManager的监听
*/
public interface OnViewPagerListener {
/*初始化完成*/
void onInitComplete();
/*释放的监听*/
void onPageRelease(boolean isNext, int position);
/*选中的监听以及判断是否滑动到底部*/
void onPageSelected(int position, boolean isBottom);
}
package com.mints.wisdomclean.video;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.mints.wisdomclean.R;
import cn.jzvd.JZDataSource;
import cn.jzvd.Jzvd;
public class TikTokRecyclerViewAdapter extends RecyclerView.Adapter<TikTokRecyclerViewAdapter.MyViewHolder> {
public static final String TAG = "AdapterTikTokRecyclerView";
int[] videoIndexs = {0, 1, 2, 3, 4, 5};
private Context context;
public TikTokRecyclerViewAdapter(Context context) {
this.context = context;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
context).inflate(R.layout.item_tiktok, parent,
false));
return holder;
}
@SuppressLint("LongLogTag")
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
position = position % videoIndexs.length;
Log.i(TAG, "onBindViewHolder [" + holder.jzvdStd.hashCode() + "] position=" + position);
// JZDataSource jzDataSource = new JZDataSource(
// UrlsKt.getVl3()[position],
// UrlsKt.getTl3()[position]);
JZDataSource jzDataSource;
if (position % 2 == 0) {
jzDataSource = new JZDataSource(
"http://oss-cn-beijing.aliyuncs.com/static-thefair-bj/eyepetizer/pgc_video/video_summary/219338.mp4",
"测试测试测试1");
} else {
jzDataSource = new JZDataSource(
"http://oss-cn-beijing.aliyuncs.com/static-thefair-bj/eyepetizer/pgc_video/video_summary/220775.mp4",
"测试测试测试2");
}
holder.jzvdStd.setOnVideoCompletion(onVideoCompletion);
// jzDataSource.looping = true;
jzDataSource.looping = false;
holder.jzvdStd.setUp(jzDataSource, Jzvd.SCREEN_NORMAL);
Glide.with(holder.jzvdStd.getContext()).load(UrlsKt.getPl3()[position]).into(holder.jzvdStd.posterImageView);
}
public void setOnVideoCompletion(JzvdStdTikTok.OnVideoCompletion onVideoCompletion) {
this.onVideoCompletion = onVideoCompletion;
}
private JzvdStdTikTok.OnVideoCompletion onVideoCompletion;
@Override
public int getItemCount() {
// return videoIndexs.length;
return Integer.MAX_VALUE;
}
static class MyViewHolder extends RecyclerView.ViewHolder {
JzvdStdTikTok jzvdStd;
public MyViewHolder(View itemView) {
super(itemView);
jzvdStd = itemView.findViewById(R.id.videoplayer);
}
}
}
package com.mints.wisdomclean.video
import android.view.MenuItem
import android.view.View
import androidx.recyclerview.widget.OrientationHelper
import androidx.recyclerview.widget.RecyclerView
import cn.jzvd.Jzvd
import com.mints.wisdomclean.R
import com.mints.wisdomclean.ui.activitys.base.BaseActivity
import kotlinx.android.synthetic.main.activity_video.*
class VideoActivity : BaseActivity() {
private var mAdapter: TikTokRecyclerViewAdapter? = null
private var mViewPagerLayoutManager: ViewPagerLayoutManager? = null
private var mCurrentPosition = -1
override fun getContentViewLayoutID() = R.layout.activity_video
override fun initViewsAndEvents() {
mAdapter = TikTokRecyclerViewAdapter(this)
mAdapter?.setOnVideoCompletion {
// if (mCurrentPosition > mAdapter!!.videoIndexs.size) return@setOnVideoCompletion
rv_video.smoothScrollToPosition(mCurrentPosition + 1)
}
mViewPagerLayoutManager = ViewPagerLayoutManager(this, OrientationHelper.VERTICAL)
rv_video.layoutManager = mViewPagerLayoutManager
rv_video.adapter = mAdapter
mViewPagerLayoutManager?.setOnViewPagerListener(object : OnViewPagerListener {
override fun onInitComplete() {
mCurrentPosition = 0
//自动播放第一条
autoPlayVideo(0)
}
override fun onPageRelease(isNext: Boolean, position: Int) {
if (mCurrentPosition == position) {
Jzvd.releaseAllVideos()
}
}
override fun onPageSelected(position: Int, isBottom: Boolean) {
if (mCurrentPosition == position) {
return
}
autoPlayVideo(position)
mCurrentPosition = position
}
})
rv_video.addOnChildAttachStateChangeListener(object :
RecyclerView.OnChildAttachStateChangeListener {
override fun onChildViewAttachedToWindow(view: View) {}
override fun onChildViewDetachedFromWindow(view: View) {
val jzvd = view.findViewById<Jzvd>(R.id.videoplayer)
if (jzvd != null && Jzvd.CURRENT_JZVD != null && jzvd.jzDataSource != null &&
jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.currentUrl)
) {
if (Jzvd.CURRENT_JZVD != null && Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_FULLSCREEN) {
Jzvd.releaseAllVideos()
}
}
}
})
}
private fun autoPlayVideo(postion: Int) {
if (rv_video == null || rv_video.getChildAt(0) == null) {
return
}
val player: JzvdStdTikTok = rv_video.getChildAt(0).findViewById(R.id.videoplayer)
if (player != null) {
player.startVideoAfterPreloading()
}
}
override fun onBackPressed() {
if (Jzvd.backPress()) {
return
}
super.onBackPressed()
}
override fun onPause() {
super.onPause()
Jzvd.releaseAllVideos()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> finish()
}
return super.onOptionsItemSelected(item)
}
override fun isApplyKitKatTranslucency() = true
}
\ No newline at end of file
package com.mints.wisdomclean.video;
import android.content.Context;
import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.PagerSnapHelper;
import androidx.recyclerview.widget.RecyclerView;
/**
* Created by 钉某人
* github: https://github.com/DingMouRen
* email: naildingmouren@gmail.com
*/
public class ViewPagerLayoutManager extends LinearLayoutManager {
private static final String TAG = "ViewPagerLayoutManager";
private PagerSnapHelper mPagerSnapHelper;
private OnViewPagerListener mOnViewPagerListener;
private RecyclerView mRecyclerView;
private int mDrift;//位移,用来判断移动方向
private RecyclerView.OnChildAttachStateChangeListener mChildAttachStateChangeListener = new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {
if (mOnViewPagerListener != null && getChildCount() == 1) {
mOnViewPagerListener.onInitComplete();
}
}
@Override
public void onChildViewDetachedFromWindow(View view) {
if (mDrift >= 0) {
if (mOnViewPagerListener != null)
mOnViewPagerListener.onPageRelease(true, getPosition(view));
} else {
if (mOnViewPagerListener != null)
mOnViewPagerListener.onPageRelease(false, getPosition(view));
}
}
};
public ViewPagerLayoutManager(Context context, int orientation) {
super(context, orientation, false);
init();
}
public ViewPagerLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
init();
}
private void init() {
mPagerSnapHelper = new PagerSnapHelper();
}
@Override
public void onAttachedToWindow(RecyclerView view) {
super.onAttachedToWindow(view);
mPagerSnapHelper.attachToRecyclerView(view);
this.mRecyclerView = view;
mRecyclerView.addOnChildAttachStateChangeListener(mChildAttachStateChangeListener);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
}
/**
* 滑动状态的改变
* 缓慢拖拽-> SCROLL_STATE_DRAGGING
* 快速滚动-> SCROLL_STATE_SETTLING
* 空闲状态-> SCROLL_STATE_IDLE
*
* @param state
*/
@Override
public void onScrollStateChanged(int state) {
switch (state) {
case RecyclerView.SCROLL_STATE_IDLE:
View viewIdle = mPagerSnapHelper.findSnapView(this);
if (viewIdle != null) {
int positionIdle = getPosition(viewIdle);
if (mOnViewPagerListener != null && getChildCount() == 1) {
mOnViewPagerListener.onPageSelected(positionIdle, positionIdle == getItemCount() - 1);
}
}
break;
}
}
/**
* 监听竖直方向的相对偏移量
*
* @param dy
* @param recycler
* @param state
* @return
*/
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
this.mDrift = dy;
return super.scrollVerticallyBy(dy, recycler, state);
}
/**
* 监听水平方向的相对偏移量
*
* @param dx
* @param recycler
* @param state
* @return
*/
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
this.mDrift = dx;
return super.scrollHorizontallyBy(dx, recycler, state);
}
/**
* 设置监听
*
* @param listener
*/
public void setOnViewPagerListener(OnViewPagerListener listener) {
this.mOnViewPagerListener = listener;
}
}
package com.mints.wisdomclean.video
// Chrome浏览器和饺子demo(android.MediaPlayer)相同时间相同网络环境播放,速度相差很远,为什么。
// ijk好像略快,但没有电脑的chrome快。红米手机的自带浏览器可以完整观看视频无需中途加载。
val cn = "http://8.136.101.204"
val us = "http://videos.jzvd.org"
var server_name: String = cn
val ldjVideos = arrayOf(
"$server_name/v/ldj/01-ldj.mp4",
"$server_name/v/ldj/02-ldj.mp4",
"$server_name/v/ldj/03-ldj.mp4",
"$server_name/v/ldj/04-ldj.mp4",
"$server_name/v/ldj/05-ldj.mp4",
"$server_name/v/ldj/06-ldj.mp4",
"$server_name/v/ldj/07-ldj.mp4",
"$server_name/v/ldj/08-ldj.mp4",
"$server_name/v/ldj/09-ldj.mp4",
"$server_name/v/ldj/10-ldj.mp4",
"$server_name/v/ldj/11-ldj.mp4",
"$server_name/v/ldj/12-ldj.mp4",
"$server_name/v/ldj/13-ldj.mp4",
"$server_name/v/ldj/14-ldj.mp4",
"$server_name/v/ldj/15-ldj.mp4",
"$server_name/v/ldj/16-ldj.mp4",
"$server_name/v/ldj/17-ldj.mp4",
"$server_name/v/ldj/18-ldj.mp4",
"$server_name/v/ldj/19-ldj.mp4",
"$server_name/v/ldj/20-ldj.mp4",
"$server_name/v/ldj/21-ldj.mp4",
"$server_name/v/ldj/22-ldj.mp4",
"$server_name/v/ldj/23-ldj.mp4",
"$server_name/v/ldj/24-ldj.mp4",
"$server_name/v/ldj/25-ldj.mp4",
"$server_name/v/ldj/26-ldj.mp4",
"$server_name/v/ldj/27-ldj.mp4",
"$server_name/v/ldj/28-ldj.mp4",
"$server_name/v/ldj/29-ldj.mp4",
"$server_name/v/ldj/30-ldj.mp4",
"$server_name/v/ldj/31-ldj.mp4",
"$server_name/v/ldj/32-ldj.mp4",
"$server_name/v/ldj/33-ldj.mp4",
"$server_name/v/ldj/34-ldj.mp4",
"$server_name/v/ldj/35-ldj.mp4",
"$server_name/v/ldj/36-ldj.mp4",
"$server_name/v/ldj/37-ldj.mp4",
"$server_name/v/ldj/38-ldj.mp4",
"$server_name/v/ldj/39-ldj.mp4",
"$server_name/v/ldj/40-ldj.mp4",
"$server_name/v/ldj/41-ldj.mp4",
"$server_name/v/ldj/42-ldj.mp4",
"$server_name/v/ldj/43-ldj.mp4",
"$server_name/v/ldj/44-ldj.mp4",
"$server_name/v/ldj/45-ldj.mp4"
)
val cndVideos = arrayOf(
"https://jzvd.nathen.cn/video/cfe6c30-1767b1bc21f-0007-1823-c86-de200.mp4",//三个不同分辨率
"https://jzvd.nathen.cn/0339d49439f947419576c33a0aa51545/79e1a938b0d2435d85bd964a77640506-f4e986e3e38ed3f473f7ba82bc07e188-ld.mp4",
"https://jzvd.nathen.cn/0339d49439f947419576c33a0aa51545/79e1a938b0d2435d85bd964a77640506-8924c7da92ebd789d315bc5de0a81059-fd.mp4",
"https://jzvd.nathen.cn/video/59aa468b-1767b6d891e-0007-1823-c86-de200.mp4",//饺子还小
"https://jzvd.nathen.cn/video/25ae1b1c-1767b2a5e44-0007-1823-c86-de200.mp4",//饺子还年轻
"https://jzvd.nathen.cn/video/5a6465ff-1767b2a5e28-0007-1823-c86-de200.mp4"
)
val cndThumbnail = arrayOf(
"https://jzvd.nathen.cn/snapshot/0339d49439f947419576c33a0aa5154500005.jpg",
"",
"",
"https://jzvd.nathen.cn/snapshot/61c99f9225c04b24a1d0374e9a3f006700004.jpg",
"https://jzvd.nathen.cn/snapshot/044ef6cf452d48b795cea0a96ee4ea4100002.jpg",
"https://jzvd.nathen.cn/snapshot/a172cc6442ff40ffb826829fc78f83b700005.jpg"
)
val videos = arrayOf(
//width > height
"$server_name/v/饺子主动.mp4",
"$server_name/v/饺子运动.mp4",
"$server_name/v/饺子有活.mp4",
"$server_name/v/饺子星光.mp4",
"$server_name/v/饺子想吹.mp4",
"$server_name/v/饺子汪汪.mp4",
"$server_name/v/饺子偷人.mp4",
"$server_name/v/饺子跳.mp4",
"$server_name/v/饺子受不了.mp4",
"$server_name/v/饺子三位.mp4",
"$server_name/v/饺子起飞.mp4",
"$server_name/v/饺子你听.mp4",
"$server_name/v/饺子可以了.mp4",
"$server_name/v/饺子还小.mp4",
"$server_name/v/饺子高兴.mp4",
"$server_name/v/饺子高冷.mp4",
"$server_name/v/饺子堵住了.mp4",
"$server_name/v/饺子都懂.mp4",
"$server_name/v/饺子打电话.mp4",
"$server_name/v/饺子不服.mp4",
//height > width
"$server_name/v/饺子还年轻.mp4",
"$server_name/v/饺子好妈妈.mp4",
"$server_name/v/饺子可以.mp4",
"$server_name/v/饺子挺住.mp4",
"$server_name/v/饺子想听.mp4",
"$server_name/v/饺子真会.mp4",
"$server_name/v/饺子真萌.mp4"
)
val thumbnails = arrayOf(
"$server_name/v/饺子主动.jpg",
"$server_name/v/饺子运动.jpg",
"$server_name/v/饺子有活.jpg",
"$server_name/v/饺子星光.jpg",
"$server_name/v/饺子想吹.jpg",
"$server_name/v/饺子汪汪.jpg",
"$server_name/v/饺子偷人.jpg",
"$server_name/v/饺子跳.jpg",
"$server_name/v/饺子受不了.jpg",
"$server_name/v/饺子三位.jpg",
"$server_name/v/饺子起飞.jpg",
"$server_name/v/饺子你听.jpg",
"$server_name/v/饺子可以了.jpg",
"$server_name/v/饺子还小.jpg",
"$server_name/v/饺子高兴.jpg",
"$server_name/v/饺子高冷.jpg",
"$server_name/v/饺子堵住了.jpg",
"$server_name/v/饺子都懂.jpg",
"$server_name/v/饺子打电话.jpg",
"$server_name/v/饺子不服.jpg",
//height > width
"$server_name/v/饺子还年轻.jpg",
"$server_name/v/饺子好妈妈.jpg",
"$server_name/v/饺子可以.jpg",
"$server_name/v/饺子挺住.jpg",
"$server_name/v/饺子想听.jpg",
"$server_name/v/饺子真会.jpg",
"$server_name/v/饺子真萌.jpg"
)
val titles = arrayOf(
//width > height
"饺子主动",
"饺子运动",
"饺子有活",
"饺子星光",
"饺子想吹",
"饺子汪汪",
"饺子偷人",
"饺子跳",
"饺子受不了",
"饺子三位",
"饺子起飞",
"饺子你听",
"饺子可以了",
"饺子还小",
"饺子高兴",
"饺子高冷",
"饺子堵住了",
"饺子都懂",
"饺子打电话",
"饺子不服",
//height > width
"饺子还年轻",
"饺子好妈妈",
"饺子可以",
"饺子挺住",
"饺子想听",
"饺子真会",
"饺子真萌"
)
val vl1 = videos.copyOfRange(0, 9)
val pl1 = thumbnails.copyOfRange(0, 9)
val tl1 = titles.copyOfRange(0, 9)
val vl2 = videos.copyOfRange(10, 20)
val pl2 = thumbnails.copyOfRange(10, 20)
val tl2 = titles.copyOfRange(10, 20)
val vl3 = videos.copyOfRange(20, 26)
val pl3 = thumbnails.copyOfRange(20, 26)
val tl3 = titles.copyOfRange(20, 26)
val vll = arrayOf(
vl1, vl2, vl3
)
val pll = arrayOf(
pl1, pl2, pl3
)
val tll = arrayOf(
tl1, tl2, tl3
)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".video.VideoActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_video"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.mints.wisdomclean.video.JzvdStdTikTok
android:id="@+id/videoplayer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment