توضّح لك هذه الصفحة كيفية ضبط صيغ الإصدار لإنشاء إصدارات مختلفة من تطبيقك من مشروع واحد وكيفية إدارة التبعيات وإعدادات التوقيع بشكل صحيح.
يمثّل كل صيغة إصدار إصدارًا مختلفًا من تطبيقك يمكنك إنشاؤه. على سبيل المثال، قد تريد إنشاء إصدار واحد من تطبيقك يكون مجانيًا ويتضمّن مجموعة محدودة من المحتوى، وإصدار آخر مدفوع يتضمّن المزيد من المحتوى. يمكنك أيضًا إنشاء إصدارات مختلفة من تطبيقك تستهدف أجهزة مختلفة، استنادًا إلى مستوى واجهة برمجة التطبيقات أو أنواع الأجهزة الأخرى.
إنّ خيارات التصميم هي نتيجة استخدام Gradle لمجموعة محدّدة من القواعد لدمج الإعدادات والرموز والموارد التي تم ضبطها في أنواع الإصدارات ونكهات المنتجات. على الرغم من أنّك لا تضبط خيارات الإصدار مباشرةً، يمكنك ضبط أنواع الإصدارات وأنواع المنتجات التي تشكلها.
على سبيل المثال، قد يحدِّد نوع المنتج "إصدار تجريبي" ميزات معيّنة
ومتطلبات الجهاز، مثل رمز المصدر المخصّص والموارد والحد الأدنى
لمستويات واجهة برمجة التطبيقات، في حين يطبِّق نوع الإصدار "تصحيح الأخطاء" إعدادات مختلفة للإصدار
والتعبئة، مثل خيارات تصحيح الأخطاء ومفاتيح التوقيع. إنّ
خيار الإصدار الذي يجمع هذين الخيارَين هو إصدار "demoDebug" من تطبيقك، ويتضمّن
مجموعة من الإعدادات والموارد المضمّنة في خيار main/
لإصدار المنتج ونوع الإصدار "debug" ومجموعة مصادر main/
.
ضبط أنواع الإصدار
يمكنك إنشاء أنواع إنشاءات وضبطها داخل الجزء android
من ملف build.gradle.kts
على مستوى الوحدة. عند إنشاء
وحدة جديدة، ينشئ "استوديو Android" تلقائيًا نوعَي الإصدار المخصّص لتصحيح الأخطاء والإصدار العلني. مع أنّ نوع إصدار تصحيح الأخطاء لا يظهر في ملف إعداد الإصدار، يعمل "استوديو Android" على ضبطه باستخدام debuggable
true
. يتيح لك ذلك تصحيح أخطاء التطبيق على أجهزة Android الآمنة ويؤدي إلى
ضبط ميزة "توقيع التطبيق" باستخدام متجر مفاتيح عام لتصحيح الأخطاء.
يمكنك إضافة نوع الإصدار المخصّص لتصحيح الأخطاء إلى الإعدادات إذا كنت تريد إضافة
أو تغيير إعدادات معيّنة. يحدِّد النموذج التالي
applicationIdSuffix
لنوع الإصدار المخصّص لتصحيح الأخطاء ويضبط
نوع إصدار "الإصدار التجريبي" الذي يتم إعداده باستخدام الإعدادات من نوع الإصدار المخصّص لتصحيح الأخطاء:
Kotlin
android { defaultConfig { manifestPlaceholders["hostName"] = "www.example.com" ... } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") } getByName("debug") { applicationIdSuffix = ".debug" isDebuggable = true } /** * The `initWith` property lets you copy configurations from other build types, * then configure only the settings you want to change. This one copies the debug build * type, and then changes the manifest placeholder and application ID. */ create("staging") { initWith(getByName("debug")) manifestPlaceholders["hostName"] = "internal.example.com" applicationIdSuffix = ".debugStaging" } } }
رائع
android { defaultConfig { manifestPlaceholders = [hostName:"www.example.com"] ... } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { applicationIdSuffix ".debug" debuggable true } /** * The `initWith` property lets you copy configurations from other build types, * then configure only the settings you want to change. This one copies the debug build * type, and then changes the manifest placeholder and application ID. */ staging { initWith debug manifestPlaceholders = [hostName:"internal.example.com"] applicationIdSuffix ".debugStaging" } } }
ملاحظة: عند إجراء تغييرات على ملف إعدادات الإصدار، يطلب منك Android Studio مزامنة مشروعك مع الإعدادات الجديدة. لمزامنة مشروعك، انقر على المزامنة الآن في شريط الإشعارات الذي يظهر عند إجراء تغيير أو انقر على مزامنة المشروع من شريط الأدوات. إذا لاحظ "استوديو Android" أي أخطاء في الإعدادات، ستظهر نافذة الرسائل لوصف المشكلة.
لمعرفة المزيد من المعلومات عن جميع السمات التي يمكنك ضبطها باستخدام أنواع الإصدارات،
اطّلِع على مرجع
BuildType
.
ضبط نكهات المنتجات
يشبه إنشاء أنواع المنتجات إنشاء أنواع الإصدارات. أضِف أنواع المنتجات إلى العنصر
productFlavors
في إعدادات الإصدار وأدرِج الإعدادات التي تريدها.
تتوافق نكهات المنتج مع سمات defaultConfig
نفسها، لأنّ defaultConfig
تنتمي في الواقع إلى فئة
ProductFlavor
. وهذا يعني أنّه يمكنك تقديم الإعدادات الأساسية
لجميع النُسخ في العنصر defaultConfig
، ويمكن لكل نسخة تغيير أيّ من هذه القيم التلقائية، مثل applicationId
. للحصول على
مزيد من المعلومات عن رقم تعريف التطبيق، يُرجى الاطّلاع على مقالة
ضبط رقم تعريف التطبيق.
ملاحظة: لا يزال عليك تحديد اسم حزمة باستخدام سمة
package
في ملف بيان main/
. يجب أيضًا استخدام اسم الحزمة
هذا في رمز المصدر للإشارة إلى فئة R
أو لحلّ أي تسجيل
لنشاط أو خدمة ذات صلة. يتيح لك ذلك استخدام applicationId
لمنح كلّ نكهة من نكهات المنتج معرّفًا فريدًا لتعبئتها وتوزيعها بدون الحاجة إلى تغيير رمز المصدر.
يجب أن تنتمي جميع النكهات إلى سمة النكهة المسماة، وهي مجموعة من نكهات المنتجات. يجب تخصيص جميع النكهات لسمة نكهة، وإلا سيظهر لك خطأ الإنشاء التالي.
Error: All flavors must now belong to a named flavor dimension. The flavor 'flavor_name' is not assigned to a flavor dimension.
إذا كانت وحدة معيّنة تحديد سمة نكهة واحدة فقط، يحدّد المكوّن الإضافي لـ Android Gradle تلقائيًا جميع نكهات الوحدة لهذه السمة.
ينشئ نموذج الرمز البرمجي التالي سمة إصدار باسم "الإصدار" ويضيف
إصدارَي المنتج "تجريبي" و "كامل". تقدّم هذه النكهات
applicationIdSuffix
و
versionNameSuffix
الخاصة بها:
Kotlin
android { ... defaultConfig {...} buildTypes { getByName("debug"){...} getByName("release"){...} } // Specifies one flavor dimension. flavorDimensions += "version" productFlavors { create("demo") { // Assigns this product flavor to the "version" flavor dimension. // If you are using only one dimension, this property is optional, // and the plugin automatically assigns all the module's flavors to // that dimension. dimension = "version" applicationIdSuffix = ".demo" versionNameSuffix = "-demo" } create("full") { dimension = "version" applicationIdSuffix = ".full" versionNameSuffix = "-full" } } }
رائع
android { ... defaultConfig {...} buildTypes { debug{...} release{...} } // Specifies one flavor dimension. flavorDimensions "version" productFlavors { demo { // Assigns this product flavor to the "version" flavor dimension. // If you are using only one dimension, this property is optional, // and the plugin automatically assigns all the module's flavors to // that dimension. dimension "version" applicationIdSuffix ".demo" versionNameSuffix "-demo" } full { dimension "version" applicationIdSuffix ".full" versionNameSuffix "-full" } } }
ملاحظة: إذا كان لديك تطبيق قديم (تم إنشاؤه قبل
آب/أغسطس 2021) توزّعه باستخدام حِزم APK على Google Play، يمكنك توزيع تطبيقك باستخدام ميزة دعم حِزم APK المتعدّدة في Google Play من خلال ضبط القيمة applicationId
نفسها على جميع الصيغ ومنح كل صيغة قيمة مختلفة
versionCode
. لتوزيع
خيارات مختلفة من تطبيقك كتطبيقات منفصلة في Google Play، عليك منح
كل خيار قيمة مختلفة من applicationId
.
بعد إنشاء أنواع المنتجات وضبطها، انقر على مزامنة
الآن في شريط الإشعارات. بعد اكتمال المزامنة، تنشئ Gradle
تلقائيًا أنواع الإصدارات استنادًا إلى أنواع الإصدارات وأنواع
المنتجات، وتسميها وفقًا لملف
<product-flavor><Build-Type>
. على سبيل المثال، إذا
أنشأت نكهات المنتج "تجريبي" و "كامل"، واحتفظت بأنواع الإنشاء الافتراضية
"تصحيح أخطاء" و
"إصدار"، تنشئ Gradle صيغ الإنشاء التالية:
-
demoDebug
-
demoRelease
-
fullDebug
-
fullRelease
لتحديد صيغة الإصدار المطلوب إنشاؤها وتشغيلها، انتقِل إلى إنشاء > اختيار صيغة الإصدار واختَر صيغة الإصدار من القائمة. لبدء تخصيص كلّ خيار من خيارات الإصدار باستخدام الميزات والموارد الخاصة به، عليك إنشاء مجموعات موارد ملف المصدر وإدارتها، كما هو موضّح في هذه الصفحة.
تغيير رقم تعريف التطبيق لصِيَغ الإصدار
عند إنشاء حزمة APK أو حزمة AAB لتطبيقك، تضع أدوات الإنشاء علامة على التطبيق باستخدام
رقم تعريف التطبيق المحدَّد في العنصر defaultConfig
من ملفbuild.gradle.kts
، كما هو موضّح في المثال التالي. ومع ذلك، إذا كنت تريد إنشاء إصدارات مختلفة من
تطبيقك لتظهر كبيانات منفصلة في "متجر Google Play"، مثل إصدار "مجاني" وإصدار
"مدفوع"، عليك إنشاء
صيغ إصدار منفصلة لكل منها
معرّف تطبيق مختلف.
في هذه الحالة، حدِّد كل خيار من خيارات الإصدار على أنّه
نكهة منتج منفصلة. يمكنك إعادة تعريف السمة applicationId
لكل صيغة ضمن مجموعة productFlavors
أو إلحاق شريحة بمعرّف التطبيق التلقائي باستخدام applicationIdSuffix
، كما هو موضّح أدناه:
Kotlin
android { defaultConfig { applicationId = "com.example.myapp" } productFlavors { create("free") { applicationIdSuffix = ".free" } create("pro") { applicationIdSuffix = ".pro" } } }
رائع
android { defaultConfig { applicationId "com.example.myapp" } productFlavors { free { applicationIdSuffix ".free" } pro { applicationIdSuffix ".pro" } } }
بهذه الطريقة، يكون معرّف التطبيق لإصدار المنتج "المجاني" هو "com.example.myapp.free".
يمكنك أيضًا استخدام applicationIdSuffix
لإضافة شريحة استنادًا إلى نوع الإصدار، كما هو موضّح هنا:
Kotlin
android { ... buildTypes { getByName("debug") { applicationIdSuffix = ".debug" } } }
رائع
android { ... buildTypes { debug { applicationIdSuffix ".debug" } } }
ولأنّ Gradle يطبّق إعداد نوع التصميم بعد صيغة المنتج، يكون معرّف التطبيق لصيغة الإصدار "free debug" هو "com.example.myapp.free.debug". يكون هذا مفيدًا عندما تريد تثبيت كل من ملف debugging وملف الإصدار على الجهاز نفسه، لأنّه لا يمكن أن يتضمّن تطبيقان رقم تعريف التطبيق نفسه.
إذا كان لديك تطبيق قديم (تم إنشاؤه قبل آب (أغسطس) 2021) توزّعه باستخدام حِزم APK على Google Play، وأردت استخدام بطاقة بيانات التطبيق نفسها لتوزيع حِزم APK متعددة تستهدف كلّ منها إعدادات جهاز مختلفة، مثل مستوى واجهة برمجة التطبيقات، يجب استخدام رقم تعريف التطبيق نفسه لكلّ إصدار من إصدارات التطبيق، ولكن يجب منح كل حزمة APK رقم تعريفversionCode
مختلفًا. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة إتاحة حِزم APK متعددة. ولا يتأثّر نشر المحتوى باستخدام واجهات AAB، لأنّ هذا الإصدار يستخدم عنصرًا واحدًا بشكل تلقائي يستخدم رمز إصدار واحدًا ومعرّف تطبيق واحدًا بشكل تلقائي.
ملاحظة: إذا كنت بحاجة إلى الإشارة إلى رقم تعريف التطبيق فيملف
البيان، يمكنك استخدام العنصر النائب ${applicationId}
في أي سمة
بيان. أثناء الإنشاء، يستبدل Gradle هذه العلامة بمعرّف التطبيق الفعلي. وللمزيد من المعلومات، يُرجى الاطّلاع على إدخال متغيّرات التصميم في البيان.
دمج نكهات منتجات متعددة مع سمات النكهة
وفي بعض الحالات، قد تحتاج إلى دمج إعدادات من نكهات متعدّدة للمنتج. على سبيل المثال، قد تحتاج إلى إنشاء إعدادات مختلفة لإصدارَي المنتج "الكامل" و "الإصدار التجريبي" اللذَين يستندان إلى مستوى واجهة برمجة التطبيقات. ولإجراء ذلك، يتيح لك المكوّن الإضافي لنظام Gradle المتوافق مع Android إنشاء مجموعات متعددة من نكهات المنتجات كأبعاد للنكهة.
عند إنشاء تطبيقك، يجمع Gradle إعدادات نكهة المنتج من كل سمة نكهة تحدّدها، بالإضافة إلى إعدادات نوع الإصدار، لإنشاء خيار الإصدار النهائي. لا تدمج Gradle نكهات المنتجات التي تنتمي إلى سمة النكهة نفسها.
يستخدم نموذج الرمز البرمجي التالي السمة
flavorDimensions
لإنشاء سمة صيغة "الوضع"
لتجميع نكهات المنتج "الكاملة" و"التجريبية" وسمة صيغة "واجهة برمجة التطبيقات"
لتجميع إعدادات نكهة المنتج استنادًا إلى مستوى واجهة برمجة التطبيقات:
Kotlin
android { ... buildTypes { getByName("debug") {...} getByName("release") {...} } // Specifies the flavor dimensions you want to use. The order in which you // list the dimensions determines their priority, from highest to lowest, // when Gradle merges variant sources and configurations. You must assign // each product flavor you configure to one of the flavor dimensions. flavorDimensions += listOf("api", "mode") productFlavors { create("demo") { // Assigns this product flavor to the "mode" flavor dimension. dimension = "mode" ... } create("full") { dimension = "mode" ... } // Configurations in the "api" product flavors override those in "mode" // flavors and the defaultConfig block. Gradle determines the priority // between flavor dimensions based on the order in which they appear next // to the flavorDimensions property, with the first dimension having a higher // priority than the second, and so on. create("minApi24") { dimension = "api" minSdk = 24 // To ensure the target device receives the version of the app with // the highest compatible API level, assign version codes in increasing // value with API level. versionCode = 30000 + (android.defaultConfig.versionCode ?: 0) versionNameSuffix = "-minApi24" ... } create("minApi23") { dimension = "api" minSdk = 23 versionCode = 20000 + (android.defaultConfig.versionCode ?: 0) versionNameSuffix = "-minApi23" ... } create("minApi21") { dimension = "api" minSdk = 21 versionCode = 10000 + (android.defaultConfig.versionCode ?: 0) versionNameSuffix = "-minApi21" ... } } } ...
رائع
android { ... buildTypes { debug {...} release {...} } // Specifies the flavor dimensions you want to use. The order in which you // list the dimensions determines their priority, from highest to lowest, // when Gradle merges variant sources and configurations. You must assign // each product flavor you configure to one of the flavor dimensions. flavorDimensions "api", "mode" productFlavors { demo { // Assigns this product flavor to the "mode" flavor dimension. dimension "mode" ... } full { dimension "mode" ... } // Configurations in the "api" product flavors override those in "mode" // flavors and the defaultConfig block. Gradle determines the priority // between flavor dimensions based on the order in which they appear next // to the flavorDimensions property, with the first dimension having a higher // priority than the second, and so on. minApi24 { dimension "api" minSdkVersion 24 // To ensure the target device receives the version of the app with // the highest compatible API level, assign version codes in increasing // value with API level. versionCode 30000 + android.defaultConfig.versionCode versionNameSuffix "-minApi24" ... } minApi23 { dimension "api" minSdkVersion 23 versionCode 20000 + android.defaultConfig.versionCode versionNameSuffix "-minApi23" ... } minApi21 { dimension "api" minSdkVersion 21 versionCode 10000 + android.defaultConfig.versionCode versionNameSuffix "-minApi21" ... } } } ...
إنّ عدد صيغ الإصدار التي ينشئها Gradle يساوي حاصل ضرب عدد النُسخ في كل سمة نسخة وعدد أنواع الإصدارات التي تضبطها. عندما يُحدِّد Gradle اسمًا لكلّ صيغة إصدار أو عناصر مقابلة، تظهر أولاً smaks المنتج التي تنتمي إلى سمة النكهة ذات الأولوية الأعلى، ثم يليها تلك التي تنتمي إلى السمات ذات الأولوية الأقل، ثم يليها نوع الإصدار.
باستخدام إعدادات الإصدار السابقة كمثال، تنشئ Gradle ما مجموعه 12 متغيرًا للإصدار باستخدام نظام التسمية التالي:
- نوع التصميم:
[minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
- حزمة APK المقابلة:
app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
- على سبيل المثال:
- نوع الإصدار:
minApi24DemoDebug
- حزمة APK المقابلة:
app-minApi24-demo-debug.apk
بالإضافة إلى أدلة مجموعة المصادر التي يمكنك إنشاؤها لكل ملف شخصي
خاص بالإصدار ونوع الإصدار، يمكنك أيضًا إنشاء أدلة مجموعة مصادر
لكل مجموعة من الملفات الشخصية للإصدار. على سبيل المثال، يمكنك إنشاء
مصادر Java وإضافتها إلى دليل src/demoMinApi24/java/
،
ولا تستخدم Gradle هذه المصادر إلا عند إنشاء صيغة تجمع
بين نكهتَي المنتج هاتين.
إنّ مجموعات المصادر التي تنشئها لتركيبات ملفّات تعريف المنتج لها أولوية أعلى من مجموعات المصادر التي تنتمي إلى كل ملف تعريف منتج individual. لمزيد من المعلومات عن مجموعات المصادر وكيفية دمج Gradle للموارد، اقرأ القسم عن كيفية إنشاء مجموعات المصادر.
فلترة الأسعار المتغيرة
ينشئ Gradle خيار إصدار لكل مجموعة ممكنة من نكهات
المنتج وأنواع الإصدارات التي تضبطها. ومع ذلك، قد تكون هناك
أنواع بنيات معيّنة لا تحتاج إليها أو لا تُعدّ منطقية في
سياق مشروعك. لإزالة بعض عمليات ضبط صيغ الإصدارات،
أنشِئ فلتر خيارات المنتج في ملف build.gradle.kts
على مستوى الوحدة.
باستخدام إعدادات الإصدار من القسم السابق كمثال،
لنفترض أنّك تخطّط لإتاحة الإصدار التمهيدي
من التطبيق فقط لمستويات واجهة برمجة التطبيقات 23 والإصدارات الأحدث. يمكنك استخدام العنصر
variantFilter
لفلترة جميع إعدادات
الصيغ المختلفة للإصدار التي تجمع بين نكهات المنتج "minApi21" و "demo":
Kotlin
android { ... buildTypes {...} flavorDimensions += listOf("api", "mode") productFlavors { create("demo") {...} create("full") {...} create("minApi24") {...} create("minApi23") {...} create("minApi21") {...} } } androidComponents { beforeVariants { variantBuilder -> // To check for a certain build type, use variantBuilder.buildType == "<buildType>" if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) { // Gradle ignores any variants that satisfy the conditions above. variantBuilder.enable = false } } } ...
رائع
android { ... buildTypes {...} flavorDimensions "api", "mode" productFlavors { demo {...} full {...} minApi24 {...} minApi23 {...} minApi21 {...} } variantFilter { variant -> def names = variant.flavors*.name // To check for a certain build type, use variant.buildType.name == "<buildType>" if (names.contains("minApi21") && names.contains("demo")) { // Gradle ignores any variants that satisfy the conditions above. setIgnore(true) } } } ...
بعد إضافة فلتر الصيغة إلى إعدادات الإصدار والنقر على مزامنة الآن في شريط الإشعارات، يتجاهل Gradle أي صِيغ إصدار تستوفي الشروط التي تحدّدها. لم تعُد خيارات الإصدار تظهر في القائمة عند النقر على الإصدار > اختيار خيار الإصدار من شريط القوائم أو خيارات الإصدار في شريط نافذة الأدوات.
إنشاء مجموعات مصادر
ينشئ Android Studio تلقائيًا main/
مجموعة المصادر والأدلة
لكل ما تريد مشاركته بين جميع صيغ الإصدار. ومع ذلك،
يمكنك إنشاء مجموعات مصادر جديدة للتحكّم بدقة في الملفات التي يجمعها Gradle ويجمعها لأنواع إصدارات معيّنة وأنواع منتجات ومجموعات
أنواع منتجات (عند استخدام سمات
النكهة) وأنواع الإصدارات.
على سبيل المثال، يمكنك تحديد الوظائف الأساسية في مجموعة مصادر main/
واستخدام مجموعات مصادر صيغة المنتج لتغيير هوية العلامة التجارية لتطبيقك لمختلف أنواع العملاء، أو تضمين أذونات خاصة ووظيفة تسجيل فقط لنُسخ الإصدارات التي تستخدم نوع الإصدار المخصّص لتصحيح الأخطاء.
يتوقّع Gradle تنظيم ملفات مجموعة المصادر وأدلائها بطريقة معيّنة
تشبه مجموعة مصادر main/
. على سبيل المثال، تتوقّع أداة Gradle وجود ملفات Kotlin أو Java الخاصة بنوع التصميم "debug" في دليل src/debug/kotlin/
أو src/debug/java/
.
يوفّر المكوّن الإضافي لنظام Gradle المتوافق مع Android مهمة Gradle المفيدة التي توضح لك كيفية تنظيم ملفاتك حسب كل نوع من أنواع التصميمات ونكهات المنتجات وصيغ التصاميم. على سبيل المثال، يصف النموذج التالي من نتائج المهمة المكان الذي يتوقّع فيه نظام Gradle العثور على ملفات معيّنة لنوع الإصدار "تصحيح الأخطاء":
------------------------------------------------------------ Project :app ------------------------------------------------------------ ... debug ---- Compile configuration: debugCompile build.gradle name: android.sourceSets.debug Java sources: [app/src/debug/java] Kotlin sources: [app/src/debug/kotlin, app/src/debug/java] Manifest file: app/src/debug/AndroidManifest.xml Android resources: [app/src/debug/res] Assets: [app/src/debug/assets] AIDL sources: [app/src/debug/aidl] RenderScript sources: [app/src/debug/rs] JNI sources: [app/src/debug/jni] JNI libraries: [app/src/debug/jniLibs] Java-style resources: [app/src/debug/resources]
لعرض هذا الناتج، اتّبِع الخطوات التالية:
- انقر على Gradle في شريط نافذة الأدوات.
انتقِل إلى MyApplication > Tasks > android وانقر مرّتين على sourceSets.
للاطّلاع على مجلد المهام، يجب السماح لـ Gradle بإنشاء قائمة المهام أثناء المزامنة. ولإجراء ذلك، اتبع الخطوات التالية:
- انقر على ملف > الإعدادات > تجريبي (استوديو Android > الإعدادات > تجريبي على نظام التشغيل macOS).
- ألغِ اختيار عدم إنشاء قائمة مهام Gradle أثناء مزامنة Gradle.
- بعد تنفيذ Gradle للمهمة، تفتح نافذة Run (تشغيل) لعرض المخرجات.
ملاحظة: توضح لك نتائج المهام أيضًا كيفية تنظيم مجموعات المصادر للملفات التي تريد استخدامها لإجراء اختبارات لتطبيقك، مثل مجموعات مصادر الاختبار وtest/
وandroidTest/
.
عند إنشاء نوع إصدار جديد، لا ينشئ Android Studio أدلة مجموعة ملف المصدر بدلاً منك، ولكنه يمنحك بعض الخيارات لمساعدتك. على سبيل المثال، لإنشاء الدليل java/
فقط لنوع الإصدار "debug"
:
- افتح لوحة المشروع واختَر عرض المشروع من القائمة في أعلى اللوحة.
- انتقِل إلى
MyProject/app/src/
. - انقر بزر الماوس الأيمن على دليل
src
واختَر جديد > دليل. - من القائمة ضمن Gradle Source Sets، اختَر full/java.
- اضغط على Enter.
ينشئ "استوديو Android" دليل مجموعة مصادر لنوع الإصدار المخصّص لتصحيح الأخطاء، ثمّ ينشئ الدليل java/
داخله. بدلاً من ذلك،
يمكن أن ينشئ Android Studio الأدلة نيابةً عنك عند إضافة ملف جديد إلى
مشروعك لإصدار محدّد.
على سبيل المثال، لإنشاء ملف XML للقيم لنوع الإصدار "تصحيح الأخطاء":
- في لوحة المشروع، انقر بزر الماوس الأيمن على دليل
src
واختَر جديد > XML > ملف XML للقيم. - أدخِل اسم ملف XML أو احتفظ بالاسم التلقائي.
- من القائمة بجانب مجموعة مصادر الاستهداف، انقر على تصحيح الأخطاء.
- انقر على إنهاء.
بما أنّه تم تحديد نوع الإصدار "debug" على أنّه مجموعة المصادر المستهدَفة، ينشئ "استوديو Android" تلقائيًا الأدلة اللازمة عند إنشاء ملف XML. تبدو بنية الدليل الناتجة كما هو موضّح في الشكل 1.
تتضمّن مجموعات المصادر النشطة مؤشرًا أخضر في رمزها للإشارة إلى أنّها نشطة. تتم إضافة [main]
إلى مجموعة رمز المصدر
debug
للإشارة إلى أنّه سيتم دمجها
في مجموعة رمز المصدر main
.
باستخدام الإجراء نفسه، يمكنك أيضًا إنشاء أدلة مجموعات مصادر لملف تعريفات smaks
المنتج، مثل src/demo/
، ونُسخ الإصدار، مثل
src/demoDebug/
. بالإضافة إلى ذلك، يمكنك إنشاء مجموعات مصادر اختبار
تستهدف أنواع إصدارات معيّنة، مثل
src/androidTestDemoDebug/
. لمزيد من المعلومات، يمكنك الاطّلاع على مقالة اختبار مجموعات المصادر.
تغيير إعدادات مجموعة المصادر التلقائية
إذا كانت لديك مصادر غير منظَّمة في ملف مجموعة المصادر التلقائية
وفقًا للبنية التي يتوقّعها Gradle، كما هو موضّح في القسم السابق عن
إنشاء مجموعات المصادر، يمكنك استخدام العنصر
sourceSets
لتغيير المكان الذي يبحث فيه Gradle عن جمع
الملفات لكل مكوّن من مجموعة مصادر.
يجب أن يكون العنصر sourceSets
في العنصر android
. لست بحاجة إلى إعادة تحديد موقع
ملفات المصدر، ما عليك سوى تزويد Gradle بالمسارات، بالنسبة إلىملف build.gradle.kts
على مستوى الوحدة، حيث يمكن لـ Gradle
العثور على ملفات لكل مكوّن من مكوّنات مجموعة المصادر. للتعرّف على المكوّنات التي يمكنك
ضبطها وما إذا كان بإمكانك ربطها بملفات أو أدلة متعددة،
اطّلِع على مرجع واجهة برمجة التطبيقات لمكوّن إضافي Gradle لنظام التشغيل Android.
يربط نموذج الرمز البرمجي التالي المصادر من الدليل app/other/
بمكونات معيّنة من مجموعة المصادر main
ويغيّر
الدليل الجذر لمجموعة المصادر androidTest
:
Kotlin
android { ... // Encapsulates configurations for the main source set. sourceSets.getByName("main") { // Changes the directory for Java sources. The default directory is // 'src/main/java'. java.setSrcDirs(listOf("other/java")) // If you list multiple directories, Gradle uses all of them to collect // sources. Because Gradle gives these directories equal priority, if // you define the same resource in more than one directory, you receive an // error when merging resources. The default directory is 'src/main/res'. res.setSrcDirs(listOf("other/res1", "other/res2")) // Note: Avoid specifying a directory that is a parent to one // or more other directories you specify. For example, avoid the following: // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings'] // Specify either only the root 'other/res1' directory or only the // nested 'other/res1/layouts' and 'other/res1/strings' directories. // For each source set, you can specify only one Android manifest. // By default, Android Studio creates a manifest for your main source // set in the src/main/ directory. manifest.srcFile("other/AndroidManifest.xml") ... } // Create additional blocks to configure other source sets. sourceSets.getByName("androidTest") { // If all the files for a source set are located under a single root // directory, you can specify that directory using the setRoot property. // When gathering sources for the source set, Gradle looks only in locations // relative to the root directory you specify. For example, after applying the // configuration below for the androidTest source set, Gradle looks for Java // sources only in the src/tests/java/ directory. setRoot("src/tests") ... } } ...
رائع
android { ... sourceSets { // Encapsulates configurations for the main source set. main { // Changes the directory for Java sources. The default directory is // 'src/main/java'. java.srcDirs = ['other/java'] // If you list multiple directories, Gradle uses all of them to collect // sources. Because Gradle gives these directories equal priority, if // you define the same resource in more than one directory, you receive an // error when merging resources. The default directory is 'src/main/res'. res.srcDirs = ['other/res1', 'other/res2'] // Note: Avoid specifying a directory that is a parent to one // or more other directories you specify. For example, avoid the following: // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings'] // Specify either only the root 'other/res1' directory or only the // nested 'other/res1/layouts' and 'other/res1/strings' directories. // For each source set, you can specify only one Android manifest. // By default, Android Studio creates a manifest for your main source // set in the src/main/ directory. manifest.srcFile 'other/AndroidManifest.xml' ... } // Create additional blocks to configure other source sets. androidTest { // If all the files for a source set are located under a single root // directory, you can specify that directory using the setRoot property. // When gathering sources for the source set, Gradle looks only in locations // relative to the root directory you specify. For example, after applying the // configuration below for the androidTest source set, Gradle looks for Java // sources only in the src/tests/java/ directory. setRoot 'src/tests' ... } } } ...
يُرجى العلم أنّ الدليل المصدر يمكن أن ينتمي إلى مجموعة مصادر واحدة فقط. على سبيل المثال، لا يمكنك مشاركة
مصادر الاختبار نفسها مع مجموعتَي مصادر test
وandroidTest
. ويعود سبب ذلك
إلى أنّ "استوديو Android" ينشئ وحدات IntelliJ منفصلة لكل مجموعة مصادر، ولا يمكنه السماح
بنسخ جذور المحتوى في مجموعات المصادر.
الإنشاء باستخدام مجموعات المصادر
يمكنك استخدام أدلة مجموعة المصادر لتضمين الرمز البرمجي والموارد التي تريد حزمها مع إعدادات معيّنة فقط. على سبيل المثال، إذا كنت بصدد إنشاء الصيغة "demoDebug"، وهي ناتجة عن تفاعل بين نوع الإصدار "demo" ونوع الإصدار "debug"، يفحص Gradle هذه الأدلة ويمنحها الأولوية التالية:
-
src/demoDebug/
(مجموعة مصادر تنويعة التصميم) -
src/debug/
(مجموعة مصادر نوع التصميم) -
src/demo/
(مجموعة مصادر صيغة المنتج) -
src/main/
(مجموعة المصادر الرئيسية)
يجب أن تتضمّن مجموعات المصادر التي تمّ إنشاؤها لمجموعات نكهات المنتجات جميع سمات النكهات. على سبيل المثال، يجب أن تكون مجموعة مصادر أنواع الإصدارات هي مجموعة من نوع الإصدار وجميع سمات النكهة. لا يمكن دمج الرموز البرمجية والموارد التي تتضمن مجلدات تشمل أبعادًا متعددة ولكن ليس كل السمات.
إذا كنت تدمج نكهات متعدّدة
للمنتجات، يتم تحديد الأولوية بين نكهات المنتجات حسب سمة النكهة
التي تنتمي إليها. عند إدراج سمات النكهات باستخدام السمة
android.flavorDimensions
، تكون نكهات المنتجات التي
تنتمي إلى سمة النكهة الأولى التي تُدرِجها لها أولوية أعلى من تلك التي تنتمي إلى سمة النكهة الثانية، وهكذا. بالإضافة إلى ذلك، تكون الأولوية لمجموعات نكهات المنتجات التي تنشئها لمجموعات نكهات المنتجات مقارنةً بمجموعات المصادر التي تنتمي إلى نكهة منتج فردية.
يحدّد ترتيب الأولويات مجموعة المصادر ذات الأولوية الأعلى عندما يدمج تطبيق Gradle الرموز البرمجية والموارد. بما أنّ دليل مجموعة المصدر demoDebug/
يحتوي على ملفات خاصة بخيار الإصدار هذا، إذا تضمّن demoDebug/
ملفًا تم تحديده أيضًا في
debug/
، ستستخدم منصّة Gradle الملف في مجموعة المصادر demoDebug/
. وبالمثل، تعطي Gradle الملفات في نوع التصميم، ويحدّد مصدر صيغة المنتج أولوية أعلى من الملفات نفسها في main/
.
يراعي Gradle ترتيب الأولوية هذا عند تطبيق قواعد الإنشاء التالية:
- يتم تجميع كل رموز المصدر في دليل
kotlin/
أوjava/
معًا لإنشاء ناتج واحد.ملاحظة: بالنسبة إلى نوع إصدار معيّن، يُرسِل Gradle خطأ في الإصدار إذا صادف دليلَي مجموعة مصادر أو أكثر حدّدا فئة Kotlin أو Java نفسها. على سبيل المثال، عند إنشاء تطبيق تصحيح أخطاء، لا يمكنك تحديد كل من
src/debug/Utility.kt
وsrc/main/Utility.kt
، لأنّ Gradle يفحص كلاً من هذين الدليلَين أثناء عملية الإنشاء ويُرسِل خطأ "فئة مكرّرة" . إذا كنت تريد إصدارات مختلفة منUtility.kt
لأنواع تصاميم مختلفة، يجب أن يحدِّد كل نوع تصميم إصداره الخاص من الملف وألا يتم تضمينه في مجموعة مصادرmain/
. - يتم دمج ملفات البيان معًا في ملف بيان واحد. يتم منح الأولوية بالترتيب نفسه المُدرَج في القائمة في المثال السابق. وهذا يعني أنّ إعدادات البيان لنوع الإصدار تلغي إعدادات البيان لإصدار المنتج، وما إلى ذلك. للحصول على مزيد من المعلومات، يمكنك الاطّلاع على دمج ملف البيان.
- يتم دمج الملفات في أدلة
values/
معًا. إذا كان لملفَين الاسم نفسه، مثل ملفيstrings.xml
، تُمنَح الأولوية بالترتيب نفسه لقائمةstrings.xml
في المثال السابق. وهذا يعني أنّ القيم المحدّدة في ملف في مجموعة مصادر نوع الإنشاء تلغي القيم المحدّدة في الملف نفسه في أحد أنواع المنتج، وما إلى ذلك. - يتم تجميع الموارد في الدليلَين
res/
وasset/
معًا. إذا كانت هناك موارد تحمل الاسم نفسه محدّدة في مجموعتَي مصادر أو أكثر، يتم منح الأولوية بالترتيب نفسه للقوائم في المثال السابق. - يمنح Gradle الموارد والملفات البيانية المضمّنة في مكتبة متطلّبات وحدة أدنى أولوية عند إنشاء التطبيق.
تعريف التبعيات
لضبط تبعية لخيار إصدار معيّن أو
مجموعة مصادر اختبار،
أضِف اسم خيار الإصدار أو مجموعة مصادر الاختبار قبل الكلمة الرئيسية
Implementation
، كما هو موضّح في المثال التالي:
Kotlin
dependencies { // Adds the local "mylibrary" module as a dependency to the "free" flavor. "freeImplementation"(project(":mylibrary")) // Adds a remote binary dependency only for local tests. testImplementation("junit:junit:4.12") // Adds a remote binary dependency only for the instrumented test APK. androidTestImplementation("com.android.support.test.espresso:espresso-core:3.6.1") }
رائع
dependencies { // Adds the local "mylibrary" module as a dependency to the "free" flavor. freeImplementation project(":mylibrary") // Adds a remote binary dependency only for local tests. testImplementation 'junit:junit:4.12' // Adds a remote binary dependency only for the instrumented test APK. androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.6.1' }
لمزيد من المعلومات عن ضبط التبعيات، اطّلِع على إضافة تبعيات الإنشاء.
استخدام إدارة التبعية المراعية للأنواع
يتضمّن الإصدار 3.0.0 من "مكوّن Android Gradle الإضافي" والإصدارات الأحدث آلية جديدة للاعتماد تطابق تلقائيًا
الصيغ عند استخدام مكتبة. وهذا يعني أنّ صيغة debug
للتطبيق
تستهلك تلقائيًا صيغة debug
للمكتبة، وهكذا. ويعمل هذا الإجراء أيضًا عند استخدام ملفّات APK المخصّصة لإصدارات محدّدة من التطبيق: سيستهلك إصدار freeDebug
من التطبيق إصدار freeDebug
من المكتبة.
لكي يتطابق المكوّن الإضافي مع الأسعار المتغيرة بدقة، عليك توفير عناصر احتياطية مطابقة كما هو موضّح في القسم التالي، وذلك في الحالات التي لا تتوفّر فيها مطابقة مباشرة.
على سبيل المثال، لنفترض أنّ تطبيقك يضبط نوع إصدار يُسمى "مرحلة الاختبار"، ولكن أحد متطلّبات مكتبته لا يضبطه. عندما يحاول المكوّن الإضافي إنشاء الإصدار "التجريبي" من تطبيقك، لن يعرف إصدار المكتبة الذي يجب استخدامه، وستظهر لك رسالة خطأ مشابهة لما يلي:
Error:Failed to resolve: Could not resolve project :mylibrary. Required by: project :app
حلّ أخطاء الإصدار المتعلّقة بمطابقة خيارات المنتج
يتضمّن المكوّن الإضافي عناصر لغة وصف لغة برمجة (DSL) لمساعدتك في التحكّم في كيفية حلّ Gradle للمواقف التي لا تتوفّر فيها إمكانية مطابقة الصيغة المباشرة بين التطبيق والمكوّن الإضافي.
في ما يلي قائمة بالمشاكل المتعلّقة بمطابقة التبعيات مع مراعاة الصيغ وكيفية حلّها باستخدام خصائص لغة وصف البيانات (DSL):يشتمل تطبيقك على نوع إصدار لا يتضمّنه أحد متطلّبات المكتبة.
على سبيل المثال، يتضمّن تطبيقك نوع الإصدار "الإصدار التجريبي"، ولكن لا يتضمّن أحد التبعيات سوى نوعَي الإصدار "تصحيح الأخطاء" و "الإصدار العلني".
يُرجى العلم أنّه لا توجد مشكلة عندما يتضمّن أحد متطلّبات المكتبة نوع ملف برمجي غير متوفر في تطبيقك. ويرجع ذلك إلى أنّ المكوّن الإضافي لا يطلب أبدًا نوع الإصدار من الاعتمادية.
استخدِم
matchingFallbacks
لتحديد مطابقات بديلة لنوع إصدار معيّن، كما هو موضّح هنا:Kotlin
// In the app's build.gradle.kts file. android { buildTypes { getByName("debug") {} getByName("release") {} create("staging") { // Specifies a sorted list of fallback build types that the // plugin can try to use when a dependency does not include a // "staging" build type. You may specify as many fallbacks as you // like, and the plugin selects the first build type that's // available in the dependency. matchingFallbacks += listOf("debug", "qa", "release") } } }
رائع
// In the app's build.gradle file. android { buildTypes { debug {} release {} staging { // Specifies a sorted list of fallback build types that the // plugin can try to use when a dependency does not include a // "staging" build type. You may specify as many fallbacks as you // like, and the plugin selects the first build type that's // available in the dependency. matchingFallbacks = ['debug', 'qa', 'release'] } } }
بالنسبة إلى سمة نكهة معيّنة متوفّرة في كلّ من التطبيق وأحد تبعياته في المكتبة، يتضمّن تطبيقك نكهات لا تتضمّنها المكتبة.
على سبيل المثال، يتضمّن كلّ من تطبيقك وعناصر المكتبة الاعتمادية سمة نكهة "المستوى". ومع ذلك، تتضمّن سمة "المستوى" في التطبيق خيارَي "مجاني" و "مدفوع"، ولكن لا يتضمّن الاعتماد سوى خيارَي "إصدار تجريبي" و "مدفوع" للسمة نفسها.
يُرجى العلم أنّه بالنسبة إلى سمة نكهة معيّنة متوفّرة في كلّ من التطبيق وملف مكتبته ، لا توجد مشكلة في أن تتضمّن المكتبة نكهة منتج لا يتضمنها تطبيقك. وذلك لأن المكون الإضافي لا يطلب أبدًا أي نكهة من التبعية.
يمكنك استخدام
matchingFallbacks
لتحديد خيارات مطابقة بديلة لنكهة المنتج "المجانية" التي يوفّرها التطبيق، كما هو موضّح أدناه:Kotlin
// In the app's build.gradle.kts file. android { defaultConfig{ // Don't configure matchingFallbacks in the defaultConfig block. // Instead, specify fallbacks for a given product flavor in the // productFlavors block, as shown below. } flavorDimensions += "tier" productFlavors { create("paid") { dimension = "tier" // Because the dependency already includes a "paid" flavor in its // "tier" dimension, you don't need to provide a list of fallbacks // for the "paid" flavor. } create("free") { dimension = "tier" // Specifies a sorted list of fallback flavors that the plugin // can try to use when a dependency's matching dimension does // not include a "free" flavor. Specify as many // fallbacks as you like; the plugin selects the first flavor // that's available in the dependency's "tier" dimension. matchingFallbacks += listOf("demo", "trial") } } }
رائع
// In the app's build.gradle file. android { defaultConfig{ // Don't configure matchingFallbacks in the defaultConfig block. // Instead, specify fallbacks for a given product flavor in the // productFlavors block, as shown below. } flavorDimensions 'tier' productFlavors { paid { dimension 'tier' // Because the dependency already includes a "paid" flavor in its // "tier" dimension, you don't need to provide a list of fallbacks // for the "paid" flavor. } free { dimension 'tier' // Specifies a sorted list of fallback flavors that the plugin // can try to use when a dependency's matching dimension does // not include a "free" flavor. Specify as many // fallbacks as you like; the plugin selects the first flavor // that's available in the dependency's "tier" dimension. matchingFallbacks = ['demo', 'trial'] } } }
تتضمن العناصر الاعتمادية للمكتبة سمة نكهة لا يتضمنها تطبيقك.
على سبيل المثال، تتضمّن مكتبة معتمدة نكهات لسمة "minApi"، ولكن تطبيقك يتضمّن نكهات لسمة "المستوى" فقط. عندما تريد إنشاء إصدار "freeDebug" من تطبيقك، لا يعرف المكوّن الإضافي ما إذا كان سيستخدم الإصدار "minApi23Debug" أو "minApi18Debug" من العنصر المُستخدَم.
يُرجى العلم أنّه لا توجد مشكلة عندما يتضمّن تطبيقك سمة نكهة لا تتضمّنها مكتبة تابعة. ويعود السبب في ذلك إلى أنّ المكوّن الإضافي لا يطابق سوى أنواع السمات التي تتوفّر في العنصر المُستخدَم. على سبيل المثال، إذا لم يتضمّن أحد التبعيات سمة لـ ABI، سيستخدم إصدار "freeX86Debug" من تطبيقك إصدار "freeDebug" من التبعية.
استخدِم
missingDimensionStrategy
في القالبdefaultConfig
لتحديد الصيغة التلقائية للمكوّن الإضافي كي يختارها من كل سمة غير متوفّرة، كما هو موضّح في النموذج التالي. يمكنك أيضًا إلغاء اختياراتك في المربّعproductFlavors
، لكي يتمكّن كلّ إصدار من تحديد استراتيجية مطابقة مختلفة لسمة غير متوفّرة.Kotlin
// In the app's build.gradle.kts file. android { defaultConfig{ // Specifies a sorted list of flavors that the plugin can try to use from // a given dimension. This tells the plugin to select the "minApi18" flavor // when encountering a dependency that includes a "minApi" dimension. // You can include additional flavor names to provide a // sorted list of fallbacks for the dimension. missingDimensionStrategy("minApi", "minApi18", "minApi23") // Specify a missingDimensionStrategy property for each // dimension that exists in a local dependency but not in your app. missingDimensionStrategy("abi", "x86", "arm64") } flavorDimensions += "tier" productFlavors { create("free") { dimension = "tier" // You can override the default selection at the product flavor // level by configuring another missingDimensionStrategy property // for the "minApi" dimension. missingDimensionStrategy("minApi", "minApi23", "minApi18") } create("paid") {} } }
رائع
// In the app's build.gradle file. android { defaultConfig{ // Specifies a sorted list of flavors that the plugin can try to use from // a given dimension. This tells the plugin to select the "minApi18" flavor // when encountering a dependency that includes a "minApi" dimension. // You can include additional flavor names to provide a // sorted list of fallbacks for the dimension. missingDimensionStrategy 'minApi', 'minApi18', 'minApi23' // Specify a missingDimensionStrategy property for each // dimension that exists in a local dependency but not in your app. missingDimensionStrategy 'abi', 'x86', 'arm64' } flavorDimensions 'tier' productFlavors { free { dimension 'tier' // You can override the default selection at the product flavor // level by configuring another missingDimensionStrategy property // for the 'minApi' dimension. missingDimensionStrategy 'minApi', 'minApi23', 'minApi18' } paid {} } }
لمزيد من المعلومات، يمكنك الاطّلاع على matchingFallbacks
وmissingDimensionStrategy
في مرجع DSL لمكوّن Gradle المتوافق مع Android.
ضبط إعدادات التوقيع
لا يوقّع Gradle حِزمة APK أو حِزمة AAB لإصدار تطبيقك ما لم تحدِّد صراحةً إعدادات توقيع لهذا الإصدار. إذا لم يكن لديك مفتاح توقيع، يمكنك إنشاء مفتاح تحميل وملف تخزين مفاتيح باستخدام "استوديو Android".
لضبط إعدادات التوقيع يدويًا لنوع إصدار الإصدار الخاص بك باستخدام إعدادات إصدار Gradle، اتّبِع الخطوات التالية:
- أنشئ ملف تخزين مفاتيح. ملف تخزين المفاتيح هو ملف ثنائي يحتوي على مجموعة من المفاتيح الخاصة. يجب الاحتفاظ بملف تخزين المفاتيح في مكان آمن وموثوق به.
- أنشئ مفتاحًا خاصًا. يُستخدم المفتاح الخاص لتوقيع تطبيقك لتوزيعه، ولا يتم تضمينه مع التطبيق أو الإفصاح عنه لجهات خارجية غير مصرَّح بها.
-
أضِف إعدادات التوقيع إلى ملف
build.gradle.kts
على مستوى الوحدة:Kotlin
... android { ... defaultConfig {...} signingConfigs { create("release") { storeFile = file("myreleasekey.keystore") storePassword = "password" keyAlias = "MyReleaseKey" keyPassword = "password" } } buildTypes { getByName("release") { ... signingConfig = signingConfigs.getByName("release") } } }
رائع
... android { ... defaultConfig {...} signingConfigs { release { storeFile file("myreleasekey.keystore") storePassword "password" keyAlias "MyReleaseKey" keyPassword "password" } } buildTypes { release { ... signingConfig signingConfigs.release } } }
ملاحظة: إنّ تضمين كلمات مرور مفتاح الإصدار وملف تخزين المفاتيح داخل ملف الإنشاء ليس من الممارسات الأمنية الجيدة. بدلاً من ذلك، يمكنك ضبط ملف الإنشاء للحصول على كلمات المرور هذه من متغيّرات البيئة أو أن تطلب منك عملية الإنشاء إدخال كلمات المرور هذه.
للحصول على كلمات المرور هذه من متغيّرات البيئة:
Kotlin
storePassword = System.getenv("KSTOREPWD") keyPassword = System.getenv("KEYPWD")
رائع
storePassword System.getenv("KSTOREPWD") keyPassword System.getenv("KEYPWD")
بدلاً من ذلك، يمكنك تحميل ملف تخزين المفاتيح من ملف خصائص على الجهاز. لأسباب تتعلّق بالأمان، لا ينبغي إضافة هذا الملف إلى أداة التحكّم في المصدر. بدلاً من ذلك، يمكنك إعداده محليًا لكل مطوِّر. لمزيد من المعلومات، يُرجى الاطّلاع على المقالة إزالة معلومات التوقيع من ملفات الإنشاء.
بعد إكمال هذه العملية، يمكنك توزيع تطبيقك ونشره على Google Play.
تحذير: احتفِظ بملف تخزين المفاتيح والمفتاح الخاص في مكان آمن وموثوق به، وتأكَّد من توفُّر نُسخ احتياطية آمنة منهما. إذا كنت تستخدم ميزة "توقيع التطبيق" من Play وفقدت مفتاح التحميل، يمكنك طلب إعادة ضبطه باستخدام Play Console. إذا كنت بصدد نشر تطبيق بدون ميزة "توقيع التطبيق" من Play (للتطبيقات التي تم إنشاؤها قبل آب/أغسطس 2021) و فقدت مفتاح توقيع التطبيق، لن تتمكّن من نشر أي تحديثات لتطبيقك، لأنّه عليك دائمًا توقيع جميع إصدارات تطبيقك باستخدام المفتاح نفسه.
توقيع تطبيقات Wear OS
عند نشر تطبيقات Wear OS، يجب توقيع كل من حزمة APK المخصّصة للساعة وحزمة APK الاختيارية المخصّصة للهاتف باستخدام المفتاح نفسه. لمزيد من المعلومات عن حزم تطبيقات Wear OS وتوقيعها، اطّلِع على مقالة تجميع تطبيقات Wear OS وتوزيعها.