Android Question ExoPlayer Setting Uri Source Header

Hello,
I'm trying to play a UriSource with exoplayer but I need to set up the http header for the link.
I've found this java code (link)
Setting headers for streaming mp4 video and playing files with Exoplayer:
   // (1) Create method returns  'DataSource.Factory'
     public DataSource.Factory headers() {
            Map<String, String> headersMap = new HashMap<>();
            headersMap.put("iid", "aaa123 ");
            headersMap.put("version", "1.4");
            headersMap.put("agent", "phone");
            headersMap.put("token", "dfdf4f4yt5yf5fh4f5");
            return new DefaultHttpDataSource.Factory().setDefaultRequestProperties(headersMap);
        }
    // (2) Add headers() method call to the player
           SimpleExoPlayer player = new SimpleExoPlayer.Builder(context)
                    .setMediaSourceFactory(new
                     DefaultMediaSourceFactory(headers()))
                    .build();

Anyone can help me port it to B4A..
Thanks
 
Solution
Finally I found the solution already given by Erel (here):

B4X:
Dim jo As JavaObject = player1.CreateUriSource("...")
Dim r As Reflector
r.Target = jo
r.Target = r.GetField("dataSourceFactory")
Dim http As JavaObject = r.GetField("baseDataSourceFactory")
Log(GetType(http))
http.RunMethod("setDefaultRequestProperties", Array(CreateMap("referer": "test")))

JohnC

Expert
Licensed User
Longtime User
Try providing this prompt to ChatGPT (to check out it's response:

B4X:
Please either modify this java code or provide code so that I can use it in B4A:
[inset the java code you just posted here]
 
Upvote 0
I've managed to convert it to this code"

B4X:
Sub headers As JavaObject
    Dim headersmap As Map
    headersmap.Initialize
'   Setting (package name and sha-1) as defined by the API key restriction parameters
    headersmap.Put("X-Android-Package" , "com.myPackage.name")
    headersmap.Put("X-Android-Cert" , "000000000000000000000000000")
    Dim factory As JavaObject
    factory.InitializeNewInstance("com.google.android.exoplayer2.upstream.DefaultHttpDataSource.Factory" , Null)
    Return factory.RunMethodJO("setDefaultRequestProperties" , Array (headersmap))
End Sub

Sub CreateNativePlayer As Object
    Dim mediafactory As JavaObject
    mediafactory.InitializeNewInstance("com.google.android.exoplayer2.source.DefaultMediaSourceFactory" , Array (headers))
    Dim builder As JavaObject
    Dim ctxt As JavaObject
    ctxt.InitializeContext
    builder.InitializeNewInstance("com.google.android.exoplayer2.SimpleExoPlayer.Builder" , Array(ctxt))
    
    Dim np As JavaObject
    np = builder.RunMethodJo("setMediaSourceFactory" , Array(mediafactory)).RunMethod("build" , Null)
    Return np
End Sub
...
Player.InitializeCustom("Player" , CreateNativePlayer)

The app is running but the video can't be played.. What's wrong with it?
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
This might be an obvious issue, but you are replacing the "com.myPackage.name" with your apps real package name right?
 
Upvote 0
After checking exoplayer error log, it's showing this error:
com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 403
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
Error "403" means "Forbidden". So I would try to use a stream source that you know you have permission to access first, just to make sure all of your code is at least working, then try to figure out why you don't have permission for the main stream.
 
Upvote 0
In fact I did this test to play a video with no access permission and it worked fine..
Also when I try to play the restricted video with the default player that doesn't send authentication header I get the same error, that means the authentication used with my code is not working (although the credentials are right).
I don't know if there is something should be edited in the the way I pass the credentials (eg. encoding).
I found another way to send the authentication header that I will give it a try, but working with exoplayer classes is not easy..
 
Upvote 0
exoplyer dev suggests this code:
Customizing server interaction:
DataSource.Factory dataSourceFactory = () -> {
  HttpDataSource dataSource = httpDataSourceFactory.createDataSource();
  // Set a custom authentication request header.
  dataSource.setRequestProperty("Header", "Value");
  return dataSource;
};
ExoPlayer player = new ExoPlayer.Builder(context)
    .setMediaSourceFactory(
        new DefaultMediaSourceFactory(context)
            .setDataSourceFactory(dataSourceFactory))
    .build();
which may be written in B4A like this:
B4X:
Sub headers As JavaObject
    Dim factory As JavaObject
    factory.InitializeNewInstance("com.google.android.exoplayer2.upstream.DefaultHttpDataSource.Factory" , Null)
    Dim jo As JavaObject
    jo.InitializeNewInstance("com.google.android.exoplayer2.upstream.DefaultHttpDataSource.Factory" , Null)
    jo = factory.RunMethodJO("createDataSource" , Null)
    jo.RunMethod("setRequestProperty", Array ("X-Android-Package" , "com.myPackage.name"))
    jo.RunMethod("setRequestProperty" , Array ("X-Android-Cert" , "9778F0EC53DD4907768B881838715DCC8BBB6E73"))
    Return jo
End Sub

Sub CreateNativePlayer As Object
    Dim ctxt As JavaObject
    ctxt.InitializeContext
    mediafactory.InitializeNewInstance("com.google.android.exoplayer2.source.DefaultMediaSourceFactory" , Array (headers))
    'mediafactory.InitializeNewInstance("com.google.android.exoplayer2.source.DefaultMediaSourceFactory" , Array (ctxt)).RunMethod("setDataSourceFactory" , Array(headers))
    Dim builder As JavaObject
    builder.InitializeNewInstance("com.google.android.exoplayer2.SimpleExoPlayer.Builder" , Array(ctxt))
    Dim np As JavaObject
    np = builder.RunMethodJo("setMediaSourceFactory" , Array(mediafactory)).RunMethod("build" , Null)
    Return np
End Sub

But it giving me this error on line 15:
java.lang.RuntimeException: Constructor not found.
I think it's because the parameter should be of type 'DefaultHttpDataSource.Factory' but it receive 'DefaultHttpDataSource'
Anyone could help me with this 🙏
 
Upvote 0
Finally I found the solution already given by Erel (here):

B4X:
Dim jo As JavaObject = player1.CreateUriSource("...")
Dim r As Reflector
r.Target = jo
r.Target = r.GetField("dataSourceFactory")
Dim http As JavaObject = r.GetField("baseDataSourceFactory")
Log(GetType(http))
http.RunMethod("setDefaultRequestProperties", Array(CreateMap("referer": "test")))
 
Upvote 0
Solution
Top