این صفحه به شما نشان می دهد که چگونه می توانید انواع ساخت را برای ایجاد نسخه های مختلف برنامه خود از یک پروژه واحد پیکربندی کنید و چگونه وابستگی ها و پیکربندی های امضای خود را به درستی مدیریت کنید.
هر نوع ساخت نشان دهنده نسخه متفاوتی از برنامه شما است که می توانید بسازید. به عنوان مثال، ممکن است بخواهید یک نسخه از برنامه خود را بسازید که رایگان با مجموعه ای محدود از محتوا، و نسخه دیگری پولی که شامل موارد بیشتری باشد. همچنین میتوانید نسخههای مختلفی از برنامه خود را بسازید که دستگاههای مختلف را هدف قرار میدهند، بر اساس سطح API یا سایر تغییرات دستگاه.
انواع ساخت نتیجه استفاده Gradle از مجموعه ای خاص از قوانین برای ترکیب تنظیمات، کد و منابع پیکربندی شده در انواع ساخت و طعم محصول شماست. اگرچه شما انواع ساخت را مستقیماً پیکربندی نمیکنید، اما انواع ساخت و طعمهای محصول را که آنها را تشکیل میدهند پیکربندی میکنید.
برای مثال، طعم محصول «دمو» ممکن است ویژگیها و الزامات دستگاه را مشخص کند، مانند کد منبع سفارشی، منابع، و حداقل سطوح API، در حالی که نوع ساخت «اشکالزدایی» تنظیمات مختلف ساخت و بستهبندی، مانند گزینههای اشکالزدایی و امضا را اعمال میکند. کلیدها نوع ساختی که این دو را ترکیب میکند، نسخه «demoDebug» برنامه شما است و ترکیبی از پیکربندیها و منابع موجود در طعم محصول «دمو»، نوع ساخت «اشکالزدایی» و مجموعه main/
منبع را شامل میشود.
پیکربندی انواع ساخت
می توانید انواع ساخت را در بلوک android
فایل build.gradle.kts
در سطح ماژول ایجاد و پیکربندی کنید. هنگامی که یک ماژول جدید ایجاد می کنید، Android Studio به طور خودکار انواع ساخت دیباگ و انتشار را ایجاد می کند. اگرچه نوع ساخت اشکالزدایی در فایل پیکربندی ساخت ظاهر نمیشود، Android Studio آن را با debuggable true
پیکربندی میکند. این به شما امکان میدهد برنامه را در دستگاههای Android ایمن اشکالزدایی کنید و امضای برنامه را با یک فروشگاه کلید اشکال زدایی عمومی پیکربندی کنید.
اگر میخواهید تنظیمات خاصی را اضافه یا تغییر دهید، میتوانید نوع ساخت اشکالزدایی را به پیکربندی خود اضافه کنید. نمونه زیر یک applicationIdSuffix
برای نوع ساخت اشکالزدایی مشخص میکند و یک نوع ساخت «staging» را پیکربندی میکند که با استفاده از تنظیمات از نوع ساخت اشکالزدایی مقداردهی اولیه میشود:
کاتلین
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 Studio متوجه هر گونه خطایی در پیکربندی شما شود، پنجره Messages برای توصیف مشکل ظاهر می شود.
برای کسب اطلاعات بیشتر در مورد تمام ویژگی هایی که می توانید با انواع ساخت پیکربندی کنید، مرجع 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
خود را ارائه می دهند:
کاتلین
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>
نام گذاری می کند. به عنوان مثال، اگر طعم های محصول "دمو" و "کامل" را ایجاد کرده باشید و انواع ساخت پیش فرض "debug" و "release" را حفظ کرده باشید، Gradle انواع ساخت زیر را ایجاد می کند:
-
demoDebug
-
demoRelease
-
fullDebug
-
fullRelease
برای انتخاب نوع ساخت و اجرا، به Build > Select Build Variant بروید و یک نوع ساخت را از منو انتخاب کنید. برای شروع سفارشیسازی هر نوع ساخت با ویژگیها و منابع خاص خود، باید مجموعههای منبع را ایجاد و مدیریت کنید ، همانطور که در این صفحه توضیح داده شده است.
شناسه برنامه را برای انواع ساخت تغییر دهید
هنگامی که یک APK یا AAB برای برنامه خود می سازید، ابزارهای ساخت برنامه را با شناسه برنامه تعریف شده در بلوک defaultConfig
از فایل build.gradle.kts
تگ می کنند، همانطور که در مثال زیر نشان داده شده است. با این حال، اگر میخواهید نسخههای مختلفی از برنامهتان را ایجاد کنید تا بهصورت فهرستهای جداگانه در فروشگاه Google Play ظاهر شوند، مانند نسخههای «رایگان» و «حرفهای»، باید نسخههای ساخت جداگانهای ایجاد کنید که هر کدام شناسه برنامه متفاوتی داشته باشند.
در این مورد، هر نوع ساخت را به عنوان طعم محصول جداگانه تعریف کنید. برای هر طعم داخل بلوک productFlavors
، میتوانید ویژگی applicationId
را دوباره تعریف کنید، یا در عوض میتوانید یک بخش را با استفاده از applicationIdSuffix
به شناسه برنامه پیشفرض اضافه کنید، همانطور که در اینجا نشان داده شده است:
کاتلین
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
برای اضافه کردن یک بخش بر اساس نوع ساخت خود استفاده کنید، همانطور که در اینجا نشان داده شده است:
کاتلین
android { ... buildTypes { getByName("debug") { applicationIdSuffix = ".debug" } } }
شیار
android { ... buildTypes { debug { applicationIdSuffix ".debug" } } }
از آنجایی که Gradle پیکربندی نوع ساخت را بعد از طعم محصول اعمال می کند، شناسه برنامه برای نوع ساخت "اشکال زدایی رایگان" "com.example.myapp.free.debug" است. این زمانی مفید است که میخواهید هم اشکال زدایی و هم نسخه انتشار را روی یک دستگاه داشته باشید، زیرا هیچ دو برنامهای نمیتوانند شناسه برنامه یکسانی داشته باشند.
اگر یک برنامه قدیمی (که قبل از اوت 2021 ایجاد شده است) دارید که با استفاده از APK در Google Play توزیع میکنید، و میخواهید از همان فهرست برنامه برای توزیع چندین APK استفاده کنید که هر کدام پیکربندی دستگاه متفاوتی مانند سطح API را هدف قرار میدهند، پس شما باید از همان شناسه برنامه برای هر نوع ساخت استفاده کند اما به هر APKversionCode
متفاوتی بدهد. برای اطلاعات بیشتر، درباره پشتیبانی از APK چندگانه بخوانید. انتشار با استفاده از AAB ها بی تاثیر است، زیرا از یک مصنوع استفاده می کند که به طور پیش فرض از یک کد نسخه و شناسه برنامه استفاده می کند. نکته: اگر نیاز به ارجاع شناسه برنامه در فایل مانیفست خود دارید، میتوانید از مکاننمای ${applicationId}
در هر ویژگی مانیفست استفاده کنید. در طول ساخت، Gradle این تگ را با شناسه واقعی برنامه جایگزین می کند. برای اطلاعات بیشتر، به تزریق متغیرهای ساخت به مانیفست مراجعه کنید.
چندین طعم محصول را با ابعاد طعم ترکیب کنید
در برخی موارد، ممکن است بخواهید پیکربندی هایی را از طعم های مختلف محصول ترکیب کنید. برای مثال، ممکن است بخواهید پیکربندیهای مختلفی را برای طعمهای محصول «کامل» و «دمو» ایجاد کنید که بر اساس سطح API هستند. برای انجام این کار، افزونه Android Gradle به شما امکان می دهد چندین گروه از طعم های محصول را به عنوان ابعاد طعم ایجاد کنید.
هنگام ساخت اپلیکیشن، Gradle یک پیکربندی طعم محصول را از هر بعد طعمی که تعریف میکنید، همراه با پیکربندی نوع ساخت ترکیب میکند تا نوع ساخت نهایی را ایجاد کند. Gradle طعم های محصول را که متعلق به یک بعد طعم هستند ترکیب نمی کند.
نمونه کد زیر از ویژگی flavorDimensions
برای ایجاد یک بعد طعم "mode" برای گروه بندی طعم های محصول "full" و "demo" و یک بعد طعم "api" برای گروه بندی تنظیمات طعم محصول بر اساس سطح API استفاده می کند:
کاتلین
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 هر نوع ساخت یا مصنوعات مربوطه را نام میبرد، طعمهای محصول متعلق به بعد طعم با اولویت بالاتر ابتدا ظاهر میشوند، سپس طعمهای مربوط به ابعاد با اولویت پایینتر و سپس نوع ساخت ظاهر میشوند.
با استفاده از پیکربندی ساخت قبلی به عنوان مثال، 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
علاوه بر دایرکتوریهای مجموعه منبعی که میتوانید برای هر طعم محصول و نوع ساخت ایجاد کنید، همچنین میتوانید فهرستهای منبع مجموعه را برای هر ترکیبی از طعمهای محصول ایجاد کنید. به عنوان مثال، میتوانید منابع جاوا را به دایرکتوری src/demoMinApi24/java/
ایجاد و اضافه کنید، و Gradle از این منابع فقط در هنگام ساختن گونهای استفاده میکند که این دو طعم محصول را با هم ترکیب میکند.
مجموعههای منبعی که برای ترکیب طعم محصول ایجاد میکنید، اولویت بیشتری نسبت به مجموعههای منبعی دارند که به هر طعم محصول اختصاص دارند. برای کسب اطلاعات بیشتر درباره مجموعههای منبع و نحوه ادغام منابع Gradle، بخش نحوه ایجاد مجموعههای منبع را بخوانید.
انواع فیلتر
Gradle یک نوع ساخت برای هر ترکیب ممکن از طعم محصول و انواع ساختی که شما پیکربندی می کنید ایجاد می کند. با این حال، ممکن است انواع خاصی از ساخت وجود داشته باشد که شما به آنها نیاز ندارید یا در زمینه پروژه شما منطقی نیستند. برای حذف برخی از پیکربندیهای نوع ساخت، یک فیلتر متغیر در فایل build.gradle.kts
در سطح ماژول خود ایجاد کنید.
با استفاده از پیکربندی ساخت بخش قبلی به عنوان مثال، فرض کنید قصد دارید فقط سطوح API 23 و بالاتر را برای نسخه آزمایشی برنامه پشتیبانی کنید. میتوانید از بلوک variantFilter
برای فیلتر کردن تمام پیکربندیهای نوع ساخت که ترکیبی از طعمهای محصول «minApi21» و «demo» هستند استفاده کنید:
کاتلین
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 هر نوع ساختی را که شرایطی را که شما مشخص کردهاید برآورده میکند نادیده میگیرد. وقتی روی Build > انتخاب نوع ساخت از نوار منو یا Build Variants کلیک می کنید، دیگر در منو ظاهر نمی شود. در نوار پنجره ابزار
مجموعه های منبع ایجاد کنید
به طور پیشفرض، Android Studio مجموعه main/
منبع و دایرکتوریها را برای هر چیزی که میخواهید بین همه انواع ساخت خود به اشتراک بگذارید، ایجاد میکند. با این حال، میتوانید مجموعههای منبع جدیدی ایجاد کنید تا دقیقاً کنترل کنید که Gradle کدام فایلها را کامپایل و بستهبندی میکند برای انواع ساختهای خاص، طعمهای محصول، ترکیب طعمهای محصول (هنگام استفاده از ابعاد طعم )، و انواع ساخت.
به عنوان مثال، میتوانید عملکرد اصلی را در مجموعه main/
منبع تعریف کنید و از مجموعههای منبع طعم محصول برای تغییر نام تجاری برنامه خود برای مشتریان مختلف استفاده کنید، یا مجوزهای ویژه و عملکرد گزارشگیری را فقط برای انواع ساختهایی که از نوع ساخت اشکالزدایی استفاده میکنند، بگنجانید.
Gradle انتظار دارد که فایلها و دایرکتوریهای مجموعه منبع به روشی خاص، مشابه مجموعه main/
منبع سازماندهی شوند. به عنوان مثال، Gradle انتظار دارد فایلهای کلاس Kotlin یا Java که مخصوص نوع ساخت «debug» شما هستند در فهرستهای src/debug/kotlin/
یا src/debug/java/
قرار گیرند.
افزونه Android Gradle یک کار مفید Gradle را ارائه می دهد که به شما نشان می دهد چگونه فایل های خود را برای هر یک از انواع ساخت، طعم محصول و انواع ساخت خود سازماندهی کنید. به عنوان مثال، نمونه زیر از خروجی وظیفه توضیح می دهد که Gradle انتظار دارد فایل های خاصی را برای نوع ساخت "debug" پیدا کند:
------------------------------------------------------------ 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 دوبار کلیک کنید.
برای دیدن پوشه Tasks ، باید به Gradle اجازه دهید تا لیست وظایف را در حین همگام سازی بسازد. برای انجام این کار، این مراحل را دنبال کنید:
- روی File > Settings > Experimental ( Android Studio > Settings > Experimental on macOS) کلیک کنید.
- در حین همگام سازی Gradle، لیست وظایف Gradle ایجاد نشود را لغو انتخاب کنید.
- بعد از اینکه Gradle وظیفه را اجرا کرد، پنجره Run برای نمایش خروجی باز می شود.
توجه: خروجی وظیفه همچنین به شما نشان میدهد که چگونه مجموعههای منبع را برای فایلهایی که میخواهید برای اجرای آزمایشهای برنامه خود استفاده کنید، مانند مجموعههای منبع test/
و androidTest/
آزمایش سازماندهی کنید.
هنگامی که یک نوع ساخت جدید ایجاد می کنید، Android Studio دایرکتوری های مجموعه منبع را برای شما ایجاد نمی کند، اما چند گزینه برای کمک به شما در اختیار شما قرار می دهد. به عنوان مثال، برای ایجاد فقط دایرکتوری java/
برای نوع ساخت "debug" خود:
- پنجره Project را باز کنید و نمای پروژه را از منوی بالای صفحه انتخاب کنید.
- به
MyProject/app/src/
بروید. - روی دایرکتوری
src
کلیک راست کرده و New > Directory را انتخاب کنید. - از منوی Gradle Source Sets ، full/java را انتخاب کنید.
- Enter را فشار دهید.
اندروید استودیو یک دایرکتوری مجموعه منبع برای نوع ساخت اشکال زدایی شما ایجاد می کند و سپس دایرکتوری java/
را در داخل آن ایجاد می کند. از طرف دیگر، Android Studio می تواند زمانی که یک فایل جدید را برای یک نوع ساخت خاص به پروژه خود اضافه می کنید، دایرکتوری ها را برای شما ایجاد کند.
به عنوان مثال، برای ایجاد یک فایل XML مقادیر برای نوع ساخت "debug" خود:
- در پنجره Project ، روی دایرکتوری
src
کلیک راست کرده و New > XML > Values XML File را انتخاب کنید. - نام فایل XML را وارد کنید یا نام پیش فرض را نگه دارید.
- از منوی کنار Target Source Set ، debug را انتخاب کنید.
- روی Finish کلیک کنید.
از آنجایی که نوع ساخت «اشکالزدایی» بهعنوان مجموعه منبع هدف مشخص شده بود، Android Studio بهطور خودکار فهرستهای لازم را هنگام ایجاد فایل XML ایجاد میکند. ساختار دایرکتوری حاصل مانند شکل 1 است.
مجموعه های منبع فعال دارای یک نشانگر سبز رنگ در نماد خود هستند تا نشان دهند که فعال هستند. مجموعه منبع debug
با پسوند [main]
اضافه می شود تا نشان دهد که در مجموعه منبع main
ادغام خواهد شد.
با استفاده از همین رویه، همچنین میتوانید فهرستهای منبع مجموعهای را برای طعمهای محصول، مانند src/demo/
، و انواع ساخت، مانند src/demoDebug/
ایجاد کنید. علاوه بر این، میتوانید مجموعههای منبع آزمایشی ایجاد کنید که انواع ساختهای خاص را هدف قرار میدهند، مانند src/androidTestDemoDebug/
. برای کسب اطلاعات بیشتر، درباره تست مجموعه های منبع مطالعه کنید.
تنظیمات پیش فرض مجموعه منبع را تغییر دهید
اگر منابعی دارید که در ساختار فایل مجموعه منبع پیشفرض سازماندهی نشدهاند که Gradle انتظار دارد، همانطور که در بخش قبلی درباره ایجاد مجموعههای منبع توضیح داده شد، میتوانید از بلوک sourceSets
برای تغییر مکان ظاهری Gradle برای جمعآوری فایلها برای هر جزء از یک منبع استفاده کنید. مجموعه
بلوک sourceSets
باید در بلوک android
باشد. شما نیازی به تغییر مکان فایل های منبع ندارید. شما فقط باید مسیر(های) را نسبت به فایل build.gradle.kts
سطح ماژول در اختیار Gradle قرار دهید، جایی که Gradle میتواند فایلها را برای هر جزء مجموعه منبع پیدا کند. برای اینکه بدانید کدام مؤلفهها را میتوانید پیکربندی کنید و آیا میتوانید آنها را به چندین فایل یا فهرست راهنما نگاشت کنید، به مرجع API افزونه Android Gradle مراجعه کنید.
نمونه کد زیر منابع را از دایرکتوری app/other/
به اجزای خاصی از مجموعه منبع main
نگاشت و دایرکتوری ریشه مجموعه منبع androidTest
را تغییر می دهد:
کاتلین
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 Studio ماژول های IntelliJ جداگانه برای هر مجموعه منبع ایجاد می کند و نمی تواند از ریشه های محتوای تکراری در مجموعه های منبع پشتیبانی کند.
ساخت با مجموعه های منبع
شما می توانید از دایرکتوری های مجموعه منبع استفاده کنید تا حاوی کد و منابعی باشد که می خواهید فقط با تنظیمات خاصی بسته بندی شوند. به عنوان مثال، اگر شما در حال ساخت نوع "demoDebug" هستید که محصول متقاطع طعم محصول "دمو" و نوع ساخت "debug" است، Gradle به این دایرکتوری ها نگاه می کند و اولویت زیر را به آنها می دهد:
-
src/demoDebug/
(مجموعه منبع نوع ساخت) -
src/debug/
(مجموعه منبع نوع ساخت) -
src/demo/
(مجموعه منبع طعم محصول) -
src/main/
(مجموعه منبع اصلی)
مجموعه های منبع ایجاد شده برای ترکیبی از طعم های محصول باید شامل تمام ابعاد طعم باشد. به عنوان مثال، مجموعه منبع نوع ساخت باید ترکیبی از نوع ساخت و تمام ابعاد طعم باشد. ادغام کد و منابعی که شامل پوشههایی میشود که چندین ابعاد را پوشش میدهند اما همه ابعاد طعم را پوشش نمیدهند، پشتیبانی نمیشود.
اگر چندین طعم محصول را ترکیب کنید ، اولویت بین طعم های محصول با توجه به بعد طعمی که به آن تعلق دارند تعیین می شود. هنگام فهرستبندی ابعاد طعم با ویژگی android.flavorDimensions
، طعمهای محصولی که به بعد طعم اولی که فهرست میکنید، اولویت بیشتری نسبت به طعمهای متعلق به بعد طعم دوم دارند و غیره. علاوه بر این، مجموعههای منبعی که برای ترکیبی از طعمهای محصول ایجاد میکنید، اولویت بیشتری نسبت به مجموعههای منبعی دارند که به طعم محصول جداگانه تعلق دارند.
ترتیب اولویت تعیین میکند که وقتی Gradle کد و منابع را ترکیب میکند، کدام مجموعه منبع اولویت بیشتری دارد. از آنجایی که دایرکتوری demoDebug/
source set احتمالا حاوی فایل هایی است که مختص آن نوع ساخت هستند، اگر 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
، اولویت به همان ترتیب لیست در مثال قبلی داده می شود. یعنی مقادیر تعریف شده در یک فایل در مجموعه منبع نوع ساخت، مقادیر تعریف شده در همان فایل در طعم محصول و غیره را لغو می کنند. - منابع موجود در دایرکتوری های
res/
وasset/
با هم بسته بندی می شوند. اگر منابعی با نام یکسان در دو یا چند مجموعه منبع تعریف شده باشد، اولویت به همان ترتیب لیست در مثال قبلی داده می شود. - Gradle به منابع و مانیفست های موجود در وابستگی های ماژول کتابخانه کمترین اولویت را هنگام ساخت برنامه می دهد.
وابستگی ها را اعلام کنید
برای پیکربندی یک وابستگی برای یک نوع ساخت خاص یا مجموعه منبع آزمایشی ، پیشوند نام نوع ساخت یا مجموعه منبع آزمایشی را قبل از کلمه کلیدی Implementation
قرار دهید، همانطور که در مثال زیر نشان داده شده است:
کاتلین
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' }
برای اطلاعات بیشتر درباره پیکربندی وابستگیها، به افزودن وابستگیهای ساخت مراجعه کنید.
از مدیریت وابستگی آگاهانه استفاده کنید
افزونه Android Gradle نسخه 3.0.0 و بالاتر شامل یک مکانیسم وابستگی جدید است که به طور خودکار انواع را هنگام مصرف یک کتابخانه مطابقت می دهد. این به این معنی است که نوع debug
یک برنامه به طور خودکار نوع debug
یک کتابخانه و غیره را مصرف می کند. همچنین هنگام استفاده از طعمها کار میکند: نوع freeDebug
یک برنامه، نوع freeDebug
یک کتابخانه را مصرف میکند.
برای اینکه این افزونه به طور دقیق با انواع مختلف مطابقت داشته باشد، باید بک گراندهای منطبق را همانطور که در بخش زیر توضیح داده شده است ارائه دهید ، برای نمونه هایی که تطبیق مستقیم امکان پذیر نیست.
به عنوان مثال، فرض کنید برنامه شما یک نوع ساخت به نام "staging" را پیکربندی می کند، اما یکی از وابستگی های کتابخانه آن این کار را نمی کند. وقتی افزونه سعی میکند نسخه «staging» برنامه شما را بسازد، نمیداند از کدام نسخه کتابخانه استفاده کند و یک پیام خطایی شبیه به زیر مشاهده میکنید:
Error:Failed to resolve: Could not resolve project :mylibrary. Required by: project :app
خطاهای ساخت مربوط به تطبیق انواع را حل کنید
این افزونه شامل عناصر DSL است تا به شما کمک کند نحوه حل و فصل موقعیتهایی را که در آنها تطبیق نوع مستقیم بین یک برنامه و یک وابستگی امکانپذیر نیست را کنترل کنید.
در زیر فهرستی از مسائل مربوط به تطبیق وابستگی با نوع آگاه و نحوه حل آنها با استفاده از ویژگی های DSL آمده است:برنامه شما دارای یک نوع ساخت است که وابستگی کتابخانه آن را ندارد.
به عنوان مثال، برنامه شما شامل یک نوع ساخت "staging" است، اما یک وابستگی فقط شامل انواع ساخت "debug" و "release" است.
توجه داشته باشید که وقتی وابستگی کتابخانه شامل یک نوع ساخت است که برنامه شما ندارد، مشکلی وجود ندارد. دلیلش این است که پلاگین هرگز آن نوع ساخت را از وابستگی درخواست نمی کند.
همانطور که در اینجا نشان داده شده است، از
matchingFallbacks
برای تعیین موارد مشابه برای یک نوع ساخت معین استفاده کنید:کاتلین
// 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
برای تعیین موارد مشابه برای طعم محصول "رایگان" برنامه استفاده کنید:کاتلین
// 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
لغو کنید، بنابراین هر طعم میتواند استراتژی تطبیقی متفاوتی را برای بعد گمشده مشخص کند.کاتلین
// 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 پلاگین Android Gradle ببینید.
تنظیمات امضا را پیکربندی کنید
Gradle APK یا AAB ساخت نسخه شما را امضا نمیکند مگر اینکه صریحاً یک پیکربندی امضا برای این ساخت تعریف کنید. اگر هنوز کلید امضا ندارید، یک کلید آپلود و ذخیره کلید با استفاده از Android Studio ایجاد کنید .
برای پیکربندی دستی پیکربندی های امضا برای نوع ساخت نسخه خود با استفاده از تنظیمات ساخت Gradle:
- یک فروشگاه کلید ایجاد کنید. انبار کلید یک فایل باینری است که شامل مجموعه ای از کلیدهای خصوصی است. شما باید فروشگاه کلید خود را در مکانی امن و مطمئن نگه دارید.
- یک کلید خصوصی ایجاد کنید. یک کلید خصوصی برای امضای برنامه شما برای توزیع استفاده میشود و هرگز همراه برنامه نیست و در اختیار اشخاص ثالث غیرمجاز قرار نمیگیرد.
پیکربندی امضا را به فایل
build.gradle.kts
در سطح ماژول اضافه کنید:کاتلین
... 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 } } }
توجه: گنجاندن گذرواژههای کلید انتشار و ذخیرهسازی کلید در داخل فایل ساخت، عمل امنیتی خوبی نیست. درعوض، فایل ساخت را طوری پیکربندی کنید که این پسوردها را از متغیرهای محیطی دریافت کند یا فرآیند ساخت را از شما بخواهد که این پسوردها را دریافت کنید.
برای بدست آوردن این رمزهای عبور از متغیرهای محیطی:
کاتلین
storePassword = System.getenv("KSTOREPWD") keyPassword = System.getenv("KEYPWD")
شیار
storePassword System.getenv("KSTOREPWD") keyPassword System.getenv("KEYPWD")
همچنین، میتوانید keystore را از یک فایل ویژگیهای محلی بارگیری کنید. به دلایل امنیتی، این فایل را به کنترل منبع اضافه نکنید. در عوض، آن را به صورت محلی برای هر توسعه دهنده تنظیم کنید. برای کسب اطلاعات بیشتر، حذف اطلاعات امضا از فایلهای ساخت خود را بخوانید.
پس از تکمیل این فرآیند، می توانید برنامه خود را توزیع کرده و آن را در Google Play منتشر کنید.
اخطار: فروشگاه کلید و کلید خصوصی خود را در مکانی امن و مطمئن نگه دارید و مطمئن شوید که پشتیبان امنی از آنها دارید. اگر از Play App Signing استفاده میکنید و کلید آپلود خود را گم میکنید، میتوانید با استفاده از Play Console درخواست بازنشانی کنید . اگر برنامهای را بدون Play App Signing منتشر میکنید (برای برنامههایی که قبل از آگوست 2021 ایجاد شدهاند) و کلید امضای برنامه خود را از دست میدهید، نمیتوانید هیچ بهروزرسانی برای برنامه خود منتشر کنید، زیرا همیشه باید همه نسخههای برنامه خود را با همان کلید
امضای برنامههای Wear OS
هنگام انتشار برنامههای Wear OS، APK ساعت و APK اختیاری تلفن باید با یک کلید امضا شوند. برای اطلاعات بیشتر درباره بستهبندی و امضای برنامههای Wear OS، به بستهبندی و توزیع برنامههای Wear مراجعه کنید.