Android: Membuat Citarasa Produk Dinamis dan Menandatangani Konfigurasi

Ketika bekerja pada proyek Android, yang merupakan platform untuk membuat aplikasi untuk melihat konten video, menjadi perlu untuk secara dinamis mengkonfigurasi rasa produk dengan transfer informasi tentang menandatangani konfigurasi ke file eksternal. Detail di bawah potongan.


Sumber data


Ada proyek Android, yang merupakan platform untuk membuat aplikasi untuk melihat konten video. Basis kode umum untuk semua aplikasi, perbedaannya ada pada pengaturan parameter REST API dan pengaturan untuk penampilan aplikasi (spanduk, warna, font, dll.). Tiga dimensi rasa digunakan dalam proyek:


  1. pasar : google atau amazon. Karena aplikasi didistribusikan baik di Google Play dan di Amazon Marketplace, ada kebutuhan untuk berbagi beberapa fungsi tergantung pada tempat distribusi. Misalnya: Amazon melarang penggunaan mekanisme Pembelian Dalam Aplikasi dari Google dan mensyaratkan penerapan mekanismenya.
  2. endpoint : "pro" atau "staging". Konfigurasi khusus untuk versi produksi dan pementasan.
  3. situs : dimensi aktual untuk aplikasi tertentu. Tetapkan applicationId dan penandatanganan Konfigurasi.

Masalah yang kami temui


Saat membuat aplikasi baru, perlu menambahkan Flavour Produk:


application1 { dimension 'site' applicationId 'com.damsols.application1' signingConfig signingConfigs.application1 } 

Selain itu, perlu untuk menambahkan Konfigurasi Penandatanganan yang sesuai:


 application1 { storeFile file("path_to_keystore1.jks") storePassword "password1" keyAlias "application1" keyPassword "password1" } 

Masalahnya:


  1. lima baris untuk menambahkan satu aplikasi, hanya berbeda di applicationId dan penandatanganan Konfigurasi. Ketika jumlah aplikasi menjadi lebih dari 50, file build.gradle mulai berisi lebih dari 500 baris informasi aplikasi.
  2. penyimpanan dalam informasi teks biasa tentang keystore untuk menandatangani aplikasi.

Contoh build.gradle
 apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false } } flavorDimensions "site", "endpoint", "market" signingConfigs { application1 { storeFile file("application1.jks") storePassword "password1" keyAlias "application1" keyPassword "password1" } application2 { storeFile file("application2.jks") storePassword "password2" keyAlias "application2" keyPassword "password2" } application3 { storeFile file("application3.jks") storePassword "password3" keyAlias "application3" keyPassword "password3" } } productFlavors { pro { dimension 'endpoint' } staging { dimension 'endpoint' } google { dimension 'market' } amazon { dimension 'market' } application1 { dimension 'site' applicationId "com.damsols.application1" signingConfig signingConfigs.application1 } application2 { dimension 'site' applicationId "com.damsols.application2" signingConfig signingConfigs.application2 } application3 { dimension 'site' applicationId "com.damsols.application3" signingConfig signingConfigs.application3 } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' } 

Menghapus Informasi Sertifikat


Langkah pertama adalah mentransfer informasi sertifikat ke file json yang terpisah. Misalnya, informasi juga disimpan dalam teks biasa, tetapi tidak ada yang mencegah Anda menyimpan file dalam bentuk terenkripsi (kami menggunakan GPG) dan mendekripsi langsung saat membangun aplikasi. File JSON memiliki struktur berikut:


 { "signingConfigs":[ { "configName":"application1", "storeFile":"application1.jks", "storePassword":"password1", "keyAlias":"application1", "keyPassword":"password1" }, { "configName":"application2", "storeFile":"application2.jks", "storePassword":"password2", "keyAlias":"application2", "keyPassword":"password2" }, { "configName":"application3", "storeFile":"application3.jks", "storePassword":"password3", "keyAlias":"application3", "keyPassword":"password3" }, ] } 

Bagian penandatanganan Konfigurasi di file build.gradle dihapus.


Sederhanakan Bagian Rasa Produk


Untuk mengurangi jumlah baris yang diperlukan untuk menggambarkan Flavour Produk dengan dimensi = "situs", sebuah array dibuat dengan informasi yang diperlukan untuk menggambarkan aplikasi tertentu, dan semua Flavour Produk dengan dimensi = "situs" dihapus.
Itu:


 ... productFlavors { pro { dimension 'endpoint' } staging { dimension 'endpoint' } google { dimension 'market' } amazon { dimension 'market' } application1 { dimension 'site' applicationId "com.damsols.application1" signingConfig signingConfigs.application1 } application2 { dimension 'site' applicationId "com.damsols.application2" signingConfig signingConfigs.application2 } application3 { dimension 'site' applicationId "com.damsols.application3" signingConfig signingConfigs.application3 } } } ... 

Itu menjadi:


 ... productFlavors { pro { dimension 'endpoint' } staging { dimension 'endpoint' } google { dimension 'market' } amazon { dimension 'market' } } def applicationDefinitions = [ ['name': 'application1', 'applicationId': 'com.damsols.application1'], ['name': 'application2', 'applicationId': 'com.damsols.application2'], ['name': 'application3', 'applicationId': 'com.damsols.application3'] ] } ... 

Penciptaan Rasa Produk Dinamis


Langkah terakhir adalah secara dinamis membuat rasa produk dan menandatangani konfigurasi menggunakan file JSON eksternal dengan informasi sertifikat dari array applicationDefinitions.


 def applicationDefinitions = [ ['name': 'application1', 'applicationId': 'com.damsols.application1'], ['name': 'application2', 'applicationId': 'com.damsols.application2'], ['name': 'application3', 'applicationId': 'com.damsols.application3'] ] def signKeysFile = file('signkeys/signkeys.json') def signKeys = new JsonSlurper().parseText(signKeysFile.text) def configs = signKeys.signingConfigs def signingConfigsMap = [:] configs.each { config -> signingConfigsMap[config.configName] = config } applicationDefinitions.each { applicationDefinition -> def signingConfig = signingConfigsMap[applicationDefinition['name']] android.productFlavors.create(applicationDefinition['name'], { flavor -> flavor.dimension = 'site' flavor.applicationId = applicationDefinition['applicationId'] flavor.signingConfig = android.signingConfigs.create(applicationDefinition['name']) flavor.signingConfig.storeFile = file(signingConfig.storeFile) flavor.signingConfig.storePassword = signingConfig.storePassword flavor.signingConfig.keyAlias = signingConfig.keyAlias flavor.signingConfig.keyPassword = signingConfig.keyPassword }) } 

Untuk menambahkan bacaan dari penyimpanan terenkripsi, Anda perlu mengganti bagian


 def signKeysFile = file('signkeys/signkeys.json') def signKeys = new JsonSlurper().parseText(signKeysFile.text) def configs = signKeys.signingConfigs 

untuk membaca dari file yang dienkripsi.


build.gradle keseluruhan
 import groovy.json.JsonSlurper apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false } } flavorDimensions "site", "endpoint", "market" signingConfigs {} productFlavors { pro { dimension 'endpoint' } staging { dimension 'endpoint' } google { dimension 'market' } amazon { dimension 'market' } } } def applicationDefinitions = [ ['name': 'application1', 'applicationId': 'com.damsols.application1'], ['name': 'application2', 'applicationId': 'com.damsols.application2'], ['name': 'application3', 'applicationId': 'com.damsols.application3'] ] def signKeysFile = file('signkeys/signkeys.json') def signKeys = new JsonSlurper().parseText(signKeysFile.text) def configs = signKeys.signingConfigs def signingConfigsMap = [:] configs.each { config -> signingConfigsMap[config.configName] = config } applicationDefinitions.each { applicationDefinition -> def signingConfig = signingConfigsMap[applicationDefinition['name']] android.productFlavors.create(applicationDefinition['name'], { flavor -> flavor.dimension = 'site' flavor.applicationId = applicationDefinition['applicationId'] flavor.signingConfig = android.signingConfigs.create(applicationDefinition['name']) flavor.signingConfig.storeFile = file(signingConfig.storeFile) flavor.signingConfig.storePassword = signingConfig.storePassword flavor.signingConfig.keyAlias = signingConfig.keyAlias flavor.signingConfig.keyPassword = signingConfig.keyPassword }) } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' } 

Tautan GitHub


Terima kasih

Source: https://habr.com/ru/post/id434994/


All Articles