diff --git a/app/build.gradle b/app/build.gradle index 973830e..a6061ba 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -49,7 +49,7 @@ dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.1.0' implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' - implementation 'cn.jzvd:jiaozivideoplayer:7.6.0' +// implementation 'cn.jzvd:jiaozivideoplayer:7.6.0' implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-core:1.0.15' implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-native:1.0.15' implementation 'com.github.ittianyu:BottomNavigationViewEx:2.0.4' @@ -64,4 +64,5 @@ dependencies { implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8' implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4' debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3' + implementation project(path: ':library') } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 387bf01..c90c774 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,7 +13,10 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> - + @@ -21,9 +24,10 @@ - diff --git a/app/src/main/java/com/uiui/videoplayer/CustomJzvd/JzvdStdAssert.java b/app/src/main/java/com/uiui/videoplayer/CustomJzvd/JzvdStdAssert.java index 3b68198..96f6de1 100644 --- a/app/src/main/java/com/uiui/videoplayer/CustomJzvd/JzvdStdAssert.java +++ b/app/src/main/java/com/uiui/videoplayer/CustomJzvd/JzvdStdAssert.java @@ -5,6 +5,7 @@ import android.util.AttributeSet; import cn.jzvd.JzvdStd; + public class JzvdStdAssert extends JzvdStd { public JzvdStdAssert(Context context) { super(context); @@ -24,4 +25,10 @@ public class JzvdStdAssert extends JzvdStd { } onStatePlaying(); } + + @Override + public void gotoFullscreen() { + super.gotoFullscreen(); + + } } diff --git a/app/src/main/java/com/uiui/videoplayer/activity/ActivityTikTok.java b/app/src/main/java/com/uiui/videoplayer/activity/ActivityTikTok.java index 3670ccd..4c7d2f4 100644 --- a/app/src/main/java/com/uiui/videoplayer/activity/ActivityTikTok.java +++ b/app/src/main/java/com/uiui/videoplayer/activity/ActivityTikTok.java @@ -1,14 +1,19 @@ package com.uiui.videoplayer.activity; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.os.Bundle; +import android.util.Log; import android.view.MenuItem; import android.view.View; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.OrientationHelper; import androidx.recyclerview.widget.RecyclerView; @@ -23,15 +28,18 @@ import java.util.ArrayList; import java.util.List; import cn.jzvd.Jzvd; +import cn.jzvd.JzvdStd; public class ActivityTikTok extends AppCompatActivity { + private static final String TAG = "ActivityTikTok"; private RecyclerView rvTiktok; private TikTokRecyclerViewAdapter mAdapter; private ViewPagerLayoutManager mViewPagerLayoutManager; private int mCurrentPosition = -1; private int position = 0; private List videoPath = new ArrayList<>(); + private int onGlobalLayout = -1; @Override protected void onCreate(Bundle savedInstanceState) { @@ -44,24 +52,31 @@ public class ActivityTikTok extends AppCompatActivity { Intent intent = getIntent(); if (null != intent) { position = intent.getIntExtra("position", 0); + Log.e(TAG, "position: " + position); videoPath = intent.getStringArrayListExtra("list"); } rvTiktok = findViewById(R.id.rv_tiktok); - mAdapter = new TikTokRecyclerViewAdapter(this,videoPath ); + mAdapter = new TikTokRecyclerViewAdapter(this, videoPath); mViewPagerLayoutManager = new ViewPagerLayoutManager(this, OrientationHelper.VERTICAL); rvTiktok.setLayoutManager(mViewPagerLayoutManager); + rvTiktok.setNestedScrollingEnabled(false); rvTiktok.setAdapter(mAdapter); rvTiktok.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { - + if (onGlobalLayout == -1) { + rvTiktok.scrollToPosition(position); + mCurrentPosition = position; + onGlobalLayout = 0;//只在第一次进行跳转 + } } }); mViewPagerLayoutManager.setOnViewPagerListener(new OnViewPagerListener() { @Override public void onInitComplete() { //自动播放第一条 + Log.e(TAG, "autoPlayVideo: " + "onInitComplete"); autoPlayVideo(position); } @@ -77,6 +92,7 @@ public class ActivityTikTok extends AppCompatActivity { if (mCurrentPosition == position) { return; } + Log.e(TAG, "autoPlayVideo: " + "onPageSelected"); autoPlayVideo(position); mCurrentPosition = position; } @@ -101,8 +117,53 @@ public class ActivityTikTok extends AppCompatActivity { }); } + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + Configuration config = getResources().getConfiguration(); + // 如果当前是横屏 +// if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { +// // 设为竖屏 +// this.setRequestedOrientation( +// ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); +// } +// // 如果当前是竖屏 +// if (config.orientation == Configuration.ORIENTATION_PORTRAIT) { +// // 设为横屏 +// this.setRequestedOrientation( +// ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); +// } + Log.e(TAG, "orientation: " + config.orientation); + } + + /** + * RecyclerView 移动到当前位置, + * + * @param manager 设置RecyclerView对应的manager + * @param mRecyclerView 当前的RecyclerView + * @param n 要跳转的位置 + */ + public static void MoveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int n) { + + + int firstItem = manager.findFirstVisibleItemPosition(); + int lastItem = manager.findLastVisibleItemPosition(); + if (n <= firstItem) { + mRecyclerView.scrollToPosition(n); + } else if (n <= lastItem) { + int top = mRecyclerView.getChildAt(n - firstItem).getTop(); + mRecyclerView.scrollBy(0, top); + } else { + mRecyclerView.scrollToPosition(n); + } + + } + private void autoPlayVideo(int postion) { - if (rvTiktok == null || rvTiktok.getChildAt(0) == null) { +// mViewPagerLayoutManager.scrollToPositionWithOffset(postion, 0); + View child = rvTiktok.getChildAt(0); + if (rvTiktok == null || child == null) { + Log.e(TAG, "autoPlayVideo: " + "view is null"); return; } JzvdStdAssert player = rvTiktok.getChildAt(0).findViewById(R.id.videoplayer); @@ -134,4 +195,15 @@ public class ActivityTikTok extends AppCompatActivity { } return super.onOptionsItemSelected(item); } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (null != rvTiktok) { + rvTiktok = null; + } + if (null != mAdapter) { + mAdapter = null; + } + } } diff --git a/app/src/main/java/com/uiui/videoplayer/activity/MainActivity.java b/app/src/main/java/com/uiui/videoplayer/activity/MainActivity.java index e2b8015..246acb4 100644 --- a/app/src/main/java/com/uiui/videoplayer/activity/MainActivity.java +++ b/app/src/main/java/com/uiui/videoplayer/activity/MainActivity.java @@ -8,7 +8,9 @@ import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.RecyclerView; import android.Manifest; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; @@ -45,8 +47,39 @@ public class MainActivity extends AppCompatActivity { scanTask.execute(); } + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + Configuration config = getResources().getConfiguration(); + // 如果当前是横屏 + if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { + // 设为竖屏 + mManager = new RecycleGridLayoutManager(MainActivity.this, 2); + recyclerView.setLayoutManager(mManager); +// MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + // 如果当前是竖屏 + if (config.orientation == Configuration.ORIENTATION_PORTRAIT) { + // 设为横屏 + mManager = new RecycleGridLayoutManager(MainActivity.this, 3); + recyclerView.setLayoutManager(mManager); +// MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + } + private void initView() { recyclerView = findViewById(R.id.recyclerView); + int orientation = getResources().getConfiguration().orientation; + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + mManager = new RecycleGridLayoutManager(MainActivity.this, 3); + } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { + mManager = new RecycleGridLayoutManager(MainActivity.this, 2); + } + recyclerView.setLayoutManager(mManager); + recyclerView.setNestedScrollingEnabled(false); + recyclerView.addItemDecoration(new SpacesItemDecoration(getResources().getDimensionPixelSize(R.dimen.PX1x), getResources().getDimensionPixelSize(R.dimen.PX1x), + getResources().getDimensionPixelSize(R.dimen.PX1x), getResources().getDimensionPixelSize(R.dimen.PX1x))); + ((DefaultItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); } // private String[] getFolder(String folderPath) { @@ -90,7 +123,7 @@ public class MainActivity extends AppCompatActivity { } private static final String[] extension = new String[]{ - ".3gp", ".flv", ".mkv", ".mov", ".mp4", ".webm" + ".3gp", ".avi", ".flv", ".mkv", ".mov", ".mp4", ".webm" }; private static boolean isVideoFormat(String filePath) { @@ -154,12 +187,6 @@ public class MainActivity extends AppCompatActivity { super.onPostExecute(strings); Log.e("ScanTask", "onPostExecute: " + strings); adapter = new VideoAdapter(MainActivity.this, strings); - mManager = new RecycleGridLayoutManager(MainActivity.this, 2); - recyclerView.setLayoutManager(mManager); - recyclerView.setNestedScrollingEnabled(false); - recyclerView.addItemDecoration(new SpacesItemDecoration(getResources().getDimensionPixelSize(R.dimen.PX1x), getResources().getDimensionPixelSize(R.dimen.PX1x), - getResources().getDimensionPixelSize(R.dimen.PX1x), getResources().getDimensionPixelSize(R.dimen.PX1x))); - ((DefaultItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); // recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); recyclerView.setAdapter(adapter); } diff --git a/app/src/main/java/com/uiui/videoplayer/adapter/VideoAdapter.java b/app/src/main/java/com/uiui/videoplayer/adapter/VideoAdapter.java index ce739b8..af7a875 100644 --- a/app/src/main/java/com/uiui/videoplayer/adapter/VideoAdapter.java +++ b/app/src/main/java/com/uiui/videoplayer/adapter/VideoAdapter.java @@ -1,11 +1,14 @@ package com.uiui.videoplayer.adapter; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.media.Image; import android.media.MediaMetadataRetriever; import android.os.AsyncTask; +import android.os.Build; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -21,9 +24,12 @@ import com.bumptech.glide.Glide; import com.uiui.videoplayer.R; import com.uiui.videoplayer.activity.ActivityTikTok; import com.uiui.videoplayer.utils.ToastUtil; +import com.uiui.videoplayer.utils.Utils; import java.io.File; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import io.reactivex.Observable; @@ -33,6 +39,7 @@ import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; +import wseemann.media.FFmpegMediaMetadataRetriever; public class VideoAdapter extends RecyclerView.Adapter { private Context mContext; @@ -52,6 +59,11 @@ public class VideoAdapter extends RecyclerView.Adapter this.videoPath = path; } + private static class VideoResult { + long time; + Bitmap frame; + } + @NonNull @Override public VideoHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { @@ -70,27 +82,37 @@ public class VideoAdapter extends RecyclerView.Adapter // Glide.with(holder.video_image).load(bitmap).into(holder.video_image); // } // }; - Observable.create(new ObservableOnSubscribe() { + Observable.create(new ObservableOnSubscribe() { @Override - public void subscribe(ObservableEmitter emitter) throws Exception { - MediaMetadataRetriever mmr = new MediaMetadataRetriever(); + public void subscribe(ObservableEmitter emitter) throws Exception { + FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever(); mmr.setDataSource(path); - String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); + String duration = mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION); + Bitmap bitmap = mmr.getFrameAtTime();//获得视频第一帧的Bitmap对象. Long time = Long.valueOf(duration); - Bitmap bitmap = mmr.getFrameAtTime();//获得视频第一帧的Bitmap对象 - emitter.onNext(bitmap); + + mmr.release(); + VideoResult result = new VideoResult(); + result.frame = bitmap; + result.time = time; + emitter.onNext(result); } }).subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer() { + .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { } @Override - public void onNext(Bitmap bitmap) { - Glide.with(holder.video_image).load(bitmap).into(holder.video_image); + public void onNext(VideoResult result) { + try { + Glide.with(holder.video_image).load(result.frame).into(holder.video_image); + holder.duration.setText(Utils.TimeFormat(result.time)); + } catch (Exception e) { + + } } @Override @@ -106,6 +128,7 @@ public class VideoAdapter extends RecyclerView.Adapter // this.listener = bitmapRetultListener; holder.title.setText(getFileName(path)); + Log.e("title:", holder.title.getText().toString()); } holder.root.setOnClickListener(new View.OnClickListener() { @Override @@ -125,18 +148,35 @@ public class VideoAdapter extends RecyclerView.Adapter } private String getFileName(String path) { - return path.substring(path.lastIndexOf("/") + 1); + String name = path.substring(path.lastIndexOf("/") + 1); + Log.e("getFileName", "Name: " + name); + return name; + } + + /** + * 判断Activity是否Destroy + * + * @param mActivity + * @return + */ + public static boolean isDestroy(Activity mActivity) { + if (mActivity == null || mActivity.isFinishing() || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && mActivity.isDestroyed())) { + return true; + } else { + return false; + } } static class VideoHolder extends RecyclerView.ViewHolder { ImageView video_image; - TextView title; + TextView title, duration; ConstraintLayout root; public VideoHolder(@NonNull View itemView) { super(itemView); video_image = itemView.findViewById(R.id.video_image); title = itemView.findViewById(R.id.title_text); + duration = itemView.findViewById(R.id.duration); root = itemView.findViewById(R.id.root); } diff --git a/app/src/main/java/com/uiui/videoplayer/utils/Utils.java b/app/src/main/java/com/uiui/videoplayer/utils/Utils.java new file mode 100644 index 0000000..5144767 --- /dev/null +++ b/app/src/main/java/com/uiui/videoplayer/utils/Utils.java @@ -0,0 +1,22 @@ +package com.uiui.videoplayer.utils; + +public class Utils { + public static String TimeFormat(long millisecond) { + int ss = 1000; + int mi = ss * 60; + int hh = mi * 60; + + long hour = (millisecond) / hh; + long minute = (millisecond - hour * hh) / mi; + long second = (millisecond - hour * hh - minute * mi) / ss; + + String strHour = hour < 10 ? "0" + hour : "" + hour; + String strMinute = minute < 10 ? "0" + minute : "" + minute; + String strSecond = second < 10 ? "0" + second : "" + second; + if (hour > 0) { + return strHour + ":" + strMinute + ":" + strSecond; + } else { + return strMinute + ":" + strSecond; + } + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml similarity index 100% rename from app/src/main/res/layout/activity_main.xml rename to app/src/main/res/layout-land/activity_main.xml diff --git a/app/src/main/res/layout/activity_tiktok.xml b/app/src/main/res/layout-land/activity_tiktok.xml similarity index 100% rename from app/src/main/res/layout/activity_tiktok.xml rename to app/src/main/res/layout-land/activity_tiktok.xml diff --git a/app/src/main/res/layout-port/activity_main.xml b/app/src/main/res/layout-port/activity_main.xml new file mode 100644 index 0000000..4e82778 --- /dev/null +++ b/app/src/main/res/layout-port/activity_main.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-port/activity_tiktok.xml b/app/src/main/res/layout-port/activity_tiktok.xml new file mode 100644 index 0000000..3fb6c33 --- /dev/null +++ b/app/src/main/res/layout-port/activity_tiktok.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_videofile.xml b/app/src/main/res/layout/item_videofile.xml index 605d3bc..3cf68d7 100644 --- a/app/src/main/res/layout/item_videofile.xml +++ b/app/src/main/res/layout/item_videofile.xml @@ -12,18 +12,32 @@ android:layout_height="162dp" android:layout_marginTop="4dp" android:adjustViewBounds="true" + android:background="@color/black" android:scaleType="fitCenter" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + +