Skip to content
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

Exoplayer cannot be constructed with a specification for "surface_type" programmatically? Why not? #1375

Closed
jonmdev opened this issue May 15, 2024 · 5 comments

Comments

@jonmdev
Copy link

jonmdev commented May 15, 2024

Version

Media3 main branch

More version details

As noted here:

There exists no way to create an ExoPlayer programmatically while declaring the surface type in the constructor in C#/.NET. The only proposed way to do this in Android is explained here but even this is extremely clumsy and illogical.

No equivalent to this Android code exists in C#/.NET. No one is able to propose a method to make this possible in C#/.NET.

It seems obvious then the simplest solution is to simply add a constructor (which should exist either way) where we can declare the surface type on construction.

For example, we could have a simple enum:

enum ExoPlayerSurfaceType {
    surfaceView,
    textureView,
    none
}

We have the currently unhelpful constructor:

public unsafe StyledPlayerView (global::Android.Content.Context? context, global::Android.Util.IAttributeSet? attrs)

We could add the following option:

public unsafe StyledPlayerView (global::Android.Content.Context context, ExoPlayerSurfaceType surfaceType)

Or we could have an entire new class for ExoPlayerConstructorAttributes which we could create an object of and set the surface type inside (along with any other "only available on construction" parameters if they exist).

Why is this not the case already? If you agree this is a logical solution, how can we add it?

Thanks.

Devices that reproduce the issue

All ExoPlayer developments

Devices that do not reproduce the issue

n/a

Reproducible in the demo app?

Yes

Reproduction steps

See demo code and the problems this issue is causing in links above, or again, at:

Expected result

One should be able to easily create an ExoPlayer with any type of surface (TextureView, SurfaceView, none) easily from a simple constructor in Android or C#/.NET.

Actual result

It is currently very circuitous to do this in native Android code and completely impossible in C#/.NET. No solutions or answers are available anywhere.

Media

Open Visual Studio 2022. Go File > New > Android Application. Copy and paste the code here into MainActivity.cs:

protected override void OnCreate(Bundle? savedInstanceState) {
    base.OnCreate(savedInstanceState);
    
    string xmlString =
        "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
        "<Com.Google.Android.Exoplayer2.UI.PlayerView " +           
        "android:id=\"@+id/player_view\" " +
        "app:surface_type=\"texture_view\" " + //KEY NEEDED LINE FOR GOAL
        "android:layout_width=\"match_parent\" " +
        "android:layout_height=\"match_parent\"/>";
    
    XmlReader xmlReader = XmlReader.Create(new StringReader(xmlString));
    xmlReader.Read();
    System.Diagnostics.Debug.WriteLine("XML READER " + xmlReader.AttributeCount);
            
    Android.Util.IAttributeSet attributes = Android.Util.Xml.AsAttributeSet(xmlReader);
    System.Diagnostics.Debug.WriteLine("ATTRIBUTES " + attributes.AttributeCount);
    
    Com.Google.Android.Exoplayer2.UI.StyledPlayerView styledPlayerView = new(this, attributes);            

Receive errors as there is no current working workflow available to do this.

@andrewlewis
Copy link
Collaborator

Providing support for usage from C# is not really in scope for this tracker, but have you tried storing a layout file as a resource like what's described here, instead of trying to construct and read the XML file programmatically?

Is this issue a duplicate of #1360?

@jonmdev
Copy link
Author

jonmdev commented May 16, 2024

I have just realized the only Kotlin method to do this also does not programmatically create the XML but rather just loads from resources. It seems Android offers no way to allow one to programmatically do this at all.

One must save the XML to resources and then load it.

.NET "SOLUTION"

  1. Create XML file named "test.xml" in Resources\layout
  2. Copy paste into it:
<?xml version="1.0" encoding="utf-8" ?> 
<com.google.android.exoplayer2.ui.StyledPlayerView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/test"
    app:surface_type="texture_view"
    android:layout_width= "match_parent"
    android:layout_height= "match_parent" />
  1. Run code in MainActivity.cs:
XmlReader xmlResource = this.Resources.GetXml(Resource.Layout.test);
xmlResource.Read();

Android.Util.IAttributeSet attributes = Android.Util.Xml.AsAttributeSet(xmlResource);

//BUILD EXOPLAYER
Com.Google.Android.Exoplayer2.UI.StyledPlayerView styledPlayerView = new(this, attributes); 

INTENDED DESIGN?

Is this the intended design of Android? Are we supposed to save tiny little snippets of silly XML in our Resources folder and then load them like this for usage when we need to construct something?

Why? Why not programmatically create the XML (if XML must be used as an intermediate) on the fly in the code?

@jonmdev jonmdev changed the title Exoplayer is missing a basic constructor for surface type. Can we please add this so we can properly use it? Exoplayer cannot be constructed with a specification for "surface_type" programmatically? Why not? May 16, 2024
@andrewlewis
Copy link
Collaborator

I think setting attributes in the XML file is a conventional way to specify properties for a custom view -- see Define custom attributes. There are a bunch of these for PlayerView defined around here.

As documented here the intended way to use this is to set them in your layout XML file.

After adding a .NET discussion (linked above) which has also been unhelpful, and reviewing further, I again believe this is an Android issue not a .NET issue.

Based on your reply just now, did you get this to work in the end? If not, please could you describe what didn't work in case that's useful to someone else in future?

@jonmdev
Copy link
Author

jonmdev commented May 16, 2024

I posted the "working" code one reply above yours.

The remaining problem as I see it however applies to Kotlin or C#/.NET (as it is clearly a basic Google Android design issue):

  1. You cannot create XML from string (ie. programmatically) and convert it to a AttributeSet.
  2. You can only convert XML that is loaded from Resources to AttributeSet.

This is absurd because it means you need to save a bunch of small snippets of XML to your Resources folder in order to characterize your objects.

It reduces portability and flexibility of code. Android should have a working method to create the needed AttributeSet WITHOUT having to save and load a five line XML snippet from the Resources folder.

One does not need to use XML in any way to build an Android hierarchy, and one should not need to save XML snippets into the Resources folder and load from them to simply build the AttributeSet for a basic constructor.

How is this not silly? How does this not cause increased problems? Why wouldn't it be logical to be able to build the AttributeSet on the fly from just the string of desired XML in a function of code?

ie. If Google Android is committed to the design concept that constructors should be parameterized by writing small XML snippets and converting them to AttributeSet, then so be it. Some method must be necessary. That is fine.

But then why prohibit us from writing those XML snippets on the fly in our code? Why can't we have portable and coherent code/classes/scripts without also having to create these bunches of tiny XML snippets and save them separately in the Resources folder? How is this helpful or practical? What is the point?

@andrewlewis
Copy link
Collaborator

This issue tracker is focused on AndroidX media3 specifically. If you want to pass on feedback about the Android design, I suggest filing a bug at https://source.android.com/docs/setup/contribute/report-bugs to get it routed to the relevant team(s). I guess Compose may help address some of your concerns.

About PlayerView specifically: there are a bunch of different attributes defined (see class javadoc here) and some of them can be changed via setters (which I guess would equally satisfy your concerns as a constructor parameter) but so far I don't think we considered it to be useful to set surface type dynamically. (By the way, we recommend using SurfaceView (which is the default) -- see https://developer.android.com/media/media3/ui/playerview#surfacetype.)

@androidx androidx locked and limited conversation to collaborators Jul 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants