توزیع میانافزار ساخته شده با NDK مشکلات دیگری را ایجاد میکند که توسعهدهندگان برنامهها نیازی به نگرانی در مورد آن ندارند. کتابخانه های از پیش ساخته شده برخی از انتخاب های پیاده سازی خود را به کاربران خود تحمیل می کنند.
انتخاب سطوح API و نسخه های NDK
کاربران شما نمی توانند از minSdkVersion کمتر از شما استفاده کنند. اگر برنامه های کاربران شما باید روی API 21 اجرا شوند، نمی توانید برای API 24 بسازید. اشکالی ندارد که کتابخانه خود را برای سطح API پایین تر از کاربران خود بسازید. می توانید برای API 16 بسازید و با کاربران API 21 خود سازگار بمانید.
نسخه های NDK تا حد زیادی با یکدیگر سازگار هستند، اما گاهی اوقات تغییراتی رخ می دهد که سازگاری را از بین می برد. اگر می دانید که همه کاربران شما از یک نسخه از NDK استفاده می کنند، بهتر است از همان نسخه ای استفاده کنید که آنها استفاده می کنند. در غیر این صورت از جدیدترین نسخه استفاده کنید.
با استفاده از STL
اگر در حال نوشتن C++ هستید و از STL استفاده میکنید، انتخاب شما بین libc++_shared
و libc++_static
بر کاربران شما تأثیر میگذارد، اگر یک کتابخانه مشترک را توزیع کنید. اگر یک کتابخانه مشترک توزیع می کنید، باید یا از libc++_shared
استفاده کنید یا مطمئن شوید که نمادهای libc++ توسط کتابخانه شما نمایش داده نمی شوند. بهترین راه برای انجام این کار این است که به صراحت سطح ABI خود را با یک نسخه اسکریپت اعلام کنید.
یکی دیگر از گزینه های کمتر قوی استفاده از -Wl,--exclude-libs,libc++_static.a -Wl,--exclude-libs,libc++abi.a
هنگام پیوند است. این کمتر قوی است زیرا فقط نمادهای موجود در کتابخانههایی را که به صراحت نامگذاری شدهاند پنهان میکند، و هیچ تشخیصی برای کتابخانههایی که استفاده نمیشوند گزارش نمیشود (اشتباه تایپی در نام کتابخانه یک خطا نیست، و این وظیفه بر عهده کاربر است که لیست کتابخانه را به روز نگه دارید). این رویکرد همچنین جزئیات پیاده سازی خود را پنهان نمی کند.
توزیع کتابخانه های بومی در AARs
افزونه Android Gradle می تواند وابستگی های بومی توزیع شده در AAR ها را وارد کند. اگر کاربران شما از افزونه Android Gradle استفاده می کنند، این ساده ترین راه برای آنها برای مصرف کتابخانه شما خواهد بود.
کتابخانه های بومی را می توان توسط AGP در یک AAR بسته بندی کرد. اگر کتابخانه شما قبلاً توسط externalNativeBuild ساخته شده باشد، این سادهترین گزینه خواهد بود.
ساختهای غیر AGP میتوانند از ndkports استفاده کنند، یا بستهبندی دستی را با پیروی از مستندات Prefab انجام دهند تا فهرست prefab/
فرعی AAR خود را ایجاد کنند.
میان افزار جاوا با کتابخانه های JNI
کتابخانههای جاوا که شامل کتابخانههای JNI هستند (به عبارت دیگر، AARهایی که حاوی jniLibs
هستند) باید مراقب باشند که کتابخانههای JNI که شامل میشوند با کتابخانههای دیگر در برنامه کاربر برخورد نکنند. برای مثال، اگر AAR شامل libc++_shared.so
باشد، اما نسخه متفاوتی از libc++_shared.so
با آنچه برنامه استفاده میکند، تنها یک مورد در APK نصب میشود و ممکن است منجر به رفتار غیرقابل اعتماد شود.
مطمئن ترین راه حل این است که کتابخانه های جاوا بیش از یک کتابخانه JNI را شامل نشوند (این توصیه خوبی برای برنامه ها نیز هست). همه وابستگی ها از جمله STL باید به صورت ایستا به کتابخانه پیاده سازی مرتبط شوند و یک نسخه اسکریپت باید برای اجرای سطح ABI استفاده شود. به عنوان مثال، یک کتابخانه جاوا com.example.foo
که شامل کتابخانه JNI libfooimpl.so
است باید از اسکریپت نسخه زیر استفاده کند:
LIBFOOIMPL {
global:
JNI_OnLoad;
local:
*;
};
این مثال از registerNatives
از طریق JNI_OnLoad
همانطور که در نکات JNI توضیح داده شده است استفاده می کند تا اطمینان حاصل شود که حداقل سطح ABI در معرض دید قرار می گیرد و زمان بارگذاری کتابخانه به حداقل می رسد.