FacebookTwitterGoogle+Share

Trigger vibration on Android from Heaps/Hashlink

I wanted to trigger vibrations in Hexlock – so I did, and here’s how! I am not saying this is the best, correct, or even a good way to go about it. It’s just what I did. Maybe it will help.

I added a static function to my Main class, the idea being that it would do nothing unless I was compiling for Android. (I added -D android to my compile-to-c.hxml for just this purpose). There may already be a hlNative one, but who knows at this point. I didn’t see one, and adding -D android was easy enough.

#if android
@:hlNative("Java_io_heaps_android_HeapsActivity")
#end
public static function vibrate(i:Int) : Void { }

When compiling to C code for Hashlink, calls to that function (Main.vibrate(i)) get replaced with Java_io_heaps_android_HeapsActivity_vibrate(i), which I defined in my jni.c1 file.

JNIEXPORT void JNICALL Java_io_heaps_android_HeapsActivity_vibrate(int duration) {
    (*jvm)->AttachCurrentThread(jvm, &thisEnv, 0); 
    jclass cls = (*thisEnv)->FindClass(thisEnv, "io/heaps/android/HeapsActivity");
    jmethodID method = (*thisEnv)->GetStaticMethodID(thisEnv, cls, "vibrate", "(I)V");

    __android_log_print(ANDROID_LOG_DEBUG, "JNI.c", "Vibrating: %d", duration);

    if (method > 0)
        (*thisEnv)->CallStaticVoidMethod(thisEnv, cls, method, duration);
}

You’re probably wondering where thisEnv comes from, and if you are I can help! I modified my startHL() function to be:

JNIEnv* thisEnv; // I want access to these from other functions
JavaVM  *jvm;
  
 
JNIEXPORT int JNICALL Java_io_heaps_android_HeapsActivity_startHL(JNIEnv* env, jclass cls) {
    thisEnv=env; // Store the JNIEnv for later use
    (*env)->GetJavaVM(env, &jvm); // Also the JVM
     return main(0, NULL);
}

As you can see from two functions back, the code assumes there is a vibrate() function in io.heaps.android.HeapsActivity, and there is, because I added one.

    static public void vibrate(int duration) {
        Log.d("HeapsActivity.java", "static vibration call");
        Vibrator v = (Vibrator)instance.getSystemService(Context.VIBRATOR_SERVICE);
        v.vibrate((long)duration);
    }

And now it vibrates! You can find out more about the files I’m referencing (including a Git repo hosting them) here.

Comments

You must be logged in to post a comment.