Thursday, November 18, 2010

Chỉ dẫn lập trình game 3D trên Android (P2)

Bài hôm nay tôi sẽ hướng dẫn các bạn biên dịch native code trong ứng dụng Android.
JNI là viết tắt của Java Native Interface. Sử dụng JNI chúng ta có thể gọi các hàm được viết trong những ngôn ngữ khác từ Java.
Trước hết bạn tạo một Android project tạo một activity MainActivity:

package com.vndev.jni.activities;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import jni.Natives;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {
    private static final String LIB = "libch02.so";
    private static final String LIB_PATH = "/data/data/com.vndev.jni.activities/files/" + LIB;

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        try {

            // Install lib

            System.out.println("Installing LIB: " + LIB);

            // Copy lib from assests folder to files folder:

            // /data/data/PKG_NAME/files

            writeToStream(getAssets().open(LIB), openFileOutput(LIB, 0));

            // Load Lib

            System.load(LIB_PATH);

            // Run it

            String[] argv = { "MyLib", "arg1", "arg2" };

            Natives.LibMain(argv);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }



    /**

     * Write to a stream

     * 

     * @param in

     * @param out

     * @throws IOException

     */

    public static void writeToStream(InputStream in, OutputStream out)

            throws IOException {

        byte[] bytes = new byte[2048];

        for (int c = in.read(bytes); c != -1; c = in.read(bytes)) {

            out.write(bytes, 0, c);

        }

        in.close();

        out.close();

    }

}

Trong activity này ta sẽ load thư viện từ C vào bằng cách gọi:

System.load(LIB_PATH);


Activity này gọi một phương thức trong lớp Natives:
Natives.LibMain(argv);


Phương thức này được khai báo:
public static native int LibMain(String[] argv);


Phương thức này có từ khóa native, nó sẽ gọi phương thức LibMain trong thư viên được load ở trên.
Toàn bộ nội dung class Natives sẽ như sau:
package jni;

public class Natives {
    /**
     * Native Main Doom Loop
     * @param argv
     * @return
     */
    public static native int LibMain(String[] argv);
    
    /**
     * This fires on messages from the C layer
     * @param text
     */
    @SuppressWarnings("unused")
    private static void OnMessage(String text, int level) {
        System.out.println("OnMessage text:" + text + " level=" + level);
    }
}

Để tạo file header cho lớp này ta sử dụng javah trong java như sau
Javah -jni Natives


Khi đó ta có file header như sau
/* DO NOT EDIT THIS FILE - it is machine generated */

#include 

/* Header for class jni_Natives */



#ifndef _Included_jni_Natives

#define _Included_jni_Natives

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     jni_Natives

 * Method:    LibMain

 * Signature: ([Ljava/lang/String;)I

 */

JNIEXPORT jint JNICALL Java_jni_Natives_LibMain

  (JNIEnv *, jclass, jobjectArray);



//implements method call by java native



#ifdef __cplusplus

}

#endif

#endif



Giờ bạn cần tạo một file C khác dựa vào khai báo trên cài đặt phương thức này trong C và biên dịch chúng, chạy để thấy kết quả.

Download source

2 comments: