مفاهیم

قبل از شروع

این راهنما فرض می کند که شما قبلاً با مفاهیم ذاتی برنامه نویسی بومی و توسعه اندروید آشنا هستید.

مقدمه

این بخش توضیحی در سطح بالایی از نحوه عملکرد NDK ارائه می دهد. Android NDK مجموعه ای از ابزارها است که به شما امکان می دهد C یا C++ ("کد بومی") را در برنامه های اندروید خود جاسازی کنید. توانایی استفاده از کد بومی در برنامه های اندروید می تواند به ویژه برای توسعه دهندگانی که مایل به انجام یک یا چند مورد از موارد زیر هستند مفید باشد:

  • برنامه های آنها را بین پلتفرم ها منتقل کنید.
  • استفاده مجدد از کتابخانه های موجود، یا ارائه کتابخانه های خود برای استفاده مجدد.
  • افزایش عملکرد در موارد خاص، به ویژه موارد فشرده محاسباتی مانند بازی ها.

چگونه کار می کند

در این قسمت اجزای اصلی مورد استفاده در ساخت اپلیکیشن بومی اندروید معرفی شده و در ادامه مراحل ساخت و بسته بندی توضیح داده می شود.

اجزای اصلی

هنگام ساختن برنامه خود باید درک درستی از اجزای زیر داشته باشید:

  • کتابخانه های مشترک بومی: NDK این کتابخانه ها یا فایل های .so را از کد منبع C/C++ شما می سازد.

  • کتابخانه‌های استاتیک بومی: NDK همچنین می‌تواند کتابخانه‌های استاتیک یا فایل‌های .a بسازد که می‌توانید آن‌ها را به کتابخانه‌های دیگر پیوند دهید.

  • رابط بومی جاوا (JNI): JNI رابطی است که از طریق آن اجزای Java و C++ با یکدیگر صحبت می کنند. این راهنما دانش JNI را فرض می کند. برای اطلاعات در مورد آن، به مشخصات رابط بومی جاوا مراجعه کنید.

  • رابط باینری برنامه (ABI): ABI دقیقاً نحوه تعامل کد ماشین برنامه شما با سیستم را در زمان اجرا تعریف می کند. NDK فایل های .so را برخلاف این تعاریف می سازد. ABI های مختلف با معماری های مختلف مطابقت دارند: NDK شامل پشتیبانی ABI برای ARM 32 بیتی، AArch64، x86 و x86-64 است. برای اطلاعات بیشتر، Android ABIs را ببینید.

  • Manifest: اگر در حال نوشتن برنامه ای هستید که جز جاوا در آن وجود ندارد، باید کلاس NativeActivity را در مانیفست اعلام کنید. برای جزئیات بیشتر در مورد نحوه انجام این کار، به استفاده از رابط native_activity.h مراجعه کنید.

جریان

جریان کلی برای توسعه یک برنامه بومی برای اندروید به شرح زیر است:

  1. برنامه خود را طراحی کنید، تصمیم بگیرید که کدام بخش ها را در جاوا پیاده سازی کنید، و کدام قسمت ها را به عنوان کد اصلی پیاده سازی کنید.

  2. مانند هر پروژه اندرویدی دیگری، یک پروژه برنامه اندروید ایجاد کنید.

  3. اگر در حال نوشتن یک برنامه فقط بومی هستید، کلاس NativeActivity را در AndroidManifest.xml اعلام کنید. برای اطلاعات بیشتر، به فعالیت ها و برنامه های بومی مراجعه کنید.

  4. یک فایل Android.mk ایجاد کنید که کتابخانه بومی را توصیف می کند، از جمله نام، پرچم ها، کتابخانه های پیوند شده، و فایل های منبع برای کامپایل شدن در فهرست "JNI".

  5. به صورت اختیاری، می توانید یک فایل Application.mk ایجاد کنید که ABI های هدف، زنجیره ابزار، حالت انتشار/اشکال زدایی و STL را پیکربندی می کند. برای هر یک از این موارد که مشخص نکرده اید، به ترتیب از مقادیر پیش فرض زیر استفاده می شود:

    • ABI: همه ABI های منسوخ نشده
    • حالت: انتشار
    • STL: سیستم
  6. منبع اصلی خود را در فهرست jni پروژه قرار دهید.

  7. از ndk-build برای کامپایل کتابخانه های بومی ( .so ، .a ) استفاده کنید.

  8. کامپوننت جاوا را بسازید و فایل اجرایی .dex را تولید کنید.

  9. همه چیز را در یک فایل APK بسته بندی کنید، حاوی .so ، .dex و سایر فایل های مورد نیاز برای اجرای برنامه شما.

فعالیت ها و برنامه های بومی

Android SDK یک کلاس کمکی به نام NativeActivity ارائه می دهد که به شما امکان می دهد یک فعالیت کاملاً بومی بنویسید. NativeActivity ارتباط بین فریم ورک اندروید و کد بومی شما را مدیریت می کند، بنابراین مجبور نیستید آن را زیر کلاس بندی کنید یا متدهای آن را فراخوانی کنید. تنها کاری که باید انجام دهید این است که در فایل AndroidManifest.xml برنامه خود را بومی اعلام کنید و شروع به ایجاد برنامه بومی خود کنید.

یک برنامه اندرویدی با استفاده از NativeActivity هنوز در ماشین مجازی خودش اجرا می‌شود که از سایر برنامه‌ها جعبه‌بندی شده است. بنابراین همچنان می‌توانید از طریق JNI به APIهای فریمورک اندروید دسترسی داشته باشید. در موارد خاص، مانند حسگرها، رویدادهای ورودی و دارایی‌ها، NDK رابط‌های بومی را ارائه می‌کند که می‌توانید به جای تماس با JNI از آنها استفاده کنید. برای اطلاعات بیشتر در مورد چنین پشتیبانی، API های بومی را ببینید.

صرف نظر از اینکه در حال توسعه یک فعالیت بومی هستید یا خیر، توصیه می کنیم پروژه های خود را با ابزارهای سنتی ساخت اندروید ایجاد کنید. انجام این کار به ساخت و بسته بندی برنامه های اندروید با ساختار صحیح کمک می کند.

Android NDK دو انتخاب برای پیاده سازی فعالیت بومی خود در اختیار شما قرار می دهد:

  • هدر native_activity.h نسخه اصلی کلاس NativeActivity را تعریف می کند. این شامل رابط پاسخ به تماس و ساختارهای داده ای است که برای ایجاد فعالیت بومی خود به آنها نیاز دارید. از آنجایی که رشته اصلی برنامه شما پاسخگوی تماس ها را مدیریت می کند، اجرای پاسخ به تماس شما نباید مسدود شود. اگر آنها مسدود شوند، ممکن است خطاهای ANR (برنامه پاسخ نمی دهد) دریافت کنید زیرا رشته اصلی شما تا زمانی که تماس برگشتی برگردد پاسخگو نیست.
  • فایل android_native_app_glue.h یک کتابخانه کمکی ثابت را تعریف می کند که بر روی رابط native_activity.h ساخته شده است. این یک رشته دیگر ایجاد می کند، که مواردی مانند تماس ها یا رویدادهای ورودی را در یک حلقه رویداد مدیریت می کند. انتقال این رویدادها به یک رشته مجزا از مسدود کردن رشته اصلی شما در تماس‌های قبلی جلوگیری می‌کند.

منبع <ndk_root>/sources/android/native_app_glue/android_native_app_glue.c نیز موجود است که به شما امکان می‌دهد پیاده‌سازی را تغییر دهید.

برای اطلاعات بیشتر در مورد نحوه استفاده از این کتابخانه استاتیک، نمونه برنامه کاربردی Native-activity و مستندات آن را بررسی کنید. مطالعه بیشتر نیز در نظرات در فایل <ndk_root>/sources/android/native_app_glue/android_native_app_glue.h موجود است.

از رابط native_activity.h استفاده کنید

برای پیاده سازی یک فعالیت بومی با رابط native_activity.h :

  1. یک دایرکتوری jni/ در دایرکتوری ریشه پروژه خود ایجاد کنید. این فهرست همه کدهای اصلی شما را ذخیره می کند.

  2. فعالیت بومی خود را در فایل AndroidManifest.xml اعلام کنید.

    چون برنامه شما کد جاوا ندارد، android:hasCode روی false قرار دهید.

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

    باید ویژگی android:name تگ فعالیت را روی NativeActivity تنظیم کنید.

    <activity android:name="android.app.NativeActivity"
              android:label="@string/app_name">
    

    ویژگی android:value تگ meta-data نام کتابخانه مشترک حاوی نقطه ورود به برنامه (مانند C/C++ main )، با حذف پیشوند lib و پسوند .so از نام کتابخانه را مشخص می کند.

    <manifest>
      <application>
        <activity>
          <meta-data android:name="android.app.lib_name"
                     android:value="native-activity" />
          <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
        </activity>
      </application>
    </manifest>
    
  3. یک فایل برای فعالیت بومی خود ایجاد کنید و تابعی را که در متغیر ANativeActivity_onCreate نامگذاری شده است، پیاده سازی کنید. برنامه زمانی که فعالیت بومی شروع می شود، این تابع را فراخوانی می کند. این تابع، مشابه main در C/C++، یک اشاره‌گر به ساختار ANativeActivity دریافت می‌کند که شامل نشانگرهای تابع به پیاده‌سازی‌های مختلف پاسخ به تماس است که باید بنویسید. نشانگرهای تابع callback قابل اجرا در ANativeActivity->callbacks را برای پیاده سازی تماس های خود تنظیم کنید.

  4. فیلد ANativeActivity->instance را روی آدرس هر نمونه ای از داده های خاص که می خواهید استفاده کنید، تنظیم کنید.

  5. هر چیز دیگری را که می‌خواهید فعالیتتان در شروع کار انجام دهد، اجرا کنید.

  6. بقیه تماس‌هایی را که در ANativeActivity->callbacks تنظیم کرده‌اید، پیاده‌سازی کنید. برای اطلاعات بیشتر درباره زمان فراخوانی تماس‌های برگشتی، به مدیریت چرخه حیات فعالیت مراجعه کنید.

  7. بقیه برنامه خود را توسعه دهید.

  8. یک Android.mk file در دایرکتوری jni/ پروژه خود ایجاد کنید تا ماژول بومی خود را برای سیستم ساخت توصیف کنید. برای اطلاعات بیشتر به Android.mk مراجعه کنید.

  9. هنگامی که یک فایل Android.mk دارید، کد بومی خود را با استفاده از دستور ndk-build کامپایل کنید.

    cd <path>/<to>/<project>
    $NDK/ndk-build
    
  10. پروژه اندروید خود را طبق معمول بسازید و نصب کنید. اگر کد اصلی شما در دایرکتوری jni/ است، اسکریپت ساخت به طور خودکار فایل(های) .so ساخته شده از آن را در APK بسته بندی می کند.

کد نمونه اضافی

برای دانلود نمونه های NDK، به نمونه های NDK مراجعه کنید.