1+ package ir .smartdevelopers .smartfilebrowser .acitivties ;
2+
3+ import static ir .smartdevelopers .smartfilebrowser .customClasses .Utils .formatTime ;
4+
5+ import androidx .annotation .NonNull ;
6+ import androidx .annotation .Nullable ;
7+ import androidx .appcompat .app .AppCompatActivity ;
8+ import androidx .appcompat .widget .AppCompatImageView ;
9+ import androidx .appcompat .widget .AppCompatSeekBar ;
10+ import androidx .appcompat .widget .AppCompatTextView ;
11+ import androidx .core .app .ActivityCompat ;
12+ import androidx .core .app .SharedElementCallback ;
13+ import androidx .core .view .ViewCompat ;
14+
15+ import android .annotation .SuppressLint ;
16+ import android .content .res .Configuration ;
17+ import android .graphics .Bitmap ;
18+ import android .graphics .Color ;
19+ import android .graphics .drawable .Drawable ;
20+ import android .media .MediaMetadataRetriever ;
21+ import android .media .MediaPlayer ;
22+ import android .media .ThumbnailUtils ;
23+ import android .net .Uri ;
24+ import android .os .Build ;
25+ import android .os .Bundle ;
26+ import android .os .Handler ;
27+ import android .os .Looper ;
28+ import android .os .PersistableBundle ;
29+ import android .provider .MediaStore ;
30+ import android .transition .Transition ;
31+ import android .transition .TransitionInflater ;
32+ import android .util .Log ;
33+ import android .view .MotionEvent ;
34+ import android .view .View ;
35+ import android .view .Window ;
36+ import android .widget .ImageView ;
37+ import android .widget .MediaController ;
38+ import android .widget .TextView ;
39+ import android .widget .VideoView ;
40+ import com .google .android .material .slider .LabelFormatter ;
41+ import com .google .android .material .slider .Slider ;
42+ import java .util .Locale ;
43+ import ir .smartdevelopers .smartfilebrowser .R ;
44+
45+ public class VideoViewActivity extends AppCompatActivity {
46+
47+ public static final String KEY_TRANSITION_NAME ="transition_name" ;
48+ private Uri mVideoUri ;
49+ private ImageView imgThumbnailHolder ;
50+
51+ private VideoView mVideoView ;
52+ private boolean isExiting =false ;
53+ private AppCompatImageView btnPlay ;
54+ private AppCompatTextView txtVideoLength ,txtCurrentTime ;
55+ private Runnable mTimerRunnable ;
56+ private Handler mTimerHandler ;
57+ private boolean isPlaying ;
58+ private Slider mSlider ;
59+ @ SuppressLint ("ClickableViewAccessibility" )
60+ @ Override
61+ protected void onCreate (Bundle savedInstanceState ) {
62+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
63+ getWindow ().requestFeature (Window .FEATURE_ACTIVITY_TRANSITIONS );
64+ Transition transition = TransitionInflater .from (this ).inflateTransition (R .transition .iten_transition_in );
65+ getWindow ().setSharedElementEnterTransition (transition );
66+ getWindow ().setSharedElementReturnTransition (transition );
67+
68+
69+ }
70+ super .onCreate (savedInstanceState );
71+ setContentView (R .layout .activity_video_view );
72+
73+ mVideoUri =getIntent ().getData ();
74+ String transitionName =getIntent ().getStringExtra (KEY_TRANSITION_NAME );
75+
76+ findViews ();
77+ initTimer ();
78+ ViewCompat .setTransitionName (imgThumbnailHolder ,transitionName );
79+
80+ btnPlay .setOnClickListener (v ->{
81+ btnPlay .setVisibility (View .GONE );
82+ mVideoView .setVisibility (View .VISIBLE );
83+ playVideo ();
84+ if (imgThumbnailHolder .getVisibility ()==View .VISIBLE ){
85+ new Handler ().postDelayed (()->{
86+ imgThumbnailHolder .setVisibility (View .INVISIBLE );
87+ },900 );
88+ }
89+
90+ });
91+
92+ mVideoView .setOnTouchListener (new View .OnTouchListener () {
93+ @ Override
94+ public boolean onTouch (View v , MotionEvent event ) {
95+ if (event .getAction ()==MotionEvent .ACTION_DOWN ){
96+ if (mVideoView .isPlaying ()){
97+ pauseVideo ();
98+ return true ;
99+ }
100+ }
101+ return false ;
102+ }
103+ });
104+
105+
106+ mVideoView .setOnCompletionListener (new MediaPlayer .OnCompletionListener () {
107+ @ Override
108+ public void onCompletion (MediaPlayer mp ) {
109+ mVideoView .seekTo (1 );
110+ btnPlay .setVisibility (View .VISIBLE );
111+ // mPlayerSeekbar.setProgress(0);
112+ mSlider .setValue (0 );
113+ isPlaying =false ;
114+ setTime (0 ,txtCurrentTime );
115+ }
116+ });
117+
118+ mVideoView .setVideoURI (mVideoUri );
119+ mVideoView .seekTo (1 );
120+
121+
122+ ActivityCompat .postponeEnterTransition (this );
123+ loadVideoThumbnail ();
124+
125+ }
126+
127+ private void initTimer () {
128+ mTimerHandler =new Handler (Looper .getMainLooper ());
129+ mTimerRunnable =new Runnable () {
130+ @ Override
131+ public void run () {
132+ if (isPlaying ){
133+ long current =mVideoView .getCurrentPosition ();
134+ setTime (current ,txtCurrentTime );
135+ mSlider .setValue (current );
136+ mTimerHandler .postDelayed (this ,100 );
137+ }
138+ }
139+ };
140+ }
141+
142+ private void setTime (long millis , TextView textView ){
143+ textView .setText (formatTime (millis ));
144+
145+ }
146+
147+ private void pauseVideo (){
148+ if (!isExiting ){
149+ btnPlay .setVisibility (View .VISIBLE );
150+ }
151+ mVideoView .pause ();
152+ isPlaying =false ;
153+ if (mTimerRunnable !=null ){
154+ mTimerHandler .removeCallbacks (mTimerRunnable );
155+ }
156+ }
157+ private void playVideo (){
158+ btnPlay .setVisibility (View .GONE );
159+ mVideoView .start ();
160+ isPlaying =true ;
161+ startTimer ();
162+ }
163+
164+ private void startTimer () {
165+ if (mTimerRunnable !=null ){
166+ mTimerHandler .removeCallbacks (mTimerRunnable );
167+ mTimerHandler .postDelayed (mTimerRunnable ,100 );
168+ }
169+
170+ }
171+
172+ private void findViews () {
173+ imgThumbnailHolder =findViewById (R .id .sfb_activity_videoView_imagePlaceHolder );
174+ mVideoView =findViewById (R .id .sfb_activity_videoView_playerView );
175+ btnPlay =findViewById (R .id .sfb_activity_videoView_imgPlayButton );
176+ txtCurrentTime =findViewById (R .id .sfb_activity_videoView_playerSeekbarCurrentTime );
177+ txtVideoLength =findViewById (R .id .sfb_activity_videoView_playerSeekbarEndTime );
178+ mSlider =findViewById (R .id .sfb_activity_videoView_playerSeekbar );
179+ mSlider .setValueFrom (0 );
180+ LabelFormatter labelFormatter =new LabelFormatter () {
181+ @ NonNull
182+ @ Override
183+ public String getFormattedValue (float value ) {
184+
185+ return formatTime ((long ) value );
186+ }
187+ };
188+ mSlider .setLabelFormatter (labelFormatter );
189+ mSlider .addOnSliderTouchListener (new Slider .OnSliderTouchListener () {
190+ boolean lastPlayingStateIsPlaying =false ;
191+ @ Override
192+ public void onStartTrackingTouch (@ NonNull Slider slider ) {
193+ lastPlayingStateIsPlaying =isPlaying ;
194+ mVideoView .pause ();
195+ isPlaying =false ;
196+ mTimerHandler .removeCallbacks (mTimerRunnable );
197+
198+ }
199+
200+ @ Override
201+ public void onStopTrackingTouch (@ NonNull Slider slider ) {
202+ mVideoView .seekTo ((int ) slider .getValue ());
203+ if (lastPlayingStateIsPlaying ){
204+ playVideo ();
205+ }
206+ }
207+ });
208+
209+ }
210+
211+ private void loadVideoThumbnail () {
212+ MediaMetadataRetriever retriever =new MediaMetadataRetriever ();
213+ retriever .setDataSource (this ,mVideoUri );
214+ Bitmap bitmap =retriever .getFrameAtTime ();
215+ imgThumbnailHolder .setImageBitmap (bitmap );
216+ String durationSt =retriever .extractMetadata (MediaMetadataRetriever .METADATA_KEY_DURATION );
217+ if (durationSt !=null ){
218+ long duration =Long .parseLong (durationSt );
219+ setTime (duration ,txtVideoLength );
220+ mSlider .setValueTo (duration );
221+ }
222+
223+ setTime (0 ,txtCurrentTime );
224+ ActivityCompat .startPostponedEnterTransition (VideoViewActivity .this );
225+ retriever .release ();
226+ }
227+
228+
229+ @ Override
230+ protected void onStart () {
231+ super .onStart ();
232+
233+ }
234+
235+ @ Override
236+ protected void onStop () {
237+
238+ if (mVideoView !=null && mVideoView .isPlaying ()){
239+ mVideoView .pause ();
240+ }
241+ isPlaying =false ;
242+ super .onStop ();
243+ }
244+
245+ @ Override
246+ protected void onDestroy () {
247+ if (mVideoView !=null ){
248+ mVideoView .stopPlayback ();
249+ }
250+ isPlaying =false ;
251+ isExiting =true ;
252+ super .onDestroy ();
253+ }
254+
255+ @ Override
256+ public void onBackPressed () {
257+ if (mVideoView !=null ){
258+ mVideoView .pause ();
259+ }
260+
261+ isPlaying =false ;
262+ imgThumbnailHolder .setVisibility (View .VISIBLE );
263+ imgThumbnailHolder .post (()->{
264+ mVideoView .setVisibility (View .GONE );
265+ });
266+ isExiting =true ;
267+ super .onBackPressed ();
268+ }
269+ }
0 commit comments