I am trying to create an ExoPlayer using Android code within .NET (MAUI) that renders to a TextureView (rather than the default SurfaceView).
This is discussed in terms of Android in this thread.
In .NET/MAUI we have the following constructor which would apply for the ExoPlayer:
public unsafe StyledPlayerView (global::Android.Content.Context? context, global::Android.Util.IAttributeSet? attrs)
So you could run this as:
var PlayerView = new StyledPlayerView(androidContext, attributes);
//presuming you have a working 'attributes' file...
The second 'attributes' argument global::Android.Util.IAttributeSet? attrs
is where we are supposed to specify we want a TextureView.
From the link above, we must pass in an XML file which is first converted into the IAttributeSet
object to specify the TextureView as a target surface.
An example XML given is:
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/player_view"
app:surface_type="texture_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
The XML file of this nature must be converted into the attribute needed for the constructor by:
val xmlAttributes = context.resources.getXml(R.xml.player_view).let {
try {
it.next()
it.nextTag()
} catch (e: Exception) {
// do something, log, whatever
}
Xml.asAttributeSet(it)
}
If I want to work completely in a C# script, and I want to have no XML files to load from anywhere, but rather want to just declare this minimal short XML snippet as a string or written in my C# code directly, can I do this?
Can I then pass that into the code for creating the attribute? Or alternatively, can we make the IAttributeSet
for the constructor directly in C# without even bothering with creating the XML first?
My best attempt shown provides an error which I don't understand.
In Visual Studio 2022, if one goes:
Xam.Plugins.Android.ExoPlayer
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);
No errors are given in Visual Studio on coding. However two problems are evident on running it:
xmlReader
with the following code, it says **System.Xml.XmlException:** ''android' is an undeclared prefix. Line 2, position 52.'
:while (xmlReader.Read()) {
switch (xmlReader.NodeType) {
case XmlNodeType.Element:
System.Diagnostics.Debug.WriteLine("<{0}>", xmlReader.Name);
break;
case XmlNodeType.Text:
System.Diagnostics.Debug.WriteLine(xmlReader.Value);
break;
case XmlNodeType.CDATA:
System.Diagnostics.Debug.WriteLine("<![CDATA[{0}]]>", xmlReader.Value);
break;
case XmlNodeType.ProcessingInstruction:
System.Diagnostics.Debug.WriteLine("<?{0} {1}?>", xmlReader.Name, xmlReader.Value);
break;
case XmlNodeType.Comment:
System.Diagnostics.Debug.WriteLine("<!--{0}-->", xmlReader.Value);
break;
case XmlNodeType.XmlDeclaration:
System.Diagnostics.Debug.WriteLine("<?xml version='1.0'?>");
break;
case XmlNodeType.Document:
break;
case XmlNodeType.DocumentType:
System.Diagnostics.Debug.WriteLine("<!DOCTYPE {0} [{1}]", xmlReader.Name, xmlReader.Value);
break;
case XmlNodeType.EntityReference:
System.Diagnostics.Debug.WriteLine(xmlReader.Name);
break;
case XmlNodeType.EndElement:
System.Diagnostics.Debug.WriteLine("</{0}>", xmlReader.Name);
break;
}
}
Debug taken from: https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlreader.read?view=net-8.0
**Java.Lang.ClassCastException:** 'android.util.XmlPullAttributes cannot be cast to android.content.res.XmlBlock$Parser'
Why is this code is failing on these two points? The only other place I see the error from (2) is here and I am not sure of how this works.
Can anyone provide a working sample of C# code that can make the attribute needed for the StyledPlayerView constructor to allow a TextureView Exoplayer to be created in .NET?
Thanks for any help.
After further research there is no way to do this in .NET except:
<?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" />
XmlReader xmlResource = this.Resources.GetXml(Resource.Layout.test);
xmlResource.Read();
Android.Util.IAttributeSet attributes = Android.Util.Xml.AsAttributeSet(xmlResource);
Com.Google.Android.Exoplayer2.UI.StyledPlayerView styledPlayerView = new(this, attributes);
This does work. But there is no way to programmatically create the XML whether in Kotlin or C#. It must be pre-stored in Resources and loaded from there.
This seems to be just bad Android design.