Örnek: yerel-etkinlik

Yerel etkinlik örneği, Klasörde NDK örnekleri kökü native-activity. Bu, tamamen doğal bir ortamda olmanın çok basit bir örneği. (Java kaynak kodu olmadan) başvurur. Herhangi bir Java kaynağı yoksa Java derleyici, sanal makinenin çalışması için hâlâ yürütülebilir bir saplama oluşturuyor. Saplama, .so konumunda bulunan gerçek, yerel program için bir sarmalayıcı işlevi görür dosyası olarak kaydedebilirsiniz.

Uygulamanın kendisi tüm ekranı renklendiriyor ve ardından, algıladığı harekete karşılık olarak rengi kısmen değiştirir.

AndroidManifest.xml

Yalnızca yerel koda sahip uygulamalar, API düzeyi 9'dan düşük olan bir Android API düzeyi belirtemez. NativeActivity çerçeve sınıfını kullanabilirsiniz.

<uses-sdk android:minSdkVersion="9" />

Aşağıdaki satırda android:hasCode bu uygulama için yalnızca false olarak tanımlandığından Java değil, yerel kod.

<application android:label="@string/app_name"
android:hasCode="false">

Bir sonraki satırda NativeActivity sınıfı tanımlanır.

<activity android:name="android.app.NativeActivity"

Son olarak, manifest dosyasında kullanılacak paylaşılan kitaplığın adı olarak android:value değerini belirtir: (ilk lib ve .so uzantısı çıkarılarak) Bu değer aşağıdakiyle aynı olmalıdır: Android.mk dilindeki LOCAL_MODULE adı.

<meta-data android:name="android.app.lib_name"
        android:value="native-activity" />

Android.mk

Bu dosya, oluşturulacak paylaşılan kitaplığın adını sağlayarak başlar.

LOCAL_MODULE    := native-activity

Daha sonra yerel kaynak kodu dosyasının adını tanımlar.

LOCAL_SRC_FILES := main.c

Ardından, derleme sisteminin ikili dosyayı oluştururken kullanacağı harici kitaplıkları listeler. İlgili içeriği oluşturmak için kullanılan -l (karşıt bağlantı) seçeneği her kitaplık adından önce gelir.

  • log, bir günlük kaydı kitaplığıdır.
  • android, NDK için standart Android destek API'lerini kapsar. Daha fazla bilgi için tarafından desteklenen API'ler için bkz. Android NDK Yerel API'ler.
  • EGL, grafik API'sinin platforma özel bölümüne karşılık gelir.
  • GLESv1_CM, Android için OpenGL sürümü olan OpenGL ES'ye karşılık gelir. Bu kitaplık EGL'ye bağlıdır.

Her kitaplık için:

  • Gerçek dosya adı lib ile başlar ve şununla biter: .so uzantısı. Örneğin, log kitaplığı liblog.so.
  • Kitaplık şu dizinde, yani NDK kökünde bulunur: <ndk>/platforms/android-<sdk_version>/arch-<abi>/usr/lib/
LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM

Sonraki satırda statik kitaplığın adı verilir (android_native_app_glue). uygulama, NativeActivity yaşam döngüsü olaylarını ve dokunmatik girişi yönetmek için kullanır.

LOCAL_STATIC_LIBRARIES := android_native_app_glue

Son satır, derleme sistemine bu statik kitaplığı oluşturmasını söyler. ndk-build komut dosyası, oluşturulan kitaplığı yerleştirir (libandroid_native_app_glue.a) obj dizinine eklendi oluşturulan bir örnektir. android_native_app_glue hakkında daha fazla bilgi için kitaplığının android_native_app_glue.h başlığına ve ilgili .ckaynak dosyasına bakın.

$(call import-module,android/native_app_glue)

Android.mk dosyası hakkında daha fazla bilgi için bkz. Android.mk.

ana.k

Bu dosya temelde programın tamamını içerir.

Aşağıdakiler, hem paylaşılan hem de statik kitaplıklara karşılık gelir Android.mk içinde numaralanmıştır.

#include <EGL/egl.h>
#include <GLES/gl.h>


#include <android/sensor.h>
#include <android/log.h>
#include <android_native_app_glue>

android_native_app_glue kitaplığı aşağıdaki işlevi çağırır: bir durum yapısı aktarın. Aynı zamanda dosya, NativeActivity geri çağırmasının işlenmesini kolaylaştırır.

void android_main(struct android_app* state) {

Daha sonra program birleştirici kitaplığı tarafından sıraya alınan etkinlikleri işler. Etkinlik işleyicisi durum yapısını izler.

struct engine engine;



// Suppress link-time optimization that removes unreferenced code
// to make sure glue isn't stripped.
app_dummy();


memset(&engine, 0, sizeof(engine));
state->userData = &engine;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
engine.app = state;

Uygulama, sensörleri izlemeye başlamak için sensor.h ürününde API'ler.

    engine.sensorManager = ASensorManager_getInstance();
    engine.accelerometerSensor =
                    ASensorManager_getDefaultSensor(engine.sensorManager,
                        ASENSOR_TYPE_ACCELEROMETER);
    engine.sensorEventQueue =
                    ASensorManager_createEventQueue(engine.sensorManager,
                        state->looper, LOOPER_ID_USER, NULL, NULL);

Ardından bir döngü başlar. Bu döngüde uygulama, mesajları (sensör etkinlikleri). Mesajları şuraya gönderir: android_native_app_glue: eşleşme olup olmadığını kontrol eder. android_main içinde tanımlanan tüm onAppCmd etkinlikleri. Bir eşleşmesi gerçekleşirse mesaj yürütülmek üzere işleyiciye gönderilir.

while (1) {
        // Read all pending events.
        int ident;
        int events;
        struct android_poll_source* source;


        // If not animating, we will block forever waiting for events.
        // If animating, we loop until all events are read, then continue
        // to draw the next frame of animation.
        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL,
                &events,
                (void**)&source)) >= 0) {


            // Process this event.
            if (source != NULL) {
                source->process(state, source);
            }


            // If a sensor has data, process it now.
            if (ident == LOOPER_ID_USER) {
                if (engine.accelerometerSensor != NULL) {
                    ASensorEvent event;
                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
                            &event, 1) > 0) {
                        LOGI("accelerometer: x=%f y=%f z=%f",
                                event.acceleration.x, event.acceleration.y,
                                event.acceleration.z);
                    }
                }
            }


        // Check if we are exiting.
        if (state->destroyRequested != 0) {
            engine_term_display(&engine);
            return;
        }
    }

Sıra boşalıp program yoklama döngüsünden çıktığında programı ekranı çizmek için OpenGL’yi çağırır.

    if (engine.animating) {
        // Done with events; draw next animation frame.
        engine.state.angle += .01f;
        if (engine.state.angle > 1) {
            engine.state.angle = 0;
        }


        // Drawing is throttled to the screen update rate, so there
        // is no need to do timing here.
        engine_draw_frame(&engine);
    }
}