I implemented a e-Reader that has embedded video players on it, I need a option to toggle fullscreen mode from the player.
My question is the following:
Which is the best way to play a video on fullscreen and let the user come back from this state to the page he is reading before and also keep the current time of the video.
Another complicated situation I need to handle is:
There's different visualizations of a page on portrait and landscape, if the user toggle fullscreen on portrait and rotate the device, the video should go to landscape mode and rescale the video to fit the screen, but if the user goes back from this page he should return to portrait once again.
I'm able to give more info if needed.
Thanks in advance
I can recommend using Activity with VideoView in layout.
You can save position on orientation change like this
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mVideoView.isPlaying()) outState.putInt("pos", mVideoView.getCurrentPosition());
}
Then restore position and resume playing in onCreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.video);
mVideoView = (VideoView) findViewById(R.id.video);
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(mVideoView);
mVideoView.setMediaController(mediaController);
mVideoView.setOnCompletionListener(this);
Intent intent = getIntent();
path = intent.getExtras().getString("path");
int pos = 0;
if (savedInstanceState != null) {
pos = savedInstanceState.getInt("pos");
}
playVideoFromPos(pos);
}
Related
I have a dialog (that contains a video player by ExoPlayer) that is created like this:
dialog = new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
#Override
public void onBackPressed() {
if (exoPlayerFullscreen)
closeFullscreenDialog();
super.onBackPressed();
}
};
This way, the video is showed in landscape mode but not in fullscreen. If I remove setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE), the video is played in fullscreen but in portrait mode. How can I get the video show up in both (fullscreen and landscape mode)?
Thank you.
Make a cool icon and on the click of the icon change the orientation at runTime. .
#Override
onClick(View v) {
if(flag_landscape)
setRequestedOrientation(ActivityInfo
.SCREEN_ORIENTATION_LANDSCAPE);
else
setRequestedOrientation(ActivityInfo
.SCREEN_ORIENTATION_PORTRAIT);
}
I have a video url, which I can play with whatever player or VideoView. But here is what I am trying to do.
There is RecyclerView in which each element contains a video's title and thumbnails. When user clicks on the video a popup window appear. This popup window contains a VideoView (or whatever can play a video from url) and plays the video. The user can drag this window around. The trick is to make it so, that if user presses the back button the current activity closes, the window should remain and continue playing the video. While the video is being played the user can do whatever he wants in other apps, while the window with the video remains on top and continues to play the video. At any time user can press on the window (or on button in it) and video will become fullscreen. At the time user decides to play fullscreen the app activity might not be there.
Something like I described above is implemented in this app
https://play.google.com/store/apps/details?id=com.djit.apps.stream&hl=en
I can create a window with a view which will remain there when the user closes the app activity. For this purpose I use this library
https://github.com/pingpongboss/StandOut
If you check the source code of the lib you will see that StandOutWindow is Service which creates a popup window.
I actually can play a video in this window. Here is my window class
public class FloatingWindow extends StandOutWindow {
private static final int WIDTH = 400;
private static final int HEIGHT = 361;
/*
I didn't think of a better way to set video url
therefore I made it static and set it with a static method
I know it is bad, but it works.
I will do it another way later
Now I have other issues
*/
private static String videoUrl = null;
public static void setVideoUrl(String videoUrl) {
FloatingWindow.videoUrl = videoUrl;
}
#Override
public String getAppName() {
return getApplicationContext().getResources().getString(R.string.app_name);
}
#Override
public int getAppIcon() {
return android.R.drawable.ic_menu_close_clear_cancel;
}
#Override
public void createAndAttachView(int id, FrameLayout frame) {
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.floating_window, frame, true);
/*
As you can see I didn't use MediaController for this videoView
VideoView works with it, except for device
On this one device MediaController crashed the app with BadTokenException: token null is not valid, is your activity running
*/
final VideoView videoView = (VideoView) view.findViewById(R.id.textureVideoView);
final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.videoProgressBar);
final ScrollView description = (ScrollView) view.findViewById(R.id.videoDescription);
videoView.setVideoURI(Uri.parse(videoUrl));
videoView.requestFocus();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
videoView.start();
/*
I don't want my video view to be visible until it is ready
Because while it is preparing it gets transparent
But I want a progress bar instead
Therefore initially set its dimensions to 1x1 and change the size when it's ready
*/
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER;
videoView.setLayoutParams(params);
progressBar.setVisibility(View.GONE);
}
});
/*
When the activity is not present VideoView crashes when clicked
To avoid crash I overrided setOnTouchListener method and return true from it
*/
videoView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
if (videoView.isPlaying()) {
videoView.pause();
} else {
videoView.start();
}
}
return true;
}
});
}
#Override
public StandOutLayoutParams getParams(int id, Window window) {
return new StandOutLayoutParams(id, WIDTH, HEIGHT,
StandOutLayoutParams.CENTER, StandOutLayoutParams.CENTER);
}
#Override
public int getFlags(int id) {
return super.getFlags(id)
| StandOutFlags.FLAG_BODY_MOVE_ENABLE
| StandOutFlags.FLAG_WINDOW_FOCUSABLE_DISABLE
| StandOutFlags.FLAG_DECORATION_SYSTEM
| StandOutFlags.FLAG_ADD_FUNCTIONALITY_DROP_DOWN_DISABLE
| StandOutFlags.FLAG_DECORATION_CLOSE_DISABLE;
}
#Override
public String getPersistentNotificationMessage(int id) {
return "Click here to close floating window";
}
#Override
public Intent getPersistentNotificationIntent(int id) {
return StandOutWindow.getCloseIntent(this, FloatingWindow.class, id);
}
}
The code above works, but there are several problems with it.
I tested it on three devices and emulator and it worked. But there is a device at which it crashed at first. I remove MediaController and now it almost works. When user changes the size of the window the VideoView size gets weird. Perhaps I should test the device, on which the code does not work for Android compatibility. But, anyway maybe how I am doing the windowed player is wrong and you know a better way.
I have to set the size of the VideoView to 1x1 and then change it, I cannot make it normal size right away, because if I do it the area in the window where VideoView should be becomes transparent until the video is loaded. Also I cannot click on the VideoView and let the system process the click event. If I do it I get BadTokenException: token null is not valid, is your activity running. The activity is not running, therefore I have to process the click event myself to prevent the crash. These hacks make me think that I am doing it wrong.
I cannot think of a way to make video fullscreen. The only thing I thought of is to start a fullscreen activity and pass url and video position to it. Maybe this is the way to go. In this case the user will have to wait for video to load again when (s)he hits the fullscreen button. Plus I have no idea how the window will behave when fullscreen activity is started.
It feels like video was not intended to be played without activity. Maybe there is way to make this window player in such a way that there is always an invisible activity which would miss all the touch events and pass them down to the activity stack. And such an activity could be used for video playback.
You can make it to full screen by inflating the layout with these dimensions:
LayoutParams.y = getApplicationContext().getResources().getDisplayMetrics().heightPixels
LayoutParams.x = getApplicationContext().getResources().getDisplayMetrics().widthPixels
Here's my MAIN ACTIVITY
public static boolean popupStatus=false;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null){
popupStatus = savedInstanceState.getBoolean("Open");
}
setContentView(R.layout.main);
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean("Open", DateTimePicker.openPopup);
super.onSaveInstanceState(savedInstanceState);
}
I have DateTimePicker.java class which has 1 button and 1 Textview. Clicking on button, my another class Calendar.java get populated in PopupWindow and this Popup window displays my class Calendar.java . I have created different layouts of my Calendar.java class for portrait and landscape mode. Here's DateTimePicker.java some snippet of code,
public static boolean openPopup = false;
textView = new TextView(this.getContext());
this.addView(textView, layoutParams);
button = new Button(this.getContext());
button.setText("C");
this.addView(button, layoutParams1);
button.setOnClickListener(this);
if(Main.popupStatus){
button.performClick();
}
public void onClick(View v) {
if(Main.popupStatus){
new Handler().postDelayed(new Runnable() {
public void run() {
openCalendar();
}
}, 100);
}
else{
openCalendar();
}
private void openCalendar() {
Calendar calendar = new Calendar(this.getContext());
if(portrait.equals(orientation)){
pw = new PopupWindow(calendarLayout, 245, 284, true);
}
else{
pw = new PopupWindow(calendarLayout, 295, 240, true);
}
pw.setOutsideTouchable(false);
pw.showAtLocation(this, Gravity.NO_GRAVITY, 10, 80);
openPopup = true;
}
public void closeCalendar(){
pw.dismiss();
openPopup = false;
}
Main.XML contain DateTimePicker .
Actually I wanted my Popup window to be opened up even when orientation gets changed at run time, so I have done it through setting flag openPopup = true; in openCalendar() method and if it is opened and orientation gets changed at run time, this flag will be saved in onSaveInstanceState() method. After orientation will change, it will be checked in onCreate() and popup will be opened up for respective orientation mode. I hope you got my point.
PROBLEM: Initially When I click on button in Portrait mode, popup window pops up for portrait layout. then without dismissing popup window, I change the orientation to landscape. And after changing, I can see my popup window as intact and appears on screen of landscape layout. Till now it works fine. But IF popup window is opened up in landscape mode and then I change the orientation to portrait, popup window of portrait layout didn't come up and I see FORCE CLOSE message:/ Please help since I am working behind it so long and getting no clue. I would be very grateful to you all. Thanks!
P.S.: Changing orientation means I am pressing ctrl+F11 and changing orientation of Emulator
The emulator has an odd feature (some consider it a bug) in which changing from landscape to portrait in the emulator causes two configuration changes and two restarts of your activity. (One configuration change is the orientation and the other is an emulated change in the keyboard state.) The timing of the configuration changes frequently causes crashes like this. Try adding this attribute:
android:configChanges="keyboard|keyboardHidden"
to your <activity> tag in the manifest. See if that improves the situation.
Make sure you have your layout defined in layout-land folder and ensure onCreate is not called again and again. android:configChanges="keyboard|keyboardHidden" Put this in your manifest file so that the state is retained when you change orientation
I am having trouble with audio in Android. Here is the deal, I have a very simple splash screen. My intention is once the screen loads it will play a very small audio file.
The problem is that a lot of the time, the audio will play before the splash screen actually appears.
Is there a way programmatically to verify that the screen has loaded? I do not want to add an unnecessary timer to make sure the sound doesn't play before it loads. And I want the sound to play at the exact moment the screen appears.
Here is a snippet from my xml file:
<ImageView
android:src="#drawable/splash"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
splash is a .png image
And here is the onCreate code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.scarysplash);
mpPlaySound = MediaPlayer.create(this, R.raw.scream1);
mpPlaySound.start();
}
}
Thanks in advance for your help!
you are not the only only one who has similar problem:)) There are couple of ways how to do that, the popular one is to implement OnGlobalLayoutListener(), e.g.:
View yourView = ...;
yourView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener()
{
// -----------------------------------------
//
// Callback method to be invoked when the
// global layout state or the visibility
// of views within the view tree changes
//
// -----------------------------------------
#Override
public void onGlobalLayout()
{
// Remove view
View yourView = findViewById( R.id.yourId );
if ( yourView != null )
{
yourView .getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
// PLAY SOUND
}
});
Petr
I have a problem preserving the current scroll position of content loaded in Android's WebView control during orientation changes. The issue currently exist only in Android 2.1 and Android 2.1 Update 1
The code that I use is based on the default Browser application and looks like this:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mWebView = new WebView(this);
setContentView(mWebView);
mWebView.setWebViewClient(mWebViewClient);
if (savedInstanceState != null)
{
final WebBackForwardList list = mWebView.restoreState(savedInstanceState);
if (list == null)
return;
if (savedInstanceState.containsKey("currentPicture"))
{
final File f = new File(savedInstanceState.getString("currentPicture"));
mWebView.restorePicture(savedInstanceState, f);
f.delete();
}
}else
mWebView.loadUrl("http://slashdot.org/");
}
#Override
protected void onSaveInstanceState(Bundle outState)
{
final WebBackForwardList list = mWebView.saveState(outState);
File mThumbnailDir = getDir("thumbnails", 0);
if (list != null)
{
final File f = new File(mThumbnailDir, mWebView.hashCode() + "_pic.save");
if (mWebView.savePicture(outState, f))
outState.putString("currentPicture", f.getPath());
}
}
This code works in Android 1.5, 1.6 and 2.0.1. In Android 2.1 the same code restores the position for a split second but then the page reloads and scrolls to position 0,0.
In Android 2.1 Update 1, it not only scrolls back to 0,0, but also changes the Zoom to fit the page width (similar to the browser Overview mode introduced in 2.1)
Does anyone know of a workaround or has any idea what may cause such behavior?
Just load the WebViewState in onRestoreInstanceState.
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
myWebView.restoreState(savedInstanceState);
}
Changing the orientation from landscape to portrait or vise-versa, it starts the new activity. Hence you the open as refreshed activity.
Put the the code in your AndroidManifest.xml and reload app.
"activity android:name=".Main
android:configChanges="orientation"
in activity tab. Thanks