Ara katman yazılımları satıcıları için öneriler

NDK ile oluşturulan ara katman yazılımları dağıtmak, uygulama geliştiricilerin endişelenmelerine gerek olmayan bazı ek sorunları ortaya çıkarır. Önceden oluşturulmuş kitaplıklar, kullanıcılara uygulama seçeneklerinden bazılarını uygular.

API düzeylerini ve NDK sürümlerini seçme

Kullanıcılarınız sizinkinden daha düşük bir minSdkVersion kullanamaz. Kullanıcılarınızın uygulamalarının API 21 üzerinde çalışması gerekiyorsa API 24 için uygulama geliştiremezsiniz. Kitaplığınızı, kullanıcılarınızdan daha düşük bir API düzeyi için derleyebilirsiniz. API 16 için uygulama geliştirebilir ve API 21 kullanıcılarınızla uyumlu olmaya devam edebilirsiniz.

NDK sürümleri birbirleriyle büyük ölçüde uyumludur ancak bazen uyumluluğu bozan değişiklikler olabilir. Tüm kullanıcılarınızın NDK'nın aynı sürümünü kullandığını biliyorsanız en iyisi onlarla aynı sürümü kullanmaktır. Aksi takdirde, en yeni sürümü kullanın.

STL'yi kullanma

C++ yazıyorsanız ve STL kullanıyorsanız libc++_shared ile libc++_static arasındaki seçim, paylaşılan bir kitaplığı dağıtmanız durumunda kullanıcılarınızı etkiler. Paylaşılan bir kitaplığı dağıtıyorsanız libc++_shared kullanmanız veya libc++ sembollerinin kitaplığınızda gösterilmemesini sağlamanız gerekir. Bunu yapmanın en iyi yolu, ABI yüzeyinizi bir sürüm komut dosyasıyla açıkça beyan etmektir (bu, uygulama ayrıntılarınızın gizli tutulmasına da yardımcı olur). Örneğin, basit bir aritmetik kitaplığında şu sürüm komut dosyası olabilir:

LIBMYMATH {
global:
    add;
    sub;
    mul;
    div;
    # C++ symbols in an extern block will be mangled automatically. See
    # https://stackoverflow.com/a/21845178/632035 for more examples.
    extern "C++" {
        "pow(int, int)";
    }
local:
    *;
};

Simge görünürlüğünü kontrol etmenin en sağlam yolu olduğu için sürüm komut dosyası tercih edilmelidir. Bu, uygulama ayrıntılarınızın açığa çıkmasını önlediğinden ve yükleme süresini kısalttığından, ara katman yazılımları olsun veya olmasın tüm paylaşılan kitaplıklar için en iyi uygulamadır.

Diğer bir daha az etkili seçenek, bağlantı oluştururken -Wl,--exclude-libs,libc++_static.a -Wl,--exclude-libs,libc++abi.a kullanmaktır. Bu, yalnızca açıkça adlandırılmış kitaplıklardaki sembolleri gizleyeceğinden ve kullanılmayan kitaplıklar için teşhis bildirilmediğinden (kitaplık adında yazım hatası olması bir hata değildir ve kitaplık listesini güncel tutma sorumluluğu kullanıcının üzerindedir) daha az güçlüdür. Bu yaklaşım, kendi uygulama ayrıntılarınızı da gizlemez.

AAR'lerde yerel kitaplıkları dağıtma

Android Gradle eklentisi, AAR'lerde dağıtılan yerel bağımlılıkları içe aktarabilir. Kullanıcılarınız Android Gradle eklentisini kullanıyorsa bu, kitaplığınızı kullanmalarının en kolay yoludur.

Yerel kitaplıklar, AGP tarafından AAR'ye paketlenebilir. Kitaplığınız zaten externalNativeBuild tarafından derlenmişse bu en kolay seçenek olacaktır.

AGP olmayan derlemeler ndkports kullanabilir veya AAR'lerinin prefab/ alt dizinini oluşturmak için Prefab dokümanlarındaki talimatları uygulayarak manuel paketleme gerçekleştirebilir.

JNI kitaplıkları olan Java ara katman yazılımı

JNI kitaplıkları (yani jniLibs içeren AAR'ler) içeren Java kitaplıklarının, içerdikleri JNI kitaplıklarının kullanıcının uygulamasındaki diğer kitaplıklarla çakışmayacağından emin olması gerekir. Örneğin, AAR libc++_shared.so içeriyorsa ancak uygulamanın kullandığından farklı bir libc++_shared.so sürümü içeriyorsa APK'ya yalnızca biri yüklenir ve bu durum güvenilir olmayan davranışlara yol açabilir.

En güvenilir çözüm, Java kitaplıklarının bir'den fazla JNI kitaplığı eklenmemesidir (bu, uygulamalar için de iyi bir öneridir). STL dahil tüm bağımlılıklar uygulama kitaplığına statik olarak bağlanmalı ve ABI yüzeyini uygulamak için bir sürüm komut dosyası kullanılmalıdır. Örneğin, libfooimpl.so JNI kitaplığını içeren bir Java kitaplığı com.example.foo aşağıdaki sürüm komut dosyasını kullanmalıdır:

LIBFOOIMPL {
global:
    JNI_OnLoad;
local:
    *;
};

Bu örnekte, minimum ABI yüzeyinin açığa çıkmasını ve kitaplık yükleme süresinin en aza indirilmesini sağlamak için JNI İpuçları bölümünde açıklandığı gibi JNI_OnLoad üzerinden registerNatives kullanılmıştır.