React Native生成已签名的APK" KeyStore文件未设置为签署配置版本"

时间:2017-06-05 08:57:48

标签: gradle react-native android-gradle build.gradle gradlew

我正在尝试生成已签名的APK。我的密码.keystore文件位于\ Dictionary \ android \ app中,当我在cmd上运行gradlew assembleRelease时,错误:

任务执行失败':app:validateSigningRelease'。

未设置签名配置版本的密钥库文件

我应该在哪里存储我的password.keystore文件?因为当我评论if (project.hasProperty("password.keystore") {它似乎工作但是反而出现以下错误:

无法处理传入的事件' ProgressComplete' (ProgressCompleteEvent)

我应该如何编写if条件或应该在哪里存储password.keystore文件?

源代码如下:

signingConfigs {
  release {
    if (project.hasProperty("password.keystore")) {
      storeFile file("password.keystore")
      storePassword "password"
      keyAlias "username"
      keyPassword "password"
    }
  }
}

12 个答案:

答案 0 :(得分:16)

密钥库文件必须位于 android / app 文件夹中。

消息'未设置签名配置版本的密钥库文件'必须这样做,android / app / build.gradle文件中没有signedConfig。

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

对于测试,你可以硬编码android / app / build.gradle中的设置,而不是在gradle.properties中设置它。这给我解决了'Keystore被篡改或密码错误的问题'

  signingConfigs {
    release {
        //if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
            storeFile file("key.keystore")
            storePassword "****"
            keyAlias "myKey"
            keyPassword "****"
       // }
    }
}

答案 1 :(得分:4)

我找到了解决方法!

如果您像我一样跟随React Native's official instructions,则将关注添加到gradle.properties

MYAPP_RELEASE_STORE_FILE=<your-app>.keystore
MYAPP_RELEASE_KEY_ALIAS=<keystore-alias>
MYAPP_RELEASE_STORE_PASSWORD=<password>
MYAPP_RELEASE_KEY_PASSWORD=<password>

然后是我完全误会的部分。

app/build.gradle文件中,应该替换字符串。如果您的gradle.properties与我粘贴的app/build.gradle类似,则您的signingConfigs { release { if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) { storeFile file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD } } } 应该如下所示:

gradle.properties

我最初所做的是替换字符串(即'MYAPP_RELEASE_STORE_FILE'与我的密钥库文件的路径),但是应该完全替换任何变量。我想您可能会看到我们在app/build.gradle中创建的字符串与我们在.keystore中创建的release-config之间的联系。

请记住,您的android/app文件也应放在const path = require('path'); const precss = require('precss'); const webpack = require('webpack'); const packageJson = require('./package.json'); const autoprefixer = require('autoprefixer'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const HtmlWebPackPlugin = require('html-webpack-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const filenames = { css: '[name].bundle.css', js: '[name].bundle.js', }; console.log('#########################################'); /* Cache busted names for production */ if (process.env.NODE_ENV === 'production') { console.log('# XXXXXX v', packageJson.version, ' PRODUCTION #'); const timestamp = +new Date(); filenames.css = `[name].bundle.${timestamp}.css`; filenames.js = `[name].bundle.${timestamp}.js`; } else { console.log('# XXXXXX v', packageJson.version, ' DEVELOPMENT #'); } console.log('#########################################'); console.log(''); module.exports = (env, options) => ({ entry: './src/assets/js/Scheduler.jsx', output: { publicPath: '/', filename: `assets/js/${filenames.js}`, path: path.resolve(__dirname, 'public'), }, watchOptions: { ignored: /node_modules/, }, node: { fs: 'empty', }, devtool: (options.mode === 'production') ? 'source-map' : 'cheap-module-source-map', devServer: { hot: true, watchContentBase: true, historyApiFallback: true, contentBase: path.join(__dirname, 'src'), }, module: { rules: [{ test: /\.(js|jsx)$/, exclude: /node_modules|bower_components/, use: [ 'babel-loader', 'eslint-loader', ], }, { test: /\.(css)$/, exclude: /node_modules|bower_components/, use: [ MiniCssExtractPlugin.loader, { /* Interprets `@import` and `url()` like `import/require()` and will resolve them */ loader: 'css-loader', options: { sourceMap: true, }, }, ], }, { test: /\.(scss)$/, exclude: /node_modules|bower_components/, use: [ { loader: 'css-hot-loader', options: { sourceMap: true, }, }, /** * Commented out as we want to extract the styles into a seperate file which the mini CSS extract plugin will do. * If you want to keep the styles within the scripts, comment this back in and comment out mini CSS extract plugin line below. */ /* { loader: 'style-loader', options: { sourceMap: true, }, }, */ MiniCssExtractPlugin.loader, { /* Interprets `@import` and `url()` like `import/require()` and will resolve them */ loader: 'css-loader', options: { sourceMap: true, }, }, { /* Loader for webpack to process CSS with PostCSS */ loader: 'postcss-loader', options: { autoprefixer: { browsers: ['last 3 versions'], }, plugins: loader => [ precss(), autoprefixer(), ], sourceMap: true, }, }, { /* Loads a SASS/SCSS file and compiles it to CSS */ loader: 'sass-loader', options: { sourceMap: true, }, }, ], }, { test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/, exclude: /node_modules|bower_components/, use: 'url-loader?limit=10000', }, { test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/, exclude: /node_modules|bower_components/, use: 'file-loader', }, { test: /\.(png|jp(e*)g|svg|gif)$/, exclude: /node_modules|bower_components/, use: [{ loader: 'url-loader', options: { limit: 8000, /* Convert images < 8kb to base64 strings */ name: 'assets/img/[name]-[hash].[ext]', }, }], }, { test: /\.html$/, exclude: /node_modules|bower_components/, use: { loader: 'html-loader', options: { minimize: true, }, }, }, { test: /bootstrap\/dist\/js\/umd\//, use: 'imports-loader?jQuery=jquery', }], }, resolve: { extensions: ['*', '.jsx', '.js', '.scss', '.css', '.html'], }, performance: { hints: false, }, optimization: { runtimeChunk: 'single', splitChunks: { cacheGroups: { commons: { name: 'vendors', chunks: 'initial', test: /node_modules/, }, }, }, minimizer: [ new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true, }), new OptimizeCSSAssetsPlugin(), ], }, plugins: [ new MiniCssExtractPlugin({ filename: `assets/css/${filenames.css}`, }), new HtmlWebPackPlugin({ template: 'src/index.html', filename: 'index.html', hash: (options.mode === 'production'), }), new HtmlWebPackPlugin({ template: 'src/404.html', filename: '404.html', hash: (options.mode === 'production'), }), new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery', }), new webpack.HashedModuleIdsPlugin(), new CopyWebpackPlugin([ { force: true, cache: true, to: 'assets/icons', from: 'src/assets/icons', }, { force: true, cache: true, to: 'assets/img', from: 'src/assets/img', }, { force: true, cache: true, to: 'assets/fonts', from: 'src/assets/fonts', }, { force: true, cache: true, to: 'assets/fonts', from: 'node_modules/font-awesome/fonts', }, ]), ], }); 中。

答案 2 :(得分:3)

我有完全相同的问题。结果我忘了编辑gradle.properties文件。它应该是这样的:

android.useDeprecatedNdk=true

MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias

答案 3 :(得分:3)

就我而言,我的项目使用的是RN版本0.59,而我使用的是0.60 RC文档。所以在app/build.gradle

如果版本为0.59:

if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {

如果版本为0.60:

if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {

区别是从RELEASEUPLOAD

答案 4 :(得分:1)

project.hasProperty将在gradle.properties文件中查找名为password.keystore的变量。

进入~/.gradle并查看您是否有gradle.properties文件,如果有,请确保变量password.keystore在那里,它应指向您的密钥库文件:{{1 }}

虽然您应该将其命名为不同的内容,例如password.keystore=password.keystore。然后当你运行MYAPP_RELEASE_STORE_FILE=password.keystore时,你的项目将拥有它正在寻找的属性,以下将解析为true并允许gradlew设置所有的signedConfigs.release属性:

./gradlew assembleRelease

答案 5 :(得分:1)

在探索了有关此问题的所有答案之后,答案都没有帮助!

在下面的实验中试过,它有助于!!!!

my-release-key.keystore文件放在项目文件夹中的 android 目录下。

答案 6 :(得分:1)

我实际上更喜欢使用环境变量将这些参数存储在app repo之外,因为它包含密码等敏感信息。

signingConfigs {
    release {
        if (System.env.MYAPP_RELEASE_STORE_FILE != null) {
            storeFile       file(System.env.MYAPP_RELEASE_STORE_FILE)
            storePassword   System.env.MYAPP_RELEASE_STORE_PASSWORD
            keyAlias        System.env.MYAPP_RELEASE_KEY_ALIAS
            keyPassword     System.env.MYAPP_RELEASE_KEY_PASSWORD
        }
    }
}

完成后,我可以加载一个bash脚本,其中包含

等详细信息
# path to my keystore
export MYAPP_RELEASE_STORE_FILE=/path/to/key.file
# ...

这样签名配置与repo完全隔离。这可以防止您对自己的秘密进行意外提交。

答案 7 :(得分:1)

使用./gradlew bundleRelease比./gradlew assembleRelease

答案 8 :(得分:0)

确保已将 .keystore 文件放在app文件夹中,并进行如下所示的gradle更改:

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

答案 9 :(得分:0)

确保gradle.properties中使用的别名与创建keystore(使用keytool)时使用的别名相同

答案 10 :(得分:0)

我放置在android / gradle.properties中的gradle.properties文件对我有用,看起来像最新的react .gradle / gradle.properties文件,如果我们将其放置在未从其选择的位置。

答案 11 :(得分:0)

在我的gradle.properties文件中,就像

MYAPP_RELEASE_STORE_FILE=<your-app>.keystore
MYAPP_RELEASE_KEY_ALIAS=<keystore-alias>
MYAPP_RELEASE_STORE_PASSWORD=<password>
MYAPP_RELEASE_KEY_PASSWORD=<password>

以及我的build.gradle文件

release {
            if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
                storeFile file(MYAPP_UPLOAD_STORE_FILE)
                storePassword MYAPP_UPLOAD_STORE_PASSWORD
                keyAlias MYAPP_UPLOAD_KEY_ALIAS
                keyPassword MYAPP_UPLOAD_KEY_PASSWORD
            }
        }

我在gradle.properties中使用了 RELEASE ,而不是 UPLOAD 。只是在gradle.properties中将 RELEASE 更改为 UPLOAD ,问题就解决了。