Skip to content

Commit 90189f0

Browse files
Merge pull request #1 from smartdevelopers-ir/new_video_view
New video view
2 parents 427885e + d85b307 commit 90189f0

29 files changed

+3330
-880
lines changed

SmartFileBrowser/build.gradle

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ android {
3131
}
3232
}
3333
group = 'ir.smartdevelopers'
34-
version = '1.3.0'
34+
version = '1.4.0'
3535
task sourcesJar(type: Jar) {
3636
archiveClassifier.set("sources")
3737
from android.sourceSets.main.java.srcDirs
@@ -42,23 +42,22 @@ task javadocJar2(type: Jar) {
4242
}
4343
dependencies {
4444

45-
implementation 'androidx.appcompat:appcompat:1.3.1'
45+
implementation 'androidx.appcompat:appcompat:1.4.0'
4646
implementation 'com.google.android.material:material:1.4.0'
47-
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
47+
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
4848
implementation 'com.github.bumptech.glide:glide:4.12.0'
49+
4950
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
50-
// implementation 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:3.0.0'
5151
implementation 'com.aurelhubert:ahbottomnavigation:2.3.4'
52-
// implementation 'com.ashokvarma.android:bottom-navigation-bar:2.2.0'
5352
def lifecycle_version = "2.4.0"
5453
// ViewModel
5554
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
5655
// LiveData
5756
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
58-
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
59-
implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"
60-
implementation 'com.github.smartdevelopers-ir:PhotoEditor:1.1.0'
57+
58+
implementation 'com.github.smartdevelopers-ir:PhotoEditor:1.1.3'
6159
// implementation 'ir.smartdevelopers:photo-editor:1.1.0'
60+
6261
}
6362
afterEvaluate{
6463
publishing {

SmartFileBrowser/src/main/AndroidManifest.xml

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,34 @@
1212
tools:ignore="ScopedStorage" />
1313
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
1414

15+
<queries>
16+
<intent>
17+
<action android:name="android.media.action.IMAGE_CAPTURE" />
18+
</intent>
19+
</queries>
20+
1521
<application android:requestLegacyExternalStorage="true">
22+
<activity
23+
android:name=".acitivties.VideoViewActivity"
24+
android:exported="false"
25+
android:theme="@style/sfb_EditorTheme"
26+
android:screenOrientation="locked"
27+
/>
1628
<activity
1729
android:name=".acitivties.PhotoEditorActivity"
1830
android:exported="false"
1931
android:theme="@style/sfb_EditorTheme"
32+
android:screenOrientation="locked"
2033
/>
2134
<activity
2235
android:name=".acitivties.FileBrowserMainActivity"
2336
android:configChanges="keyboard|orientation"
24-
android:theme="@style/sfb_AppTheme" />
25-
<!-- <activity-->
26-
<!-- android:name="iamutkarshtiwari.github.io.ananas.editimage.EditImageActivity"-->
27-
<!-- android:exported="true"-->
28-
<!-- android:label="@string/sfb_image_editor_label"-->
29-
<!-- android:theme="@style/sfb_EditorTheme"-->
30-
<!-- tools:replace="android:label" />-->
31-
37+
android:theme="@style/sfb_AppTheme" /> <!-- <activity -->
38+
<!-- android:name="iamutkarshtiwari.github.io.ananas.editimage.EditImageActivity" -->
39+
<!-- android:exported="true" -->
40+
<!-- android:label="@string/sfb_image_editor_label" -->
41+
<!-- android:theme="@style/sfb_EditorTheme" -->
42+
<!-- tools:replace="android:label" /> -->
3243
<provider
3344
android:name=".customClasses.SmartFileProvider"
3445
android:authorities="${applicationId}.sfb_provider"

SmartFileBrowser/src/main/java/ir/smartdevelopers/smartfilebrowser/acitivties/FileBrowserMainActivity.java

Lines changed: 522 additions & 190 deletions
Large diffs are not rendered by default.

SmartFileBrowser/src/main/java/ir/smartdevelopers/smartfilebrowser/acitivties/PhotoEditorActivity.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,9 @@
4343

4444
public class PhotoEditorActivity extends AppCompatActivity {
4545

46-
public static final String KEY_PHOTO_URI = "photo_uri";
4746
public static final String KEY_TRANSITION_NAME = "transition_name";
4847
public static final String KEY_SAVE_PATH = "save_path";
49-
public static final String KEY_IS_EDITED = "is_edited";
50-
public static final String KEY_THUMBNAIL = "thumbnail";
48+
5149

5250
private PhotoEditorFragment mPhotoEditorFragment;
5351
private ImageButton btnDone;
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
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+
}

SmartFileBrowser/src/main/java/ir/smartdevelopers/smartfilebrowser/adapters/FileBrowserAdapter.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,23 @@ public FileBrowserAdapter(List<File> selectedFiles) {
4848
}
4949

5050
public void setList(List<FileBrowserModel> fileBrowserModels) {
51+
// notifyItemRangeRemoved(0,mFileBrowserModelsCopy.size());
5152
mFileBrowserModels = fileBrowserModels;
5253
mFileBrowserModelsCopy = fileBrowserModels;
54+
// notifyItemRangeInserted(0,mFileBrowserModelsCopy.size());
5355
notifyDataSetChanged();
5456
}
5557

58+
@Override
59+
public void setHasStableIds(boolean hasStableIds) {
60+
super.setHasStableIds(true);
61+
}
62+
63+
@Override
64+
public long getItemId(int position) {
65+
return mFileBrowserModels.get(position).getId();
66+
}
67+
5668
@NonNull
5769
@Override
5870
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@@ -375,4 +387,7 @@ void bindView(FileBrowserModel model) {
375387
txtTitle.setText(model.getTitle());
376388
}
377389
}
390+
public void setSelectedFiles(List<File> selectedFiles) {
391+
mSelectedFiles = selectedFiles;
392+
}
378393
}

0 commit comments

Comments
 (0)