How to access the unity SurfaceView

I wrapped ExoPlayer within an Android plugin and used it inside a unity project. Until now everything is working fine, this is my code

Unity Script

public class WrapperExo : MonoBehaviour{

   private AndroidJavaObject javaClass;

    // Start is called before the first frame update
    void Start()
    {
        AndroidJavaClass playerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject activity = playerClass.GetStatic<AndroidJavaObject>("currentActivity");


       javaClass = new AndroidJavaObject("com.example.exowrapperlib.ExoStarter");
       javaClass.Call("openPlayer",  new object[] { activity, "test unity" });

    }
}

Android Plugin

public class ExoStarter {

    public void openPlayer(Context context, String message){
        Intent intent = new Intent(context, ExoController.class);

        Bundle b = new Bundle();
        b.putString("message", message);
        intent.putExtras(b);

        context.startActivity(intent);
    }
}

In ExoController I just initialize ExoPlayer normally

SimpleExoPlayer player = new SimpleExoPlayer.Builder(ExoController.this).build();

MediaItem mediaItem = new MediaItem.Builder()
        .setUri("https://example.com/Manifest.mpd")
        .setDrmUuid(C.WIDEVINE_UUID)
        .setDrmLicenseUri("https://example/Widevine")
        .setDrmMultiSession(true)
        .build();
player.setMediaItem(mediaItem);
SurfaceView exoOutputView = findViewById(R.id.exo_output);
player.setVideoSurfaceView(exoOutputView);
player.prepare();
player.play();

Everything is working fine until I try to play DRM protected content. With DRM content I can hear the audio but I cannot see the video. To solve the problem I am trying to render the video directly on the Unity SurfaceView and not the one created by the android plugin.
Is it possible to send a reference of the unity surfaceView to the android plugin when calling the method openPlayer of the plugin? I am looking for something like

AndroidJavaClass playerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = playerClass.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject unitySurfaceView = playerClass.GetStatic<AndroidJavaObject>("currentSurfaceView");

javaClass.Call("openPlayer",  new object[] { activity, surfaceView "test unity" });

I was not able to find anything about that in the documentation.
I found one article where they did something similar but they don’t explain how they got the _androidSurface pointer ExoPlayer for building powerful VR players on Cardboard and GearVR | by CINEMUR | CINEMUR Engineering | Medium

Any idea on how to solve that or other ideas to solve the DRM problem?

UnityPlayer.java creates a framelayout and then puts the game content surfaceview inside of that framelayout.

On the Android side, you have a reference to the UnityPlayer object, say something like: mUnityPlayer. Now from that reference you have reference to its view as mUnityPlayer.view.

Make that view realize it’s a framelayout by casting it. So unityFrame=mUnityPlayer.view as FrameLayout.

That FrameLayout has exactly one child, and it’s your surfaceview. So cast it as such like this:

surfaceView=(mUnityPlayer.view as FrameLayout).child(0) as SurfaceView

This seems very interesting, but a little beyond me on how to implement it in unity.

This is Wrong. This way only can get com.unity3d.player.UnityPlayer and you will get an issue: cant cast player to surfaceview

The only way to get surfaceview is directly get surfaceview itself

It does not work. The check frameLayout.getChildAt(0) instanceof SurfaceView returns false.
It any solution to this question?

No, it works!! I tried.

1 Like

which version of unity are you on?

may be 2021 LTS, and its not work in 2022 T_T