B4A Library VideoView optimized for orientation-change

This is really not a new library but a way to show how to to use VideoView optimized for orientation-change and make your VideoView-app behave more professionally.

I have seen many apps showing a VideoView in portrait-mode and when you change the orientation into landscape-mode, the video continues to play smoothly (without interruption) and at the same time the video is being resized properly from a smaller screen in order to fill up the screen properly. This works also in the other direction.

This behaviour is not easy to accomplish without using some complimentary code. Even fellow Android-developers using Android Studio/Eclipse have faced this problem.

I sat down and tried to find a solution it but it was not an easy task and it took me a lot of testing to get it working. With Android Studio it was easier but with B4A, I had to use a different approach and add some complementary code to get it working.

Therefore, I am happy to share this project with you which shows you how you can use a VideoView and change orientation making sure that:

1) video will not stop after orientation-change but will continue playing smoothly
2) video will resize to full screen in landscape and scale in the center in portrait-mode.

I am sharing the code here below. I have also attached the code as a sample-project where you will also find the requested xml-layout file necessary to get things working properly. Check also the changes I made to the Manifest. Please make sure to read my code-comments to understand better what I am doing.

If you make any improvements to the code, please share!

Thanks for reading.

B4X:
'*****************************************************************************************************************************************
' VideoView example optimized for orientation-change by moster67 (Mikael Osterhed) - 01/08/2016
' My thanks go to JordiCP and Erel for some useful code-snippets.

'This small project shows how you can use a VideoView and change orientation making sure that:
' 1) video will not stop after orientation-change but will continue playing smoothly
' 2) video will resize to full screen in landscape and scale in the center in portrait-mode.

'The fact that the video will not stop after orientation change is because we are using a special attribute
'in the manifest. This is done by inserting the following attribute in the manifest:
'  SetActivityAttribute(Main, android:configChanges, "orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation")
'Above attribute will make the code skip the onCreate method upon orientation-change. Note: This has some drawbacks though
'which we will resolve by using some specific code (see code-comments in the project).

'In order to resize the video properly after orientation-change has taken place, we are using an xml-layout based on FrameLayout.
'With this project I am providing an xml-layout called frame. In order to use this layout, we must use the XmlLayoutBuilder library
'which you can download from the B4A-forum.

'NOTE:
'If you are streaming content from the Internet, you must also add the following permission in the manifest:
'  AddPermission(android.permission.INTERNET)
'
'Required libraries: Audio, JavaObject, XmlLayoutLibrary
'
'****************************************************************************************************************************************



#Region  Project Attributes
    #ApplicationLabel: vvxml
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
    'ensures that the res-folder (and the xml-layout) is read-only so that it cannot be deleted.
    'alternatively you can set the xml-layout file as read-only
    #CustomBuildAction: 1, c:\windows\system32\attrib.exe, +r res\*.* /s
#End Region

#Region  Activity Attributes
    #FullScreen: true
    #IncludeTitle: false
#End Region




Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim timer1 As Timer
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim vv As VideoView
    Dim x As XmlLayoutBuilder
    Private ActivityParent As JavaObject

End Sub

Sub Activity_Create(FirstTime As Boolean)
        
    '* Code needed for the sub AfterChange. See comments in said sub.
    Dim jo As JavaObject = Activity
       jo.RunMethodJO("getContext", Null).RunMethodJO("getWindow", Null)
    ActivityParent = jo.RunMethodJO("getParent", Null)

    timer1.Initialize("Timer1",100)

    '***********************************************************************************************
    'Load the layout using XmlLayoutBuilder. You may need to download the library from the forum.
    'I am providing an xml-layout based on FrameLayout. It must be placed in the layout-folder
    'under Objects/res/. This layout ensures that the video will resize after an orientation change.
    'If you have difficulties in understanding how the XmlLayoutBulder works, please then read the
    'thread from where you downloaded it.
    '***********************************************************************************************
    x.LoadXmlLayout(Activity, "frame")
    vv.Initialize("vv")
    vv = x.GetView("surface")
    Activity.Color = Colors.Black

    vv.LoadVideo("http","http://www.storiesinflight.com/js_videosub/jellies.mp4")
    vv.Play



End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub vv_Complete
  Log("Playing completed")
End Sub

Sub timer1_Tick

    If vv.IsPlaying Then
        CallSubDelayed(Me, "AfterChange")
    End If

End Sub

Sub Activity_ConfigChanged()

    '****************************************************************************************
    'This code together with the java-snippet in this project detects a configuration-change
    'Here I use the timer to call the sub AfterChange
    'My testing showed that a delay of 100ms is sufficient to let the sub AfterChange
    'be in a position to obtain the new activity values. It resulted also in a smooth
    'orientation-change of the playing video.
    '****************************************************************************************

    Log("inside configsub")
    timer1.Enabled = True
End Sub

Sub AfterChange

   '******************************************************************************************************
   'After a configuration-change, bypassing onCreate, it is difficult to get the new values
   'of Activity Height and Activity Width. This code posted by Erel helps us to obtain the new values.
   '******************************************************************************************************
   
   Dim ajo As Panel = Activity
   Dim width As Int = ActivityParent.RunMethod("getMeasuredWidth", Null)
   Dim height As Int = ActivityParent.RunMethod("getMeasuredHeight", Null)
   If width = 0 Or height = 0 Then Return
   ajo.Width = width 'update the "activity" width and height
   ajo.Height = height
   Activity.Invalidate
   vv.Width = width
   vv.Height = height
   'Log("AW=" & Activity.Width & " and AH=" & Activity.Height)
   vv.Invalidate
   timer1.Enabled = False

End Sub

#if JAVA

//This java-code will detect a configuration-change. We use it to trigger our event
//Activity_ConfigChanged in our B4A-code.
//Many thanks to JordiCP in the B4A-forum for this java-snippet!!

import android.content.res.Configuration;
import anywheresoftware.b4a.keywords.Common;
import android.view.WindowManager;
import android.content.Context;

@Override
public void onConfigurationChanged(Configuration newConfig) {

    super.onConfigurationChanged(newConfig);
    processBA.raiseEvent(null, "activity_configchanged"); // trigger event in B4A-code                                                   
}

#end if
 

Attachments

  • vvxml.zip
    8.9 KB · Views: 278
Last edited:

analizer3816

Member
Licensed User
I use this in manifest, auto orientation>>landscape or reverse landscape
B4X:
SetActivityAttribute(Main, android:screenOrientation, "sensorLandscape")

this is all screen orientation mode
B4X:
          android:screenOrientation=["unspecified" | "behind" |
                                     "landscape" | "portrait" |
                                     "reverseLandscape" | "reversePortrait" |
                                     "sensorLandscape" | "sensorPortrait" |
                                     "userLandscape" | "userPortrait" |
                                     "sensor" | "fullSensor" | "nosensor" |
                                     "user" | "fullUser" | "locked"]
 

moster67

Expert
Licensed User
Hi @analizer3816 ,
your solution is fine using the sensors when switching from normal landscape to reverse landscape and the video continues to play. So far so good.
However, the specific case for which I wrote the post involves also changing orientation from portrait to landscape and then back to portrait. In this case, you need to add:
B4X:
SetActivityAttribute(Main, android:configChanges, "orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation")
in order to avoid that the video stops and starts again.

If you use your solution (let's say using "fullSensor" to enable switch from portrait to landscape and back) and adding the SetActivityAttribute I mentioned above, then the video will continue to run continuously (without stopping) as desired, however when you come to landscape from portrait, you will notice that the VideoView is not full screen any more. My solution resolves that problem plus ensures continuous playing of the video.

I hope I understood what you meant correctly - if not please post a small sample project.
 
Top