-
-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add fullscreen option to in-line videos #2747
Changes from all commits
2cd1b6c
75f9a6e
b68126e
5ac6177
3aade54
b10af35
9f4f5a7
cd82dc9
d67ca37
d5f4d2b
b5d5dfb
0df8eed
5ff7cfa
7ba0f74
dd9f9e9
fa76bbc
8588645
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<LinearLayout 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" | ||
android:orientation="vertical" | ||
android:gravity="center"> | ||
|
||
<org.commcare.views.media.CommCareVideoView | ||
android:id="@+id/fullscreen_video_view" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" | ||
android:layout_gravity="center" /> | ||
</LinearLayout> |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package org.commcare.activities | ||
|
||
import android.content.Intent | ||
import android.os.Bundle | ||
import androidx.appcompat.app.AppCompatActivity | ||
import org.commcare.dalvik.databinding.ActivityFullscreenVideoViewBinding | ||
import org.commcare.views.media.CommCareMediaController | ||
|
||
/** | ||
* Activity to view inline videos in fullscreen mode, it returns the last time position to the | ||
* calling activity | ||
* | ||
* @author avazirna | ||
*/ | ||
class FullscreenVideoViewActivity : AppCompatActivity() { | ||
|
||
private lateinit var viewBinding: ActivityFullscreenVideoViewBinding | ||
private var lastPosition = -1 | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
viewBinding = ActivityFullscreenVideoViewBinding.inflate(layoutInflater) | ||
setContentView(viewBinding.root) | ||
|
||
// Get video URI from intent, crash if no URI is available | ||
intent.data?.let { viewBinding.fullscreenVideoView.setVideoURI(intent.data) } | ||
?: throw RuntimeException("Video file not found!"); | ||
lastPosition = restoreLastPosition(savedInstanceState) | ||
|
||
viewBinding.fullscreenVideoView.setMediaController(CommCareMediaController(this, true)) | ||
viewBinding.fullscreenVideoView.setOnPreparedListener { | ||
if (lastPosition != -1) { | ||
viewBinding.fullscreenVideoView.seekTo(lastPosition) | ||
} | ||
viewBinding.fullscreenVideoView.start() | ||
} | ||
} | ||
|
||
override fun onSaveInstanceState(outState: Bundle) { | ||
super.onSaveInstanceState(outState) | ||
if (lastPosition != -1) { | ||
outState.putInt(CommCareMediaController.INLINE_VIDEO_TIME_POSITION, lastPosition) | ||
} | ||
} | ||
|
||
override fun onPause() { | ||
super.onPause() | ||
if (viewBinding.fullscreenVideoView != null) { | ||
viewBinding.fullscreenVideoView.pause() | ||
lastPosition = viewBinding.fullscreenVideoView.currentPosition | ||
} | ||
} | ||
|
||
override fun onBackPressed() { | ||
setResultIntent() | ||
super.onBackPressed() | ||
} | ||
|
||
private fun setResultIntent() { | ||
val i = Intent() | ||
i.putExtra( | ||
CommCareMediaController.INLINE_VIDEO_TIME_POSITION, | ||
viewBinding.fullscreenVideoView.currentPosition | ||
) | ||
this.setResult(RESULT_OK, i) | ||
} | ||
|
||
override fun onDestroy() { | ||
super.onDestroy() | ||
viewBinding.fullscreenVideoView.stopPlayback() | ||
} | ||
|
||
// priority is given to lastPosition saved state | ||
private fun restoreLastPosition(savedInstanceState: Bundle?): Int { | ||
val intentExtras = intent.extras | ||
if (savedInstanceState != null && | ||
savedInstanceState.containsKey(CommCareMediaController.INLINE_VIDEO_TIME_POSITION)) { | ||
return savedInstanceState.getInt(CommCareMediaController.INLINE_VIDEO_TIME_POSITION) | ||
} else if (intentExtras != null && | ||
intentExtras.containsKey(CommCareMediaController.INLINE_VIDEO_TIME_POSITION)) { | ||
return intentExtras.getInt(CommCareMediaController.INLINE_VIDEO_TIME_POSITION) | ||
} | ||
return -1 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,56 @@ | ||
package org.commcare.views.media; | ||
|
||
import android.app.Activity; | ||
import android.content.Context; | ||
import android.content.Intent; | ||
import android.util.AttributeSet; | ||
import android.view.Gravity; | ||
import android.view.View; | ||
import android.view.ViewGroup; | ||
import android.widget.FrameLayout; | ||
import android.widget.ImageButton; | ||
import android.widget.MediaController; | ||
|
||
import androidx.appcompat.app.AppCompatActivity; | ||
|
||
import org.commcare.activities.FullscreenVideoViewActivity; | ||
import org.commcare.activities.components.FormEntryConstants; | ||
import org.commcare.dalvik.R; | ||
import org.commcare.utils.AndroidUtil; | ||
import org.commcare.utils.FileUtil; | ||
|
||
import java.io.File; | ||
|
||
/** | ||
* Custom MediaController which provides a workaround to the issue where hide and show aren't working while adding it in the view hierarchy. | ||
* Custom MediaController which provides a workaround to the issue where hide and show aren't | ||
* working while adding it in the view hierarchy. | ||
* Note: Use only when you're manually adding MediaController in the view hierarchy. | ||
* Used here {@link MediaLayout} | ||
* @author $|-|!˅@M | ||
*/ | ||
public class CommCareMediaController extends MediaController { | ||
|
||
public static final String INLINE_VIDEO_TIME_POSITION = "inline-video-time-position"; | ||
|
||
// A mock to superclass' isShowing property. | ||
// {@link https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/MediaController.java#96} | ||
private boolean _isShowing = false; | ||
private ImageButton fullscreenBtn; | ||
private boolean fullscreenMode; | ||
shubham1g5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public CommCareMediaController(Context context, AttributeSet attrs) { | ||
public CommCareMediaController(Context context, AttributeSet attrs, boolean fullscreenMode) { | ||
super(context, attrs); | ||
this.fullscreenMode = fullscreenMode; | ||
} | ||
|
||
public CommCareMediaController(Context context, boolean useFastForward) { | ||
public CommCareMediaController(Context context, boolean useFastForward, boolean fullscreenMode) { | ||
super(context, useFastForward); | ||
this.fullscreenMode = fullscreenMode; | ||
} | ||
|
||
public CommCareMediaController(Context context) { | ||
public CommCareMediaController(Context context, boolean fullscreenMode) { | ||
super(context); | ||
this.fullscreenMode = fullscreenMode; | ||
} | ||
|
||
@Override | ||
|
@@ -50,4 +73,49 @@ public void hide() { | |
ViewGroup parent = (ViewGroup) this.getParent(); | ||
parent.setVisibility(View.GONE); | ||
} | ||
|
||
@Override | ||
public void setAnchorView(View view) { | ||
super.setAnchorView(view); | ||
|
||
int videoViewId = fullscreenMode ? R.id.fullscreen_video_view : R.id.inline_video_view; | ||
CommCareVideoView videoView = view.findViewById(videoViewId); | ||
|
||
if (videoView != null) { | ||
addFullscreenButton(videoView); | ||
} | ||
} | ||
|
||
private void addFullscreenButton(CommCareVideoView videoView) { | ||
if (fullscreenBtn == null) { | ||
fullscreenBtn = new ImageButton(getContext(), null, R.style.FullScreenVideoButton); | ||
fullscreenBtn.setId(AndroidUtil.generateViewId()); | ||
if (fullscreenMode) { | ||
fullscreenBtn.setImageResource(R.drawable.ic_media_exit_fullscreen); | ||
} else { | ||
fullscreenBtn.setImageResource(R.drawable.ic_media_fullscreen); | ||
} | ||
fullscreenBtn.setOnClickListener(view1 -> { | ||
// if in fullscreen mode, we exit | ||
if (fullscreenMode) { | ||
Intent i = new Intent(); | ||
i.putExtra(CommCareMediaController.INLINE_VIDEO_TIME_POSITION, videoView.getCurrentPosition()); | ||
((AppCompatActivity)getContext()).setResult(Activity.RESULT_OK, i); | ||
((AppCompatActivity)getContext()).finish(); | ||
} else { | ||
Intent intent = new Intent(getContext(), FullscreenVideoViewActivity.class); | ||
intent.setData(FileUtil.getUriForExternalFile(getContext(), | ||
new File(videoView.getVideoPath()))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should explicitly validate videoView.getVideoPath() is not null and crash with an exception otherwise. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The validation of the of the video path happens before the instantiation of the CommCareMediaController, so this branch would only be executed if the file exists. |
||
if (videoView.isPlaying()) { | ||
intent.putExtra(INLINE_VIDEO_TIME_POSITION, videoView.getCurrentPosition()); | ||
} | ||
((AppCompatActivity) getContext()).startActivityForResult(intent, | ||
FormEntryConstants.VIEW_VIDEO_FULLSCREEN); | ||
} | ||
}); | ||
} | ||
FrameLayout.LayoutParams frameParams = new LayoutParams(LayoutParams.WRAP_CONTENT, | ||
LayoutParams.WRAP_CONTENT, Gravity.END); | ||
this.addView(fullscreenBtn, frameParams); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we keep the sizes in multiples of
8
here (reasoning)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same style being used by the Android's internal Media controller widgets, I kept the same dimensions to ensure consistency. But I don't think changing them will have an impact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good in that case.