[SOLVED] Playing YouTube inside Cocos

Hi,

I am currently working on the Android version of an app and trying to have a YouTube video play over the top of the game. I need the video to take up only part of the screen and play within the app.

I have tried doing this by using the YouTube API, but only the black bars above and below the video, and the controls appear; the video is not visible at all. (The video does play, though, even though it isn’t visible.) I think Cocos’s surface view is interfering with it.

I did a quick look for playing YouTube in a WebView (which is how Google’s samples do it for iOS), but I have read that apparently I won’t be able to get callbacks. (I need to know when the video starts playing and when it finishes.)

Has anybody managed to get a YouTube video to play on top of Cocos, with callbacks for at least when the video ends?

Thanks.

1 Like

Cocos2d-x has a video player that you can supply a URL to. I haven’t tried with a YouTube Link though.

http://www.cocos2d-x.org/reference/native-cpp/V3.2/d5/d18/classcocos2d_1_1experimental_1_1ui_1_1_video_player.html

1 Like

Thanks for the reply. Unfortunately I discovered that it is against Terms of Service to play a video outside of an official YouTube video player, which means I have to use either the official API or a WebView with the official YouTube player inside. Using something like the Cocos VideoPlayer with a direct link to the YouTube video wouldn’t be allowed.

That being said, thanks for letting me know there is a VideoPlayer in Cocos2d-x 3. I did not have fun trying to hack video into Cocos2d-x 2.

Ok, I have figured it out.

In case anyone else needs this, basically I set Cocos’s SurfaceView to a visibility of GONE (this.mGLSurfaceView.setVisibility(View.GONE);), added a YouTubePlayerView from the YouTube API in front of the SurfaceView and initialised the YouTubePlayerView. Once the YouTubePlayerView finishes initialising, I set a 1 second timer which would change the SurfaceView’s visibility to VISIBLE. After the SurfaceView is set to VISIBLE, the app will start running as it normally would.

I haven’t thoroughly tested this yet, but the only downside thus far is that the time between the app launching and your initial scene showing up is increased, meaning you get a black screen for longer. I am displaying a picture while YouTube initialises so it’s not black the entire time, but there is still some black between launching the app and the app actually showing something, and between when you set the SurfaceView to visible and the first scene actually showing up.

Hey @grimfate that sounds interesting.

could you be more elementary please… !!
I want to know what you’ve done but i am new here.

You could pm me… and could tell me how it works in a bit detail
expecting from you soon… !! :smile:

I’ll try and explain the steps for what I did in here so that anyone who wants it can see. Please be aware that this is probably not be good code, because I have just figured out how to do it. I am still working on it, so there’s a possibility there may be some huge problem I haven’t discovered yet.

  1. Download the YouTube API from https://developers.google.com/youtube/android/player/downloads/ and follow the instructions for adding the JAR to your project and getting a developer key.

  2. Create a layout XML file for YouTube player (by using com.google.android.youtube.player.YouTubePlayerView in the XML) like any other Android layout XML file.

  3. Go to your Cocos2dxActivity.java file and change the class to public abstract class Cocos2dxActivity extends YouTubeBaseActivity implements Cocos2dxHelperListener, YouTubePlayer.OnInitializedListener.

This step is so you can get the callbacks when initialising the YouTubePlayer. There may be a better place to do this.

  1. In the init() method, make Cocos’s SurfaceView’s visibility GONE. I.e. this.mGLSurfaceView.setVisibility(View.GONE);

This is necessary or else the YouTube video will appear behind Cocos’s SurfaceView.

  1. Add the YouTubePlayerView layout to the init() method just before setContentView(framelayout);. I did this using:
    LayoutInflater li = LayoutInflater.from(this);
    li.inflate(org.cocos2dx.lib.R.layout.youtube_layout, framelayout);

The YouTubePlayerView layout needs to be on top of everything else and the YouTubePlayerView needs to be in front of everything else in its layout file, or else it won’t play and will complain in the console.

  1. At the end of the init() method, hide the YouTubePlayerView and initialise it. I did this using:
    YouTubePlayerView player = (YouTubePlayerView)findViewById(R.id.youtube_view);
    player.initialize(DEVELOPER_KEY, this);
    player.setVisibility(View.INVISIBLE);

Setting it to invisible will prevent the YouTubeVideoPlayer, currently a black rectangle, from appearing on top of your app. Remember to replace DEVELOPER_KEY with your own YouTube developer key from Google.

  1. Add the YouTubePlayerView callbacks. These are:

/@Override
public void onInitializationFailure(Provider arg0, YouTubeInitializationResult arg1)

and

/@Override
public void onInitializationSuccess(Provider arg0, YouTubePlayer arg1, boolean arg2)

  1. In the onInitializationSuccess(), set a timer to make Cocos’s SurfaceView visible again. My code looks like:

    /@Override
    public void onInitializationSuccess(Provider arg0, YouTubePlayer arg1,
    boolean arg2) {
    new Timer().schedule(new TimerTask() {
    /@Override
    public void run() {
    runOnUiThread(new Runnable() {
    /@Override
    public void run() {
    makeSurfaceVisible();
    }
    });
    }
    }, 1000);
    }

    private void makeSurfaceVisible() {
    mGLSurfaceView.setVisibility(Cocos2dxGLSurfaceView.VISIBLE);
    }

The timer is necessary because, for some reason, without it the SurfaceView will still appear in front. Make sure you run setVisibility() on the UI thread using runOnUiThread(). I use the makeSurfaceVisible() method rather than running the code in the Runnable, because I couldn’t access the SurfaceView from inside the Runnable. I’m not sure if there is a way.

  1. Also in onInitializationSuccess() it seems necessary to assign the YouTubePlayer variable to a local variable so you can directly access the YouTube player. I am unsure if there is an easy way to get the YouTubePlayer object from the YouTubePlayerView otherwise. In the code above, it is the parameter arg1.

I hope this explains it and I hope I haven’t missed anything. It was quite a task to figure this out.

nice explanation

Unfortunately going out of the app and back into the app will hide the YouTube video, so this is something that needs to be dealt with.

what needs to be dealt with from a cocos2d-x standpoint exactly?

If it is against YouTube’s policy to play videos outside an official player what are you proposing?

By “official player”, I mean either the flash/html player in a browser or the player included in the Android YouTube API. So, I believe you are not allowed to use a raw video stream from YouTube played in another video player, or to take the existing YouTube player and change it. Using the API in conjunction with Cocos2d-x should be fine, if you can get it to work.

Nothing is needed from a Cocos2d-x standpoint, unless it can add a feature to prevent its SurfaceView interfering with others, which is probably more of an issue with Android. (Apparently Android wasn’t designed to have multiple SurfaceViews visible at the same time, or at least overlapping.)

I also had a similar, if not the same, issue when trying to play a video inside my Cocos2d-x app using Android’s VideoView. The solution for that was to set the setZOrderMediaOverlay to true for the VideoView, something I can’t find with the YouTubePlayerView.

Thanks. I understand.

i was trying and not refused the url form youtube

There’s also a different solution for this problem. Create new Acitvity with youTube video player. From c++ call java code (through jni) and show this activity. After watching the movie you’ll just close it and it’ll come back to the previous activity.