Як створити APK-файл, підписаний релізом, за допомогою Gradle?


514

Я хотів би створити мій Gradle, щоб створити apk-файл, підписаний релізом, за допомогою Gradle.

Я не впевнений, чи правильний код або якщо мені не вистачає параметра при виконанні gradle build?

Це деякий код у моєму файлі gradle:

android {
    ...
    signingConfigs {
          release {
              storeFile file("release.keystore")
              storePassword "******"
              keyAlias "******"
              keyPassword "******"
         }
     }
}

Збірка gradle закінчується SUCCESSFUL, і в моїй build/apkпапці я бачу лише ...-release-unsigned.apkі ...-debug-unaligned.apkфайли.

Будь-які пропозиції, як це вирішити?



підписати з v1 (jar підпис) або v2 (повний підпис apk) версія з файлу gradle? Рішення тут: stackoverflow.com/questions/57943259 / ...
user1506104

Відповіді:


429

Простіший спосіб, ніж попередні відповіді:

Покладіть це в ~/.gradle/gradle.properties

RELEASE_STORE_FILE={path to your keystore}
RELEASE_STORE_PASSWORD=*****
RELEASE_KEY_ALIAS=*****
RELEASE_KEY_PASSWORD=*****

Змініть свій app/build.gradleі додайте це всередину android {кодового блоку:

...    
signingConfigs {

   release {
       storeFile file(RELEASE_STORE_FILE)
       storePassword RELEASE_STORE_PASSWORD
       keyAlias RELEASE_KEY_ALIAS
       keyPassword RELEASE_KEY_PASSWORD

       // Optional, specify signing versions used
       v1SigningEnabled true
       v2SigningEnabled true
   }
}

buildTypes {
        release {
            signingConfig signingConfigs.release
        }
}
....

Тоді можна бігти gradle assembleRelease


Також дивіться посилання на signingConfigsDSL Gradle


12
Найкращий метод, якщо ви запитаєте мене. Нічого не зберігає в моїй папці проекту / SVN, і я можу перевірити 10 версій своїх проектів, не турбуючись про ключі.
Френк

8
Якщо ви використовуєте gradlew в Windows, вам потрібно бути впевненим, що GRADLE_USER_HOME визначений як змінна середовище, щоб зробити цю роботу. Я встановив його в одну директорію над каталогом моїх проектів і поклав туди свій магазин ключів. Шлях до вашої сховища ключів у gradle.properties повинен використовувати косою косою рискою вперед (/) або подвійною косою косою рисою (\\), а не однією косою рисою Windows. Щоб створити сховище ключів з командного рядка Windows, див. Stackoverflow.com/questions/3997748/how-can-i-create-a-keystore
Анахроніст

3
Чи шлях відносно того, де знаходиться файл build.gradle, чи відносно кореневого каталогу машин?
Прем

1
@Prem, file()завжди бере на себе відносні шляхи. Використовуйте, new File(path)якщо ви хочете, щоб це трактувалося як абсолютне.
ars-longa-vita-brevis

4
Це працювало для мене і найпростіше. У gradle.properties вкажіть storeFile відносно вашого модуля build.gradle, як RELEASE_STORE_FILE = .. / mykeystore. Не додайте котирування ще gradle mangles the path
Lakshman Chilukuri

263

Мені вдалося вирішити його, додавши цей код і створивши gradle build:

android {
    ...
    signingConfigs {
        release {
            storeFile file("release.keystore")
            storePassword "******"
            keyAlias "******"
            keyPassword "******"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

Це генерує підписаний реліз apk-файл.


33
Чи є спосіб, щоб він запропонував мені ввести паролі? Або інші пропозиції, щоб не зберігати паролі від моїх git repos?
користувач672009

3
Я редагую свій build.gradle, щоб він виглядав як ваш, але запуск "Вбудований> Створити підписаний APK ..." все ще дає мені це діалогове вікно ("Докладнішу інформацію див. У Посібнику користувача Gradle." Тощо) та жодному APK.
Semanticer

3
@Semanticer Виконати gradle buildабо gradlew buildв команді Terminal / Prompt
Phillip Kamikaze

12
@ user672009 ви ​​можете помістити паролі у файл властивостей і виключити його з репозиції за допомогою .gitignore. Ви можете побачити це посилання. gist.github.com/gabrielemariotti/6856974
Gabriele Mariotti

1
@GabrieleMariotti Це все ще залишає неповне сховище. Кращим способом було б створити скелет підписання.властивості і після вчинення видачі "git update-index - assume-unhanged signature.properties". Однак це запобігає здійсненню правок редагування futura. Щось на зразок першого варіанту, який пропонує sdqali, здається ще кращим.
користувач672009

67

Зауважте, що сценарій @ sdqali буде (принаймні при використанні Gradle 1.6) запитувати пароль будь-коли, коли ви викликаєте будь- яке завдання gradle. Оскільки вам це потрібно лише під час виконання gradle assembleRelease(або подібного), ви можете використовувати наступний трюк:

android {
    ...
    signingConfigs {
        release {
            // We can leave these in environment variables
            storeFile file(System.getenv("KEYSTORE"))
            keyAlias System.getenv("KEY_ALIAS")

            // These two lines make gradle believe that the signingConfigs
            // section is complete. Without them, tasks like installRelease
            // will not be available!
            storePassword "notYourRealPassword"
            keyPassword "notYourRealPassword"
        }
    }
    ...
}

task askForPasswords << {
    // Must create String because System.readPassword() returns char[]
    // (and assigning that below fails silently)
    def storePw = new String(System.console().readPassword("Keystore password: "))
    def keyPw  = new String(System.console().readPassword("Key password: "))

    android.signingConfigs.release.storePassword = storePw
    android.signingConfigs.release.keyPassword = keyPw
}

tasks.whenTaskAdded { theTask -> 
    if (theTask.name.equals("packageRelease")) {
        theTask.dependsOn "askForPasswords"
    }
}

Зауважте, що я також повинен був додати наступне (під android), щоб він працював:

buildTypes {
    release {
        signingConfig signingConfigs.release
    }
}

Після реалізації цього installReleaseзник із переліку завдань ... Чому?
Каарел

1
@caspase Бажаю, я серйозніше поставився до Вашого коментаря щодо фальшивих "storePassword" та "keyPassword". Без ініціалізації цих властивостей ("" наприклад) підписаний * -release.apk не створюється, помилка не відображається, і ви залишаєтеся спантеличеними лише за допомогою * -release-unsigned.apk у вашому каталозі PROJECT_NAME / build / apk / . Людина ...: /
vizZ

Дякуємо за примітку про додавання SignConfig під buildTypes -> Release. Це вирішило автоматизований підпис для мене!
mm2001

1
Я зробив простий плагін gradle, який запитує паролі при складанні випуску apk (використовуючи математику, описану в цій публікації, але вам не потрібно буде визначати підроблені storePassword & keyPassword). Він також доступний у Maven central. github.com/alexvasilkov/AndroidGradleSignPlugin
Олексій Васильков

Це чудово. KEYSTOREБудьте уважні, що змінна середовища повинна бути визначена навіть для налагодження налагодження та для синхронізації з градусами всередині Android Studio, інакше це призведе до помилки з приводу того, що шлях є нульовим.
Джеррі101

63

Якщо ви хочете уникнути жорсткого кодування вашої сховища ключів та пароля у build.gradle , ви можете використовувати файл властивостей, як пояснено тут: РОБОТА З ПІДТВЕРДЖЕННЯМ КОНФІГИ З ГРАДОМ

В основному:

1) створити файл myproject.properties за адресою / home/ evidenceusernameSense/.signing з таким вмістом:

keystore=[path to]\release.keystore
keystore.password=*********
keyAlias=***********
keyPassword=********

2) створити файл gradle.properties (можливо, в корені каталогу вашого проекту) із вмістом:

MyProject.properties=/home/[username]/.signing/myproject.properties

3) посилайтеся на це у своєму build.gradle так:

    if(project.hasProperty("MyProject.properties")
        && new File(project.property("MyProject.properties")).exists()) {

    Properties props = new Properties()
    props.load(new FileInputStream(file(project.property("MyProject.properties"))))

    signingConfigs {
        release {
            storeFile file(props['keystore'])
            storePassword props['keystore.password']
            keyAlias props['keyAlias']
            keyPassword props['keyPassword']
        }
    }
}

1
Чудово працює! Дякую. Цей код потрібно додати перед розділом buildTypes {}, а розділ повинен оголосити signConfig signConfigs.release як звичайний.
theczessensation

Нарешті я знайшов рішення цієї проблеми. Єдине, що мені справді допомогло! Це може бути прийнятою відповіддю ...
devnull69

39

Автоматичне підписання програми за допомогою Gradle при використанні git

Дивно, скільки існує суперечливих способів зробити це. Ось мій власний шлях, де я намагаюся дотримуватися власної рекомендації Google . Однак їх пояснення не є повністю зрозумілими, тому я детально опишу процедуру для Linux.


Опис:

Інструкції Google за умовчанням автоматично підписувати додаток під час збирання, не зберігаючи паролі та файли підписів у шляху розвитку вашої програми (GIT), є досить неясними. Ось уточнені покрокові інструкції, як це зробити.

Початкові припущення:

У вас є додаток під назвою «MyApp» в директорії , заданої за наступним шляхом: $HOME/projects/mydev/MyApp. Однак каталог MyApp використовується та контролюється за допомогою GIT.

введіть тут опис зображення

Проблема

Ми, очевидно, не хочемо мати своїх підписів чи паролів у будь-якому місці каталогів, що контролюється GIT, навіть якщо ми дуже вміємо використовувати .gitignoreі т.д., все-таки занадто ризиковано і легко помилитися. Таким чином, ми хочемо, щоб наші файли зберігання ключів та підписи були зовні.

Рішення

Нам потрібно зробити три (3) речі:

  1. Створіть файл пароля, який використовуватиме Android Studio
  2. Створіть файл ключа підпису
  3. Відредагуйте build.gradleфайл модуля для використання (1) та (2).

У цьому прикладі ми називаємо два файли:

  1. keystore.properties
  2. MyApp-release-key.jks

Тут можна розмістити обидва ці файли:

cd $HOME/projects/mydev/

(1) Створіть файл пароля для зберігання ключів

Перший файл містить чіткі текстові паролі, використані в; та шляхи до файлу ключа випуску у (2). Почніть із заповнення цього, оскільки це полегшить операцію введення копії для наступного кроку.

cd $HOME/projects/mydev/

Відредагуйте keystore.propertiesтак, щоб його вміст:

storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myKeyAlias
storeFile=myStoreFileLocation

Єдина складна частина тут - це myStoreFileLocation. Це шлях , який видно зbuild.gradle файлу модуля під час збирання. Як правило , це означає , що шлях схожий і по відношенню до: $HOME/projects/mydev/MyApp/app/build.gradle. Тож для того, щоб вказати на MyApp-release-key.jks файл, тут нам потрібно поставити:

../../../MyApp-release-key.jks

Тут ми також вибрали псевдонім "myapp" для ключа. Тоді фінальний файл повинен виглядати:

storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myapp
storeFile=../../../MyApp-release-key.jks

(2) Створіть файл підпису

Другий файл створюється автоматично під час створення ключа підпису. Якщо у вас немає інших програм, і це ваш єдиний сховище ключів, тоді створіть файл за допомогою:

cd $HOME/projects/mydev/
keytool -genkeypair -v -keystore MyApp-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myapp

Тут буде запропоновано два паролі та купа інформації. (Те саме, що в Android Studio.) Тепер скопіюйте та вставте раніше вибрані паролі.

(3) Відредагуйте gradle.buildфайл свого модуля, щоб скористатися вищезазначеним

Наступні частини повинні бути присутніми у файлі збірки Gradle додатка / модуля. По- перше, додайте наступні рядки поза і до того вашого android {}блоку.

//def keystorePropertiesFile = rootProject.file("$HOME/.android/keystore.properties")
def keystorePropertiesFile = rootProject.file("../../keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

Потім, всередині в android {}блоці, додайте:

android {
    ...
    defaultConfig { ... }
    signingConfigs {
            release {
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                storeFile file(keystoreProperties['storeFile'])
                storePassword keystoreProperties['storePassword']
            }
        }
    // Tell Gradle to sign your APK
    buildTypes {
        release {
            signingConfig signingConfigs.release
            ...
        }
    }
}

Тепер із оболонки ви можете знову створити додаток за допомогою:

cd $HOME/projects/mydev/MyApp/app/
./gradlew clean build

Це має створити правильно підписаний додаток, який можна використовувати в Google Play.


ОНОВЛЕННЯ: 2019-04-02

Більш пізні версії keytoolта щось вам говорять про те, що ви повинні використовувати ключовий файл на основі PKCS12 замість оригіналу / за замовчуванням, як я використовую вище. Потім вони продовжують говорити, що ви повинні перетворитись на новий відкритий формат PKCS12. Однак, здається, інструменти розробки Android ще не зовсім готові до цього, тому що якщо ви це зробите, ви отримаєте такі дивні помилки:

com.android.ide.common.signing.KeytoolException:Не вдалося прочитати ключ XXX з магазину "F: \ XXX \ XXX.jks": Отримати ключ не вдалося: Дано, що остаточний блок не зафіксований належним чином. Такі проблеми можуть виникнути, якщо під час дешифрування використовується поганий ключ.

Тому не використовуйте перетворений ключ!


Чи зберігається підписConfigs всередині apk, а потім його може декомпілювати будь-який користувач, щоб отримати паролі, або він не відображається в apk?
JavierSegoviaCordoba

2
Працює як шарм. Дякую, це має бути прийнятий відповідь
pratham kesarkar

Що робити, якщо ви хочете лише зберігати ключ і паролі на сервері збірки? З рішенням вище, кожному розробнику в команді необхідно мати магазин брелоків на своїй локальній машині. Інакше синхронізація проекту Gradle не вдасться: keystore.properties (Немає такого файлу чи каталогу).
Діана Фарін

1
Ви можете встановити фіктивний keystore.propertiesфайл для управління джерелом, тому будує роботу на верстатах для розробників. Я описав установку збірки сервера тут .
dskrvk

1
Зауваження про вашому останньому оновленні про keytoolгенерації PKCS12 сховища ключів: ви можете передати -storetype JKSв keytoolкоманді , щоб встановити тип сховища ключів JKS , який необхідний в Android інструментами.
Тревор Халворсон

35

Як сказав @Destil, але дозвольте іншим, хто не має ключа для створення: Легший спосіб, ніж попередні відповіді:

Покладіть це в ~/.gradle/gradle.properties

RELEASE_STORE_FILE={path to your keystore}
RELEASE_STORE_PASSWORD=*****
RELEASE_KEY_ALIAS=*****
RELEASE_KEY_PASSWORD=*****

Змініть build.gradleподібне:

...    
if(project.hasProperty("RELEASE_STORE_FILE")) {
    signingConfigs {    
       release {
           storeFile file(RELEASE_STORE_FILE)
           storePassword RELEASE_STORE_PASSWORD
           keyAlias RELEASE_KEY_ALIAS
           keyPassword RELEASE_KEY_PASSWORD
       }
    }
}

buildTypes {
    if(project.hasProperty("RELEASE_STORE_FILE")) {
        release {
            signingConfig signingConfigs.release
        }
    }
}
....

Тоді ви можете запустити gradle assembleRelease АБО gradle build


Як встановити шлях у windows: шлях до вашої
магазині

файл storeFile ("C: \\ Користувачі \\ xxxx \\ Документи \\ yyyy \\ mykey.jks") це правильно?
reza_khalafi

28

(У відповідь на користувача672009 вище.)

Ще простіше рішення, якщо ви хочете, щоб ваші паролі не зберігалися в сховищі git; але, хочете включити свій build.gradle в нього, який навіть чудово справляється з ароматами продукту, - це створити окремий файл gradle. Назвемо це «підпис.gradle» (включіть його у свій .gitignore). Так само, як якщо б це був ваш файл build.gradle мінус усе, що не пов’язано з його входом.

android {
    signingConfigs { 
        flavor1 {
            storeFile file("..")
            storePassword ".."
            keyAlias ".."
            keyPassword ".."
        }
        flavor2 {
            storeFile file("..")
            storePassword ".."
            keyAlias ".."
            keyPassword ".."
        }
    }
}

Потім у свій файл build.gradle включіть цей рядок прямо під "застосувати плагін: 'android" "

 apply from: 'signing.gradle'

Якщо у вас немає або не використовується декілька ароматів, перейменуйте "смак1" на "випуск" вище, і ви повинні закінчити. Якщо ви використовуєте ароматизатори, продовжуйте.

Нарешті зв’яжіть свої смакові якості з правильним підписомConfig у вашому файлі build.gradle, і ви повинні закінчити.

  ...

  productFlavors {

      flavor1 {
          ...
          signingConfig signingConfigs.flavor1
      }

      flavor2 {
          ...
          signingConfig signingConfigs.flavor2
      }
  }

  ...

Чи можете ви бути трохи більш конкретним. Я не можу його запустити: "не вдається вирішити підпис символуConfig".
Amio.io

Якщо я включаю 'sign.gradle' в build.gradle - я змушений мати його в сховищі git (інакше я отримую помилку 'sign.gradle не існує'). І якщо я покладу 'sign.gradle' в git, це переможе мету. Як я можу зробити включення sign.gradle необов’язковим?
Ягуар

21

Якщо у вас вже є файл зберігання ключів, він може бути таким же простим, як додавання декількох параметрів до команди збірки:

./gradlew assembleRelease \
 -Pandroid.injected.signing.store.file=$KEYFILE \
 -Pandroid.injected.signing.store.password=$STORE_PASSWORD \
 -Pandroid.injected.signing.key.alias=$KEY_ALIAS \
 -Pandroid.injected.signing.key.password=$KEY_PASSWORD

Не потрібно постійно змінювати проект Android.

Джерело: http://www.tinmith.net/wayne/blog/2014/08/gradle-sign-command-line.htm


18

Це відповідь до користувача672009 та додавання до повідомлення sdqali (його код вийде при створенні налагоджувальної версії кнопкою "Виконати" IDE):

Ви можете використовувати наступний код:

final Console console = System.console();
if (console != null) {

    // Building from console 
    signingConfigs {
        release {
            storeFile file(console.readLine("Enter keystore path: "))
            storePassword console.readLine("Enter keystore password: ")
            keyAlias console.readLine("Enter alias key: ")
            keyPassword console.readLine("Enter key password: ")
        }
    }

} else {

    // Building from IDE's "Run" button
    signingConfigs {
        release {

        }
    }

}

Чи є спосіб мати деякі значення за замовчуванням? Моя магазинна брелок, як правило, однакова. StorePassword зазвичай збігається з keyPassword і keyAlias, як правило, найменуванням проекту в нижньому регістрі.
user672009

@ user672009 ви ​​завжди можете використовувати код Java всередині сценарію.
AChep

1
ви можете скористатися чимось таким: keyPassword new String(console.readPassword("Enter key password: "))щоб ваш пароль не відображався під час введення
Олексій Семенюк

Це більше не працює, див. Github.com/gradle/gradle/isissue/1251
SqAR.org

16

У більш новій Android Studio є дуже легкий графічний спосіб, який також заповнює файл Gradle.

  1. File -> Project Structure

  2. Module -> Виберіть головний модуль ("додаток" або інше спеціальне ім'я)

  3. Signing вкладка -> Плюс зображення, щоб додати нову конфігурацію

  4. Заповнити дані праворуч

  5. ОК і файл Gradle створюється автоматично

  6. Вам потрібно буде вручну додати рядок signingConfig signingConfigs.NameOfYourConfigвсерединіbuiltTypes{release{}}

Зображення:

введіть тут опис зображення

введіть тут опис зображення

Дві важливі (!) Примітки:

(EDIT 12/15)

  1. Щоб створити підписаний APK, вам доведеться відкрити вкладку Термінал Android Studio (внизу основного інтерфейсу) та надати команду ./gradlew assembleRelease

  2. Якщо ви забули keyAlias(що часто трапляється зі мною), вам доведеться ініціювати, Build -> Generate Signed APKщоб запустити процес і побачити ім'я ключа Alias.


2
Це жорстке кодування ваших паролів у build.gradleфайл, правда, чи не так?
Джошуа Пінтер

16

Якщо ви будуєте apk через командний рядок, як я, то ви можете надати конфігурацію підпису як аргументи.

Додайте це до свого build.gradle

def getStore = { ->
    def result = project.hasProperty('storeFile') ? storeFile : "null"
    return result
}

def getStorePassword = { ->
    def result = project.hasProperty('storePassword') ? storePassword : ""
    return result
}

def getKeyAlias = { ->
    def result = project.hasProperty('keyAlias') ? keyAlias : ""
    return result
}

def getKeyPassword = { ->
    def result = project.hasProperty('keyPassword') ? keyPassword : ""
    return result
}

Зробіть signingConfigsтак

signingConfigs {
    release {
        storeFile file(getStore())
        storePassword getStorePassword()
        keyAlias getKeyAlias()
        keyPassword getKeyPassword()
    }
}

Тоді ви виконуєте gradlewтак

./gradlew assembleRelease -PstoreFile="keystore.jks" -PstorePassword="password" -PkeyAlias="alias" -PkeyPassword="password"

Що таке build.gradle? Вищий рівень? Додайте більше коду
Влад

Для уточнення, це app/build.gradleфайл, про який я говорю.
Егіс

11
android {
    compileSdkVersion 17
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 18
    }

    File signFile = rootProject.file('sign/keystore.properties')
    if (signFile.exists()) {
        Properties properties = new Properties()
        properties.load(new FileInputStream(signFile))
        signingConfigs {
            release {
                storeFile rootProject.file(properties['keystore'])
                storePassword properties['storePassword']
                keyAlias properties['keyAlias']
                keyPassword properties['keyPassword']
            }
        }
    }

    buildTypes {
        release {
            runProguard true
            zipAlign true
            proguardFile rootProject.file('proguard-rules.cfg')
            signingConfig signingConfigs.release
        }
        debug {
            runProguard false
            zipAlign true
        }
    }
}

Використовуючи Android Studio 0.5.1, Gradle 1.11 та плагін Gradle 0.9.
JP Ventura

1
Створення властивостей на вимогу (також динамічні властивості) було вимкнено і планується видалити в Gradle 2.0
JP Ventura

10

Ви також можете скористатися параметром -P командного рядка gradle для підписання. У свій build.gradle додайте співочі конфігури так:

signingConfigs {
   release {
       storeFile file("path/to/your/keystore")
       storePassword RELEASE_STORE_PASSWORD
       keyAlias "your.key.alias"
       keyPassword RELEASE_KEY_PASSWORD
   }
}

Тоді зателефонуйте зібрати gradle так:

gradle -PRELEASE_KEYSTORE_PASSWORD=******* -PRELEASE_KEY_PASSWORD=****** build

Ви можете використовувати -P для встановлення storeFile та keyAlias, якщо вам зручніше.

Це в основному рішення Destil, але з параметрами командного рядка.

Щоб отримати докладніші відомості про властивості gradle, перегляньте посібник користувача gradle .


7

@ Відповідь Дестіля хороша, якщо ви можете повторно використовувати однакову конфігурацію для всіх проектів. Крім того, Android Studio постачається з local.propertiesфайлом, який може бути використаний натомість, але він нібито створюється IDE, і я не можу знайти спосіб його розширення з Android Studio.

Це варіант відповіді @ jonbo . Ця відповідь дозволяє налаштувати конкретні параметри проекту, але він має дещо накладні витрати розробника. Зокрема, для переміщення signingConfigsвизначення в окремий файл необхідна значна котловарна плита, особливо якщо це потрібно зробити для декількох проектів, що є основною причиною для вибору цього рішення над Destil's. Це може бути кілька полегшено також включає лінію

apply plugin: 'com.android.application'

у файлі облікових даних, оскільки це дозволить завершити IDE.

Нарешті, більшість рішень тут не дозволяють будувати проект у режимі налагодження - який обробляє підпис налагодження автоматично - без надання синтаксичного, якщо не семантично допустимого signingConfigsвизначення. Якщо вам не потрібно виробляти збірку релізів з даної машини, цей додатковий крок може розглядатися як непотрібна перешкода. З іншого боку, це може бути допомогою проти необізнаних чи ледачих колег, які ведуть налагодження у виробництві.

Це рішення дозволить створювати налагодження, не турбуючись про облікові дані, але для створення версій версій знадобляться дійсні облікові дані, і для цього потрібно дуже мало котла. Однак, як і зворотний бік, це може спонукати інших замінити фіктивні значення справжніми обліковими даними, і немає ніякого способу захисту від цього.

// app/build.gradle
// Define this structure in signing.gradle to enable release builds.
ext.signing = [
        storeFilePath : 'path/to/keystore',
        storePassword : 'keystore password',
        keyAlias      : 'key alias',
        keyPassword   : 'key password',
]

if (file('signing.gradle').exists()) {
    apply from: 'signing.gradle'
}

android {
    ...
    signingConfigs {
        release {
            storeFile file(project.signing.storeFilePath)
            storePassword project.signing.storePassword
            keyAlias project.signing.keyAlias
            keyPassword project.signing.keyPassword
        }
    }
    buildTypes {
        debug { ... }
        release {
            signingConfig signingConfigs.release
            ...
        }
    }
}

Це створює фіктивну властивість, яка служить виключно для створення синтаксично допустимого файлу збірки. Значення, присвоєні ext.signingвластивостям s, не мають значення, наскільки йде збірка налагодження. Щоб включити реліз збірки, копію ext.signingв signing.gradleі замінити значення фіктивних з дійсними обліковими даними.

// signing.gradle
ext.signing = [
        storeFilePath : 'real/keystore',
        storePassword : 'real keystore password',
        keyAlias : 'real key alias',
        keyPassword : 'real key password',
]

Звичайно, signing.gradleслід ігнорувати VCS.


6

Зараз майже всі платформи пропонують певний брелок, тому немає причин залишати чіткі текстові паролі.

Я пропоную просте рішення, яке використовує модуль клавіш Python (в основному сценарій консолі супутника keyring) та мінімальний обгортку навколо ['do', 'something'].execute() функції Groovy :

def execOutput= { args ->
    def proc = args.execute()
    proc.waitFor()
    def stdout = proc.in.text
    return stdout.trim()
}

За допомогою цієї функції signingConfigsрозділ стає:

signingConfigs {
    release {
        storeFile file("android.keystore")
        storePassword execOutput(["keyring", "get", "google-play", storeFile.name])
        keyAlias "com.example.app"
        keyPassword execOutput(["keyring", "get", "google-play", keyAlias])
    }
}

Перед запуском gradle assembleReleaseвам потрібно встановити паролі у вашому брелоку лише один раз:

$ keyring set google-play android.keystore # will be prompted for the passwords
$ keyring set google-play com.example.app

Щасливі випуски!


5

Розширивши відповідь Девіда Вавра, створіть файл ~ / .gradle / gradle.properties та додайте

RELEASE_STORE_FILE=/path/to/.keystore
RELEASE_KEY_ALIAS=XXXXX
RELEASE_STORE_PASSWORD=XXXXXXXXX
RELEASE_KEY_PASSWORD=XXXXXXXXX

Потім у build.gradle

  signingConfigs {
    release {
    }
  }

  buildTypes {
    release {
      minifyEnabled true
      shrinkResources true

    }
  }

  // make this optional
  if ( project.hasProperty("RELEASE_KEY_ALIAS") ) {
    signingConfigs {
      release {
        storeFile file(RELEASE_STORE_FILE)
        storePassword RELEASE_STORE_PASSWORD
        keyAlias RELEASE_KEY_ALIAS
        keyPassword RELEASE_KEY_PASSWORD
      }
    }
    buildTypes {
      release {
        signingConfig signingConfigs.release
      }
    }
  }

5

Мені було дуже весело з'ясувати це. Ось мій прохід.

Прохід до того, як створити файл збірки gradle в IntelliJ (v.13.1.4) Цей покроковий опис передбачає, що ви знаєте, як зробити файл зберігання ключів. Щоб цей підручник працював, вам знадобиться, щоб ваш файл зберігання ключів знаходився у папці додатка, і ваш файл zipalign.exe повинен бути розташований у розділі "SDK-ROOT \ tools". Цей файл зазвичай знаходиться у "SDK-ROOT \ build-tools", і під цією папкою він знаходиться у найвищій папці api (альфа чи бета, я рекомендую альфа-версію).

Для тих із вас, хто хоче стрибнути прямо тут, є файл збірки gradle.

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.9.+'
    }
}
apply plugin: 'android'

repositories {
    mavenCentral()
}
android {
    compileSdkVersion 19
    buildToolsVersion '20.0.0'
    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    signingConfigs {
        playstore {
            keyAlias 'developers4u'
            keyPassword 'thisIsNotMyRealPassword'
            storeFile file('developers4u.keystore')
            storePassword 'realyItIsNot'
        }
    }
    buildTypes {
        assembleRelease {
            debuggable false
            jniDebugBuild false
            runProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            zipAlign true
            signingConfig signingConfigs.playstore
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:support-v4:20.0.0'
    implementation 'com.android.support:appcompat-v7:20.0.0'
}

Ви можете створити частину цього файлу збірки (вище) з меню меню: Структура файлу / проекту Звідси виберіть Фасетки та натисніть «Android-Gradle (Додаток). Звідси ви побачите вкладки: "Властивості", "Підписання", "Ароматизатори", "Типи збірки" та "Залежності" для цього проходження, ми будемо просто використовувати "Підписання" та "Типи збірки". У розділі "Типи збірки" (у розділі імен) введіть будь-яке ім'я, яке ви хочете визначити конфігурацію типу збірки, а в інші 4 поля введіть інформацію про ваше сховище ключів (встановивши шлях до магазину ключів, той, який знаходиться в папці додатка).

У розділі "Типи збірки" введіть значення "assembleRelease" у поле імені, "Debuggable" має бути встановлено на false, "Jni Debug Build" має бути хибним, встановити "Run Proguard" на true та "Zip Align" на true. Це створить файл збірки, але не так, як зображено вище, після цього вам доведеться додати кілька речей до файлу збірки. Розташування файлу ProGuard тут буде встановлено вручну у файлі збірки gradle. (як зображено вище)

Контейнери DSL, які вам доведеться потім додати, є такими:

android {
    ....
    compileSdkVersion 19
    buildToolsVersion '20.0.0'
    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    ....
}

Вам також доведеться додати:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:support-v4:20.0.0'
    implementation 'com.android.support:appcompat-v7:20.0.0'
}

Зверніть увагу, що цей контейнер DSL вище ("залежності") повинен знаходитися в нижній частині файлу конфігурації, але не всередині контейнера DSL для android. Щоб побудувати контейнер залежностей з меню IntelliJ, виберіть: Файл / Структура проекту. Звідти знову виберіть Грані, а потім Android-Gradle (додаток). Ви побачите ті самі 5 вкладок, про які було сказано вище. Перейдіть на вкладку "Залежності" та додайте потрібні залежності.

Після того, як усе це зроблено, ви побачите файл збірки Gradle, схожий на файл у верхній частині цього проходження. Щоб створити свій підписаний випуск з розширенням ZIP, вам потрібно буде відкрити завдання Gradle. Ви можете дістатися до цього вікна, вибравши Перегляд / Інструмент Windows / Gradle. Звідси ви можете подвійно натиснути «збиратиAssembleRelease». Це має створити розгорнуту APK.

Потенційні проблеми, які можуть виникнути під час компіляції випуску, є (але не обмежуються ними): Ваш файл збірки Gradle знаходиться в неправильному місці. Є два файли збірки Gradle; один у кореневій папці програми та інший у папці додатка під корінь програми. Ви повинні користуватися останнім.

Також у вас можуть виникнути проблеми з волосками. (Примітка: Android Developer Studio набагато краще виявляє проблеми з Lint, ніж IntelliJ. Ви помітите це, намагаючись створити підписаний APK з параметрів меню)

Щоб усунути проблеми з обличчям, вам потрібно буде помістити наступний контейнер DSL всередині контейнера для android (вгорі):

android {
        ....
    lintOptions {
        abortOnError false
    }
    ....
}

якщо помістити це всередину вашого DSL-контейнера, це призведе до генерування файлу помилок у папці збірки (безпосередньо під папкою вашої програми). Назва файлу має бути чимось на кшталт "lint-results-release-fatal.html", цей файл підкаже вам клас, де сталася помилка. Інший файл, який буде створений, - це XML-файл, який містить "ідентифікатор проблеми", пов'язаний з помилкою ворсу. Назва файлу має бути на зразок 'lint-results-release-fatal.xml'. Десь біля верхньої частини файлу ви побачите вузол 'issue', всередині якого ви побачите щось подібне до 'id = "IDOfYourLintProblem"'

Щоб виправити цю проблему, відкрийте файл у вашому проекті, який перелічено у файлі 'lint-results-assembleRelease-fatal.html' та введіть наступний рядок коду у файлі класу Java трохи вище імені класу: @SuppressLint ("IDOfYourLintProblem "). Можливо, вам доведеться імпортувати "android.annotation.SuppressLint;"

Отже ваш файл класу java повинен виглядати так:

package com.WarwickWestonWright.developers4u.app.CandidateArea;

import android.annotation.SuppressLint;
... other imports

@SuppressLint("IDOfYourLintProblem")
public class SearchForJobsFragment extends Fragment {... rest of your class definition}

Зауважте, що придушення помилок ворсу не завжди є найкращим IDEA, можливо, вам буде краще змінити свій код, який спричинив помилки ворсу.

Інша проблема, яка може виникнути, - це якщо ви не встановили змінну середовища для змінної середовища Gradle HOME. Ця змінна має ім'я 'GRADLE_HOME', і їй слід встановити шлях до домашнього каталогу gradle, як-от "C: \ gradle-1.12" Іноді ви також можете встановити змінну середовища для "ANDROID_HOME", встановивши це на "YOUR- SDK-корінь \ sdk '

Після цього поверніться до вікна завдань Gradle та двічі клацніть на збиранняAssembleRelease.

Якщо все успішно, ви повинні мати можливість перейти до програми папки \ build \ apk та знайти свій розгорнутий файл APK.


+1 за зусилля та: 'lintOptions {abortOnError false}'
Raz Tourgman

4

Ще один підхід до тієї ж проблеми. Оскільки не рекомендується зберігати будь-який тип облікових даних у вихідному коді, ми вирішили встановити паролі для зберігання ключів та псевдоніму ключа в окремий файл властивостей наступним чином:

key.store.password=[STORE PASSWORD]
key.alias.password=[KEY PASSWORD]

Якщо ви використовуєте git, ви можете створити текстовий файл, який називається, наприклад, secure.properties. Слід виключити його зі свого сховища (якщо ви використовуєте git, додавши його у файл .gitignore). Потім вам потрібно буде створити конфігурацію підпису, як вказують деякі інші відповіді. Різниця полягає лише в тому, як ви завантажуєте облікові дані:

android {
    ...
    signingConfigs {
        ...
        release {
            storeFile file('[PATH TO]/your_keystore_file.jks')
            keyAlias "your_key_alias"

            File propsFile = file("[PATH TO]/secure.properties");
            if (propsFile.exists()) {
                Properties props = new Properties();
                props.load(new FileInputStream(propsFile))
                storePassword props.getProperty('key.store.password')
                keyPassword props.getProperty('key.alias.password')
            }
        }
        ...
    }

    buildTypes {
        ...
        release {
            signingConfig signingConfigs.release
            runProguard true
            proguardFile file('proguard-rules.txt')
        }
        ...
    }
}

Ніколи не забудьте присвоїти типуCanfig тип збірки випуску вручну (чомусь я іноді припускаю, що він буде використаний автоматично). Крім того, не потрібно вмикати прогуар, але це рекомендується.

Нам подобається цей підхід краще, ніж використання змінних оточуючих середовищ або запит на введення користувача, оскільки це можна зробити з IDE, перейшовши на тип збірки Release і запустивши додаток, а не використовувати командний рядок.


1
Gradle не компілюється, використовуючи це: props = new Properties (); Неможливо встановити значення властивості "реквізит" лише для читання
кеш-файли

Ви маєте рацію @ m3n0R. Я відредагував рядок моєї відповіді, щоб відобразити виправлення, яке нам довелося ввести у нашому додатку, щоб воно все ще збиралося за допомогою останніх версій Gradle. В основному, реквізит повинен бути оголошений як локальна змінна.
argenkiwi

як це можна прийняти за допомогою хмарних інструментів CI / CD .... / шлях / до / зберігання ключів та /path/to/secure.props кидає мене .... спасибі за це.
sirvon

4

Android Studio Перейдіть у меню Файл -> Структура проекту або натисніть Ctrl + Alt + Shift + S

Дивіться зображення

введіть тут опис зображення

Натисніть Ок

Тоді підписConfigs буде генеруватися у вашому файлі build.gradle.

введіть тут опис зображення


І саме це ви не хочете робити. Таким чином усі ваші паролі є чіткими текстами і є частиною вашого проекту , і їх дуже легко випадково включити, навіть у розподілену збірку.
not2qubit

2

У мене було кілька питань, які я поставив у неправильному місці наступний рядок:

signingConfigs {
    release {
        // We can leave these in environment variables
        storeFile file("d:\\Fejlesztés\\******.keystore")
        keyAlias "mykey"

        // These two lines make gradle believe that the signingConfigs
        // section is complete. Without them, tasks like installRelease
        // will not be available!
        storePassword "*****"
        keyPassword "******"
    }
}

Переконайтеся, що ви розмістили частини підписуConfigs всередині розділу Android:

android
{
    ....
    signingConfigs {
        release {
          ...
        }
    }
}

замість

android
{
    ....
}

signingConfigs {
   release {
        ...
   }
}

Зробити цю помилку легко.


2

Настав 2019 рік, і мені потрібно підписати APK за допомогою V1 (підпис jar) або V2 (повний підпис APK). Я гуглив "сформувати підписані apk gradle", і це привело мене сюди. Тому я додаю тут своє оригінальне рішення.

signingConfigs {
    release {
        ...
        v1SigningEnabled true
        v2SigningEnabled true
    }
}

Моє оригінальне запитання: Як використовувати V1 (підпис Jar) або V2 (повний підпис APK) з файлу build.gradle


Не потрібно напівколонок; це дасть вам помилку.
Такеші Кага

Це правильно. Дякую. Я відредагував відповідь.
користувач1506104

1

Щоб доповнити інші відповіді, ви також можете розмістити файл gradle.properties у вашій власній папці модулів разом із build.gradle, на випадок, якщо ваш сховище ключів характерне для одного проекту.


1

я працюю в Ubuntu14.04. vim ~ / .bashrc та додай експорт ANDROID_KEYSTORE = експорт ANDROID_KEYALIAS =

а потім у наборі build.gradle.

    final Console console = System.console();
if (console != null) {

    // Building from console
    signingConfigs {
        release {
            storeFile file(System.getenv("KEYSTORE"))
            storePassword new String(System.console().readPassword("\n\$ Enter keystore password: "))
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword new String(System.console().readPassword("\n\$ Enter key password: "))
        }
    }

} else {

    // Building from IDE's "Run" button
    signingConfigs {
        release {

        }
    }

}

ІМХО , що здається найкращим рішенням, але , до жаль , він перестав працювати на новіших версіях Gradle : System.console()повертається null.
Антоніо Вініцій Менез Медей

1

Альтернативою є визначення завдання, яке працює лише на версії версій.

android {
  ...
  signingConfigs {
     release {
        // We can leave these in environment variables
        storeFile file('nameOfKeystore.keystore')
        keyAlias 'nameOfKeyAlias'

        // These two lines make gradle believe that the signingConfigs
        // section is complete. Without them, tasks like installRelease
        // will not be available!
        storePassword "notYourRealPassword"
        keyPassword "notYourRealPassword"

     }
  }
  buildTypes {
     ...
     release {
        signingConfig signingConfigs.release
        ...
     }
  }
  ...
}

task setupKeystore << {
final Console console = System.console();
if (console != null) {
    //def keyFile = console.readLine(“\nProject: “ + project.name + “Enter keystore path: "))
    //def keyAlias = console.readLine(“Project: “ + project.name + “Enter key alias: ")
        def storePw = new String(console.readPassword(“Project:  + project.name + “. Enter keystore password: "))
        def keyPw  = new String(console.readPassword(“Project: “ + project.name + “.Enter keystore password: "))

    //android.signingConfigs.release.storeFile = file(keyFile);
    //android.signingConfigs.release.keyAlias = keyAlias
        android.signingConfigs.release.storePassword = storePw
        android.signingConfigs.release.keyPassword = keyPw
}
}

//Validate t
def isReleaseConfig = gradle.startParameter.taskNames.any {it.contains('Release') }
if (isReleaseConfig) {
    setupKeystore.execute();
}

Мені здається переважнішим: stackoverflow.com/a/19130098/3664487 Як порівнюються два підходи?
користувач2768

1

Ви можете запитувати паролі з командного рядка:

...

signingConfigs {
  if (gradle.startParameter.taskNames.any {it.contains('Release') }) {
    release {
      storeFile file("your.keystore")
      storePassword new String(System.console().readPassword("\n\$ Enter keystore password: "))
      keyAlias "key-alias"
      keyPassword new String(System.console().readPassword("\n\$ Enter keys password: "))
    } 
  } else {
    //Here be dragons: unreachable else-branch forces Gradle to create
    //install...Release tasks.
    release {
      keyAlias 'dummy'
      keyPassword 'dummy'
      storeFile file('dummy')
      storePassword 'dummy'
    } 
  }
}

...

buildTypes {
  release {

    ...

    signingConfig signingConfigs.release
  }

  ...
}

...

Цей if-then-elseблок запобігає запитам паролів під час створення релізу. Хоча elseгілка недоступна, вона підманює Градле створити install...Releaseзавдання.

Попередня історія . Як зазначається на https://stackoverflow.com/a/19130098/3664487 , " сценарії Gradle можуть запросити для введення користувачем, використовуючи метод System.console (). ReadLine ." На жаль, Gradle завжди запитуватиме пароль, навіть коли ви будуєте випуск налагодження (див. Як створити apk-файл, підписаний релізом, за допомогою Gradle? ). На щастя, це можна подолати, як я показав вище.


Моя раніше відповідь зіткнулася з проблемами через stackoverflow.com/questions/33897802/… . Я переглянув свою відповідь, щоб усунути цю проблему.
користувач2768

@Haroon, він працював станом на 24 листопада '15. Спільнота може допомогти у вирішенні вашої проблеми, але вам потрібно надати більше деталей.
користувач2768

Мені подобається це рішення, оскільки воно уникає введення пароля чистим текстом у текстовий файл, але System.console (). ReadLine не працює в gradle через цю набридливу проблему.
морфей

@morpheus, у мене ніколи не було проблем. Сказане працює для мене.
користувач2768

Я думаю, що ви запускаєте скрипт із IDE. якщо сценарій запускається з терміналу, ви побачите помилку. але дякую за цю відповідь. це те, що я шукав.
морфей

0

Додаю спосіб зробити це в React-Native, використовуючи пакет react-native-config .
Створіть .env файл:

RELEASE_STORE_PASSWORD=[YOUR_PASSWORD]
RELEASE_KEY_PASSWORD=[YOUR_PASSWORD]

Зауважте, це не повинно бути частиною контролю версій.

у вашому build.gradle:

signingConfigs {
        debug {
            ...
        }
        release {
            storeFile file(RELEASE_STORE_FILE)
            storePassword project.env.get('RELEASE_STORE_PASSWORD')
            keyAlias RELEASE_KEY_ALIAS
            keyPassword project.env.get('RELEASE_KEY_PASSWORD')
        }
    }

0

У моєму випадку я завантажував неправильний apk, до випуску іншого додатка.


0

Для Groovy (build.gradle)

Не слід ставити свої підписні дані безпосередньо у файл build.gradle . Натомість облікові дані мають надходити з файлу, який не знаходиться під контролем версій.

Помістіть файл sign.properties, де знайдено конкретний build.gradle для модуля . Не забудьте додати його у свій .gitignore файл!

підписання.властивості

storeFilePath=/home/willi/example.keystore
storePassword=secret
keyPassword=secret
keyAlias=myReleaseSigningKey

build.gradle

android {
    // ...
    signingConfigs{
        release {
            def props = new Properties()

            def fileInputStream = new FileInputStream(file('../signing.properties'))
            props.load(fileInputStream)
            fileInputStream.close()

            storeFile = file(props['storeFilePath'])
            storePassword = props['storePassword']
            keyAlias = props['keyAlias']
            keyPassword = props['keyPassword']
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
            // ...
        }
    }
}

0

Для сценарію Котліна (build.gradle.kts)

Не слід ставити свої підписні дані безпосередньо у файл build.gradle.kts . Натомість облікові дані мають надходити з файлу, який не знаходиться під контролем версій.

Помістіть файл sign.properties, де знайдений конкретний модуль build.gradle.kts . Не забудьте додати його у свій .gitignore файл!

підписання.властивості

storeFilePath=/home/willi/example.keystore
storePassword=secret
keyPassword=secret
keyAlias=myReleaseSigningKey

build.gradle.kts

android {
    // ...
    signingConfigs {
        create("release") {
            val properties = Properties().apply {
                load(File("signing.properties").reader())
            }
            storeFile = File(properties.getProperty("storeFilePath"))
            storePassword = properties.getProperty("storePassword")
            keyPassword = properties.getProperty("keyPassword")
            keyAlias = "release"
        }
    }

    buildTypes {
        getByName("release") {
            signingConfig = signingConfigs.getByName("release")
            // ...
        }
    }
}

-1

якщо ви не хочете бачити метод Неможливо викликати метод readLine () на об’єкті null. Вам потрібно спочатку написати в gradle.properties .

KEYSTORE_PASS=*****
ALIAS_NAME=*****
ALIAS_PASS=*****
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.