How to add vibration to any cocos2dx 3.3 Android app

I had originally avoided using vibration in my game, because I had found several different posts trying to figure out exactly what you needed to do, and I wasn’t able to find any tutorials that really broke down the process, so I chugged some coffee and dug into the code that was linked on the official forums. forum post. I can’t overstate how helpful it was to have a sub 10 second turn around time, between using Visual Studio to write the code, cocos to compile it (cocos compile -p android) and then to push it to my android phone with adb (adb install -r debug.apk), and then monitoring what was happening with logcat (adb logcat *:w), filtering only for warnings, errors and anything higher). Before we jump into it though, here’s a rough summary:

  1. You need to add a header in your Classes/ folder where you just have the vibrate function declared but not defined.
  2. Add a vibration function definition in the proj.android/jni, in a .cpp file. I used proj.android/jni/hellocpp/main.cpp , which I believe is the default for a starter cocos2dxv3 project. In this method you call the method you’ve defined in your java, in this case it was defined as a static method on your Activity. The default was named AppActivity .
  3. make sure you’ve got the vibration permission on your proj.android/AndroidManifest.xml , <uses-permission android:name= android.permission.VIBRATE>”

So, in one of your standard C++ headers in the Classes/ folder, add

    //Classes/any_header.h
    void vibrate(int milliseconds);

and in the associated <tt>.cpp</tt> file, call it: 

    //Classes/any_header.cpp
    void get_hit()
    {
      vibrate(200);
    }

In your
proj.android/AndroidManifest.xml , you’ll want to add that line

    <manifest>
      ...
      <uses-permission android:name="android.permission.VIBRATE"/>
    </manifest>

In a cpp file the jni will deal with, say proj.android/jni/hellocpp/main.cpp , you’ll need to define the connection between the Java and C++ by calling the Java method:

    //proj.android/jni/hellocpp/main.cpp
    /* this function should already exist though */
    void cocos_android_app_init (JNIEnv* env, jobject thiz) {
        LOGD("cocos_android_app_init");
        AppDelegate *pAppDelegate = new AppDelegate();
    }

    /* this is the new one you're adding, where org/cocos2dx/cpp/AppActivity
       is the java file where your Activity with the vibrate static method is defined
    */
    void vibrate(int milliseconds)
    {
        JniMethodInfo minfo;
        CCAssert(JniHelper::getStaticMethodInfo(minfo, "org/cocos2dx/cpp/AppActivity", "vibrate", "(I)V"), "Function doesn't exist");
        minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, (jint)milliseconds);
        minfo.env->DeleteLocalRef(minfo.classID);
    }

Finally, here’s the .java file where the android call to vibrate is made. Mine was proj.android/src/org/cocos2dx/cpp/AppActivity.java

    /* default imports */
    package org.cocos2dx.cpp;

    import org.cocos2dx.lib.Cocos2dxActivity;

    /* imports needed for vibration stuff */
    import android.os.Vibrator;
    import android.content.Context;
    import android.app.ActivityManager;
    import android.util.Log;
    import android.os.Bundle;

    public class AppActivity extends Cocos2dxActivity {

        private static volatile Cocos2dxActivity mainActivity;
        public static void setMainActivity(Cocos2dxActivity activity)
        {
            mainActivity = activity;
        }

        public static Cocos2dxActivity getMainActivity()
        {
            if(mainActivity == null)
            {
                Log.w("MY_APP_NAME_GOES_HERE", "Warning : null main Activity");
            }
            return mainActivity;
        }

    	@Override
    	protected void onCreate(Bundle savedInstanceState)
    	{
    		super.onCreate(savedInstanceState);
        	AppActivity.setMainActivity(this);
    	}

        public static void vibrate(int milliseconds)
        {
            Vibrator v = (Vibrator) getMainActivity().getSystemService(Context.VIBRATOR_SERVICE);
            if (getMainActivity().getSystemService(Context.VIBRATOR_SERVICE) != null)
            {
                v.vibrate(milliseconds);
            }
        }
    }

Hope this helped you!

Leave a Reply

Your email address will not be published.