生成正式签名的 APK 文件
之前我们一直都是通过 Eclipse 来将程序安装到手机上的,而它背后实际的工作流程是,
Eclipse 会将程序代码打包成一个 APK 文件,然后将这个文件传输到手机上,最后再执行安
装操作。Android 系统会将所有的 APK 文件识别为应用程序的安装包,类似于 Windows 系
统上的 EXE 文件。
但并不是所有的 APK 文件都能成功安装到手机上的,Android 系统要求只有签名后的
APK 文件才可以安装,因此我们还需要对生成的 APK 文件进行签名才行。那么你可能会有
疑问了,直接通过 Eclipse 来运行程序的时候好像并没有进行过签名操作啊,为什么还能将
程序安装到手机上呢?这是因为 Eclipse 使用了一个默认的 keystore 文件帮我们自动进行了
签名,点击 Eclipse 导航栏的 Window→Preferences→Android→Build 可以查看到这个默认
keystore 文件的位置
如何生成一个带有正式签名的APK文件?
1.首先右击 你的app项目→Android Tools→Export Signed Application Package
2.如果没有创建ketstore就创建
3.指定 .keystore文件的保存路径和输入密码,确定密码
4.这时会要求输入一系列创建 keystore 文件所必要的信息(在 Validity 那一栏填写的是 keystore 文件的有效时长,单位是年)
5. 点keystore文件保存的路径
以 后 再 给 这个软件 打 包 的 时 候 就 不 用 创 建 新 的 keystore 文 件 了 , 只 需 要 选 择
已经创建的.keystore 文件,并输入正确的密码即可。
在我们的Android系统中,不许可安装两个相同的包的应用;
当包名相同的时候,如果签名相同,替换安装成功。如果签名不相同,安装失败;
如果你的签名丢了怎么办;
包名不变的情况下
1.改签名(有密码);无法替换安装,相当于安装了两个一样的程序
2.该包名 ,重新签名;
安装后写一个功能把之前的卸载
1.不同电脑默认生成的秘钥不同(不同秘钥,不能覆盖)
2.低版本不能直接覆盖高本版(但是手动去点击一个低版本安装,可以覆高本版)
来源:http://www.cnblogs.com/gao-chun/p/4891275.html
签名打包的两种方式:
注:给我们自己开发的app签名,就代表着我自己的版权,以后要进行升级,也必须要使用相同的签名才行。签名就代表着自己的身份(即keystore),多个app可以使用同一个签名。
如果不知道签名是啥意思,请自行百度哦。在eclipse中签名的方法是:选中工程,邮件选择"export-android-export android application",
1、方式1:通过Android Studio进行签名:
选中app这个module,选择菜单栏"Build-Generate signed apk":
弹出如下界面:
上图中,如果你是第一次使用签名,就单击红框部分创建一个新的签名;如果你之前有过签名的文件,就选择蓝框部分进行导入即可。那我就先选择红框部分吧:
输入一些国家,省份,城市 组织别名(alias)啥的
上图中,点击"finish"之后,可以看到Android Studio的最下方显示:Gradle正在执行assembleRelease这样一个任务,如下图所示:
生成签名好的apk之后,会弹出提示:
2、方式2:通过命令行的方式进行签名:
(1)加载Key Store:
我们先删掉上面的通过第一种方式所签名的apk文件。接下来进行第二种方式来签名,即命令行的方式。
打开Project Stucture图形化界面:
上图,选中app这个module,然后切换到singning标签栏,紧接着点击添加,然后生成release签名信息,紧接着点击"OK"。接着做如下操作:
上图中,切换到Build Types标签,将Signing config选择为"release",即将刚刚生成的release签名信息配置进去。
操作完成之后,我们可以看到app这个module的build.gradle文件多出了如下红框部分的代码:
然后执行菜单栏的"build-clean Project":
(2)生成realease版本的apk:
紧接着在命令行Terminal输入如下命令:(AS已经将命令行Terminal集成到了软件当中)
gradlew assembleRelease
如果运行成功,效果如下:
生成的签名好的apk在如下位置:
3、为什么要使用gradlew命令而不是gradle命令:
在HelloWorld工程目录下有一个gradle文件夹,在gradle/wrapper目录下有一个gradle-wrapper.properties文件,打开它:
上图代表着HelloWorld这个工程所依赖的gradle的版本信息。上图的红线表示,如果我们的工程中没有gradle,软件
签名信息的配置(安全):
1.将签名信息配置在local.properties文件下,因为该文件是不会添加到git的
# 签名配置 keystore.path=F\:\\tangsheng_work\\ts_signconfig.jks keystore.password=123456 keystore.alias=真给力 keystore.alias_password=123456
2.在app的build.gradle文件下添加配置信息
apply plugin: 'com.android.application' //******************************签名配置相关*********************************************** def keystoreFilepath = '' def keystorePSW = '' def keystoreAlias = '' def keystoreAliasPSW = '' // 默认的keystore文件,PLZ配置文件路径在local.properties def keyfile = file('s.keystore.temp') Properties properties = new Properties() // local.properties 文件的值 properties.load(project.rootProject.file('local.properties').newDataInputStream()) keystoreFilepath = properties.getProperty("keystore.path") if (keystoreFilepath) { keystorePSW = properties.getProperty("keystore.password") keystoreAlias = properties.getProperty("keystore.alias") keystoreAliasPSW = properties.getProperty("keystore.alias_password") keyfile = file(keystoreFilepath) //测试打印 keystoreAlias 编码有问题时可转换: new String(keystoreAlias.getBytes("ISO8859-1"),"GBK") println("别名keystoreAlias=" + new String(keystoreAlias.getBytes("ISO8859-1"),"UTF-8")) println("密码keystoreAliasPSW=" + keystoreAliasPSW) println("签名路径keyfile=" + keyfile) } //***************************************************************************************** android { compileSdkVersion 25 buildToolsVersion "25.0.3" defaultConfig { applicationId "com.qsgk.gelivable" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true } //配置签名 signingConfigs { /*myConfig { storeFile file('F:/tangsheng_work/ts_signconfig.jks') storePassword '123456' keyAlias '真给力' keyPassword '123456' println("====== signingConfigs.release ======") }*/ myConfig { storeFile keyfile storePassword keystorePSW keyAlias keystoreAlias keyPassword keystoreAliasPSW println("====== signingConfigs.release ======") } } buildTypes { debug { buildConfigField "boolean", "LOG_DEBUG", "true" buildConfigField("String", "BASE_URL", "\"http://appapi.yitkeji.com/\"") buildConfigField("String", "BASE_PICTURE_URL", "\"https://shch.shchnet.com/app/fileDownload\"") buildConfigField("String", "EXTENTION", "\".do\"") if (keyfile.exists()) { //如果签名文件存在 就签名 println("debug存在配置的签名文件") signingConfig signingConfigs.myConfig }else { println("debug不存在签名文件,使用默认的签名") } } release { buildConfigField "boolean", "LOG_DEBUG", "false" buildConfigField("String", "BASE_URL", "\"http://appapi.yitkeji.com/ \"") buildConfigField("String", "BASE_PICTURE_URL", "\"https://shch.shchnet.com/app/fileDownload\"") buildConfigField("String", "EXTENTION", "\".do\"") minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' if (keyfile.exists()) { //如果签名文件存在 就签名 println("release存在配置的签名文件") signingConfig signingConfigs.myConfig }else { println("release不存在签名文件,使用默认的签名") } //改变输出的apk名称 applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { // 输出apk名称为:真给力_v1.0_wandoujia.apk //def fileName = "真给力_v${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk" def fileName = "真给力_v${defaultConfig.versionName}.apk" output.outputFile = new File(outputFile.parent, fileName) } } } } } configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> def requested = details.requested if (requested.group == 'com.android.support') { if (!requested.name.startsWith("multidex")) { details.useVersion '25.3.1' } } } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:design:25.3.1' compile 'com.android.support:support-v4:25.3.1' compile 'com.android.support.constraint:constraint-layout:1.0.2' testCompile 'junit:junit:4.12' }
编译时可以看到日志如下:
由于编码问题,编译也许你会碰到下面的错误:别名输出为“????” ,所以别名最好还是用字母,不要用汉子
3.将签名文件的路径和别名密码放在gradle.properties文件中(这样别人反编译后也看不到我的密码别名信息)
1.gradle.properties添加内容
PATH=./keystore.jks
STORE_PASSWORD=123456
ALIAS=alias
ALIAS_PASSWORD=2399213
2.在build.gradle(Module:app)文件中使用
signingConfigs{
sign_name{
storeFile file(PATH)
storePassword STORE_PASSWORD
keyAlias ALIAS
keyPassword ALIAS_PASSWORD
}
}