المفاهيم

قبل البدء

يفترض هذا الدليل أنك على دراية بالمفاهيم الكامنة في البرمجة الأصلية وفي تطوير Android.

مقدّمة

يقدم هذا القسم شرحًا عالي المستوى لكيفية عمل NDK. إن Android NDK هو مجموعة من أدوات تسمح لك بتضمين لغة C أو C++ ("رموز برمجية أصلية") في تطبيقات Android. ستساعدك القدرة على استخدام يمكن أن تكون الرموز البرمجية الأصلية في تطبيقات Android مفيدة بشكل خاص للمطوّرين الذين يريدون تنفيذ واحدة أو أكثر من ما يلي:

  • نقل تطبيقاتهم بين الأنظمة الأساسية
  • إعادة استخدام المكتبات الحالية أو تقديم مكتبات خاصة بها لإعادة استخدامها.
  • تحسين الأداء في بعض الحالات، خاصةً من الناحية الحسابية مثل الألعاب.

آلية العمل

يتناول هذا القسم المكونات الأساسية المستخدمة في إنشاء إعلان تطبيقات Android، وتتابع وصف عملية إنشاء العبوة.

المكوّنات الرئيسية

يجب أن تكون على دراية بالمكونات التالية أثناء إنشاء التطبيق:

  • المكتبات المشتركة الأصلية: ينشئ NDK هذه المكتبات، أو الملفات .so، من رمز مصدر C/C++.

  • المكتبات الثابتة الأصلية: بإمكان NDK أيضًا إنشاء مكتبات ثابتة، أو .a من الملفات، والتي يمكنك ربطها بمكتبات أخرى.

  • واجهة Java الأصلية (JNI): إنّ JNI هي الواجهة التي يتم من خلالها تشغيل ملفات Java تتحدث مكونات C++ مع بعضها البعض. يفترِض هذا الدليل معلومات عن مبادرة JNI. للحصول على معلومات حول الترميز، يمكنك الاطّلاع على مواصفات واجهة Java الأصلية.

  • واجهة التطبيق الثنائية (ABI): تحدِّد واجهة التطبيق الثنائية (ABI) بدقة كيفية يُتوقع أن يتفاعل الرمز البرمجي للجهاز مع النظام في وقت التشغيل. مؤسسة NDK تنشئ .so ملف بالاستناد إلى هذه التعريفات. تتوافق واجهات التطبيق الثنائية (ABI) المختلفة مع بُنى مختلفة: يشمل NDK دعم واجهة التطبيق الثنائية (ABI) لـ ARM 32 بت، وAArch64، وx86 وx86-64. لمزيد من المعلومات، راجع Android واجهات التطبيق الثنائية (ABI).

  • البيان: إذا كنت تكتب تطبيقًا لا يتضمن مكون Java، فيجب عليك أفصح عن الفئة NativeActivity في . راجع استخدام الأصلية. لمزيد من التفاصيل حول كيفية إجراء ذلك.

تدفق

في ما يلي الخطوات العامة لتطوير تطبيق محلي لنظام Android:

  1. تصميم تطبيقك، وتحديد الأجزاء المطلوب تنفيذها في Java، وأجزاء التطبيق تنفيذه كرمز برمجي أصلي.

  2. أنشِئ مشروعًا لتطبيق Android كما تفعل مع أي مشروع Android آخر.

  3. إذا كنت تكتب تطبيقًا مدمجًا مع المحتوى فقط، يجب تحديد فئة NativeActivity في AndroidManifest.xml للحصول على مزيد من المعلومات، يمكنك الاطّلاع على الأنشطة المدمجة مع المحتوى التطبيقات.

  4. إنشاء ملف Android.mk يصف المكتبة الأصلية، بما في ذلك الاسم والمكتبات المرتبطة وملفات المصدر المطلوب تجميعها في "JNI" الدليل.

  5. اختياريًا، يمكنك إنشاء ملف Application.mk لضبط الهدف. واجهات التطبيق الثنائية (ABI) وسلسلة الأدوات ووضع الإصدار/تصحيح الأخطاء وSTL بالنسبة إلى أي من هذه الطرق عدم التحديد، يتم استخدام القيم التلقائية التالية، على التوالي:

    • واجهة التطبيق الثنائية (ABI): جميع واجهات التطبيق الثنائية (ABI) التي لم يتم إيقافها نهائيًا
    • الوضع: إصدار
    • STL: النظام
  6. ضع المصدر الأصلي ضمن دليل jni للمشروع.

  7. يمكنك استخدام ndk-build لتجميع المكتبات الأصلية (.so و.a).

  8. أنشِئ مكوّن Java، وأنشِئ ملف .dex القابل للتنفيذ.

  9. تجميع كل المحتوى في ملف APK يتضمّن .so و.dex وغير ذلك الملفات اللازمة لتشغيل تطبيقك.

الأنشطة والتطبيقات المحلية

وتوفر حزمة تطوير البرامج (SDK) لنظام التشغيل Android فئة مساعد، NativeActivity، التي تتيح لك لكتابة نشاط أصلي تمامًا. تتولى NativeActivity معالجة الاتصال. بين إطار عمل Android والرمز البرمجي الأصلي، وبذلك لن تكون هناك حاجة إلى وفئاتها الفرعية أو استدعاء طرقها. ما عليك سوى الإفصاح عن طلبك. الأصلية في ملف AndroidManifest.xml، والبدء في إنشاء التطبيق.

لا يزال تطبيق Android الذي يستخدم NativeActivity يعمل في نشاطه الافتراضي الخاص الجهاز، في وضع الحماية من التطبيقات الأخرى. وبالتالي، لا يزال بإمكانك الوصول إلى واجهات برمجة التطبيقات لإطار عمل Android من خلال JNI. في بعض الحالات، مثل أدوات الاستشعار، وأحداث الإدخال ومواد العرض، فإن NDK توفر واجهات أصلية يمكنك استخدامها بدلاً من الاضطرار إلى الاتصال عبر JNI. لمزيد من المعلومات حول يمكنك الاطّلاع على واجهات برمجة التطبيقات الأصلية.

بغض النظر عما إذا كنت تطوّر نشاطًا أصليًا أم لا، ننصحك في إنشاء المشاريع باستخدام أدوات التصميم التقليدية من Android. إجراء ذلك في ضمان إنشاء تطبيقات Android وتغليفها بالتوافق مع البنية.

يوفّر لك 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 المصدر أيضًا، ما يسمح لك بتعديل عملية التنفيذ.

لمزيد من المعلومات حول كيفية استخدام هذه المكتبة الثابتة، يمكنك مراجعة نموذج التطبيق الخاص بالنشاط الأصلي ومستنداته تُعد القراءة الإضافية متاحًا أيضًا في التعليقات في <ndk_root>/sources/android/native_app_glue/android_native_app_glue.h الملف.

استخدام واجهة local_activity.h

لتنفيذ نشاط مدمج مع المحتوى باستخدام واجهة native_activity.h:

  1. أنشِئ دليل jni/ في الدليل الجذري لمشروعك. هذا الدليل تقوم بتخزين كل التعليمات البرمجية الأصلية.

  2. يمكنك تعريف نشاطك الأصلي في ملف AndroidManifest.xml.

    بما أنّ تطبيقك لا يحتوي على رمز Java، يجب ضبط 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 التي تحتوي على مؤشرات للوظائف إلى عمليات تنفيذ معاودة الاتصال المختلفة التي تحتاج إلى كتابتها. ضبط مؤشرات دالة رد الاتصال القابلة للتطبيق في 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. إنشاء مشروع Android وتثبيته كالمعتاد إذا كان الرمز الأصلي بلغة دليل jni/، سيجمع النص البرمجي للإصدار .so تلقائيًا الملفات التي تم إنشاؤها منه في حزمة APK.

رمز نموذجي إضافي

لتنزيل نماذج NDK، يُرجى الاطّلاع على نماذج NDK.