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 .c
kaynak 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); } }