Playing video - solution

Hey all,
Seeing that there were a lot of older & newer posts about playing videos in cocos2dx, and having the iOS solution from Victor (http://www.cocos2d-x.org/boards/6/topics/2345) I’ve found a way to play them on Android - this may not be the best and only solution, but it works.

It uses a JNICall to a new class in cocos2dx library which plays the video in a new Android Activity. The Activity closes automatically after the playback finishes.

  1. Add a new class in eclipse to libcocos2dx project and name it “Cocos2dxVideo”. Here is the code :

    package org.cocos2dx.lib;

    import android.media.MediaPlayer;
    import android.net.Uri;
    import android.os.Bundle;
    import android.widget.MediaController;
    import android.widget.VideoView;
    import android.app.Activity;
    import android.content.res.Resources;

    public class Cocos2dxVideo extends Activity {

     private static final String TAG = "Cocos2dxVideo";
     private Activity me;
    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_cocos2dx_video);
    
         me = this;
    
         VideoView vv = (VideoView) findViewById(R.id.videoPlayer);
    
         String filename = getIntent().getStringExtra("FILENAME");
    
         filename = filename.toLowerCase();
    
         Resources res = this.getResources();
         int id = res.getIdentifier(filename, "raw", getPackageName());
    
         MediaController mc = new MediaController(this);
         mc.setAnchorView(vv);
    
         vv.setMediaController(mc);
         vv.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + id));
    
         vv.start();
         vv.requestFocus();
    
         vv.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    
             @Override
             public void onCompletion(MediaPlayer mp) {
                 // TODO Auto-generated method stub
                 me.finish();
             }
             ;
         });
     }
    

    }

  2. Add this snippet to Cocos2dxActivity (the “me” variable is an instance of Activity class which you should set in the onCreate method to “this” so me = this; ):

     public static void openVideo(String name) {
    
         Intent i = new Intent();
         i.setClass(me, Cocos2dxVideo.class);
    
         i.putExtra("FILENAME", name);
         me.startActivity(i);
    
     }
    
  3. Add “activity_cocos2dx_video.xml” to “res/layout”. File content :

  4. At this point we are done with changes to libcocos2dx. Rebuild the project (RMB ~~> Build).

  5. In your project Manifest add :
    <pre>


    </pre>

  6. Add JNI calls to your method : if you don’t know how, you can find great explanation here : http://www.cocos2d-x.org/boards/6/topics/3769 by Michael Developer. The Java method we want to call is of course the “openVideo(String name)” which we added to Cocos2dxActivity.

  7. In your project add file Wrapper.h with content :
    <pre>
    #include “cocos2d.h”
    #if
    #include “platform/android/jni/VideoJni.h”
    #endif
    void playMovie {
    {
    #if
    openVideoJNI;
    #endif
    }
    </pre>
    .

  8. Add your video file to your projects “res/raw” folder~~ IMPORTANT - this is not the “Resources” folder where you’d put other files in “the Cocos way”. You have to put the videos in the Android project in eclipse “the Android way”.

  9. Remember that Android forces files to be all lower case, so rename the file in Eclipse if necessary. It’s ok to call the function with fileName with uppercase letters, because it is changed to lowercase before fetching the resource id.

  10. You should be all set & ready to play movies :slight_smile:

I know that ideally it would be best not to launch another Activity and I will look into it if I find some time. At the moment I hope that someone will find it useful for hers/his project.

If you find any bugs/something doesn’t work please post here.

Cheers!

I tried to deal with this too, and this is my solution. Layout file is almost as same as yours.
I replace the cocos2dx game view with video view to play video.

import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;

import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.VideoView;

public class VideoSample extends Cocos2dxActivity {
    private static VideoSample smActivity = null;

    static {
        System.loadLibrary("game");
    }

    public static void displayVideo() {
        smActivity.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                smActivity.startVideo();
            }
        });
    }

    public static void removeVideo() {
        smActivity.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                smActivity.stopVideo();
            }
        });
    }

    private FrameLayout mGameView = null;
    private int mStopPosition = 0;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        smActivity = this;
    }

    @Override
    protected void onPause() {
        super.onPause();
        // stop video if it's playing
        if (mGameView != null) {
            VideoView vv = (VideoView) findViewById(R.id.vv);
            mStopPosition = vv.getCurrentPosition();
            vv.pause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mGameView != null) {
            VideoView vv = (VideoView) findViewById(R.id.vv);
            vv.seekTo(Math.max(0, mStopPosition - 3000));
            vv.start();
            mStopPosition = 0;
        }
    }

    private void startVideo() {
        View videoView = LayoutInflater.from(this)
                .inflate(R.layout.video, null);
        if (videoView != null) {
            FrameLayout view = (FrameLayout) findViewById(android.R.id.content);
            view.addView(videoView);
            mGameView = (FrameLayout) view.getChildAt(0);
            setContentView(videoView);

            Button skip = (Button) findViewById(R.id.skip);
            skip.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    stopVideo();
                }
            });

            VideoView vv = (VideoView) findViewById(R.id.vv);
            vv.setVideoURI(Uri.parse("android.resource://" + getPackageName()
                    + "/" + R.raw.start));
            vv.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer arg0) {
                    stopVideo();
                }
            });
            vv.start();
        }
    }

    private void stopVideo() {
        if (mGameView == null) {
            return;
        }
        VideoView vv = (VideoView) findViewById(R.id.vv);
        vv.stopPlayback();
        setContentView(mGameView);
        // make mGLSurfaceView get focus, or keyboard will popup after activity goes to background and comes back
        for (int i = 0; i < mGameView.getChildCount(); i++) {
            View v = mGameView.getChildAt(i);
            if (v instanceof Cocos2dxGLSurfaceView) {
                v.requestFocus();
                break;
            }
        }
        mGameView = null;
    }
}

Thanks for your answers, guys! They were just in time I started implementing Android video ) In my app all the data is packed to apk file and I found no way to make it compatible with ViedoView.setVideoURI. Another way to play video requires some slight changes in Cocos2dxMusic. If you try to pass a video file name instead of background track you will actually hear the sounds from the video, the only thing left is to add a SurfaceView to main activity and call setDisplay method of MediaPlayer. Everything works fine so far ) I’ll post the codes if anybody requires it.

Are you making the code compatible for both ios + android? :smiley: I’d love to use your solution…

Thanks,

Does anyone have a ios + android solution for video player?

I’ve encountered a problem when trying to return from video play to game, posted here http://www.cocos2d-x.org/forums/6/topics/41739

cocos2d-x seems have opengl state error since video view uses surfaceview, too. Any suggestion?

Pawel Lopusinski wrote:

Hey all,
Seeing that there were a lot of older & newer posts about playing videos in cocos2dx, and having the iOS solution from Victor (http://www.cocos2d-x.org/boards/6/topics/2345) I’ve found a way to play them on Android - this may not be the best and only solution, but it works.