Java Question SurfaceView

moster67

Expert
Licensed User
Longtime User
Anyone who knows to create (or wrap) a SurfaceView in B4A?
An alternative would be to able to cast a ViewGroup to a SUrfaceView although I don't think that is possible.

Thanks.
 

moster67

Expert
Licensed User
Longtime User
I have written a VideoView class for VLC and it works fine with a test app written in Android Studio (and Java).
I am now writing the wrapper of this VideoView class so it can be used with B4A. Most things are working fine but I have a problem with displaying the subtitles.

In my VideoView class I have written the following code-snippet:
B4X:
if (mSubtitlesSurfaceView != null && HWDecoderUtil.HAS_SUBTITLES_SURFACE) {
                    mediaPlayer.getVLCVout().setSubtitlesView(mSubtitlesSurfaceView);

                    Log.d("B4A", "Surfaceview was set");
                    mSubtitlesSurfaceView.setZOrderMediaOverlay(true);
                    mSubtitlesSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);

}

which requires that I pass on a SurfaceView for displaying the subtitles. To do that, I created a method as follows:
B4X:
public void setSubtitlesSurfaceView (SurfaceView subtitleview) {
    this.mSubtitlesSurfaceView = subtitleview;
}

and this works fine in my Android test-app as I just use it as follows:
B4X:
SurfaceView mSubtitlesSurfaceView = (SurfaceView) findViewById(R.id.subtitles_surface);
myVideoView.setSubtitlesSurfaceView(mSubtitlesSurfaceView);

This works, since in the Android test-app I have layout with a SurfaceView (R.id.subtitles_surface).

Now in my VideoView wrapper, I have set up the following method:
B4X:
public void setSubtitlesSurfaceView (SurfaceView subtitleView){
    getObject().setSubtitlesSurfaceView(subtitleView);
}

so I can pass on a SurfaceView (to use to show the subtitles) from the app written B4A but the problem is that I have no SurfaceView in B4A to pass on and I don't know how I can use the layout-designer in B4A to create the required SurfaceView.

I was thinking of using XMLLayoutBuilder and my own Layout with a SurfaceView and then add a method in my VideoView wrapper more or less as follows:
B4X:
public void setSubtitlesSurfaceView (){
    String resourceName="surface_view";
    int resourceId = BA.applicationContext.getResources().getIdentifier(resourceName, "id", BA.packageName);
    subtitleView = (SurfaceView) subtitleView.findViewById(resourceId);
    setSubtitlesSurfaceView(subtitleView);
}

Alternatively I guess I could include the Layout as a Resource in my library and then use #AdditionalRes in B4A.

However, the idea is that I don't need to supply any resources and maybe I can do that if I was able to write a SurfaceView in B4A by code.

Edit: First I was hoping I could pass on a B4A panel but a panel is a ViewGroup object (I think) and therefore it cannot be used.

Hope what I wrote makes sense
 
Last edited:

JordiCP

Expert
Licensed User
Longtime User
The panel option you mention seems ok. The user passes a panel from B4A and you build a surfaceView on it, so the process is invisible to the user.
 

moster67

Expert
Licensed User
Longtime User
You mean that in my wrapper I "take" the panel (which I believe is a ViewGroup) and then add a SurfaceView?
How would I do that? Any hint?
 

JordiCP

Expert
Licensed User
Longtime User
Exactly.
I have done something similar with a RelativeLayout, but it should work with any ViewGroup derived class

This is a part of the code

B4X:
     if (mFrameLayout.getChildCount() == 0) {
        sv = new SurfaceView(context);
        RelativeLayout.LayoutParams mLayoutParams = new RelativeLayout.LayoutParams(mFrameLayout.getLayoutParams().width,mFrameLayout.getLayoutParams().height);
        mFrameLayout.addView(sv, mLayoutParams);
        sv.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        sv.getHolder().setFixedSize(mFrameLayout.getLayoutParams().width, mFrameLayout.getLayoutParams().height);

        //add event listener
        listener = new Callback() {
           @Override
           public void surfaceChanged(SurfaceHolder holder, int format,
               int width, int height) {
                //....
           }
           //...also add surfaceCreated and surfaceDestroyed....  
        }
        sv.getHolder().addCallback(listener);
     }
     else {    // Already exists
         sv = (SurfaceView)mFrameLayout.getChildAt(0); 
     }
 

moster67

Expert
Licensed User
Longtime User
Thank you @JordiCP! I got it working using your code example and idea.

Screenshot_2016-03-20-16-55-54.jpg


PS: anyone who recognizes this cult tv-show? ;)
 
Top