我们使用Android Studio 运行我们的app,无非两种模式:debug和release模式。
debug模式使用一个默认的debug.keystore进行签名。
这个默认签名(keystore)是不需要密码的,它的默认位置在C:\Users\<用户名>\.Android\debug.keystore,如果不存在Android studio会自动创建它。
例如我的debug.keystore就在C:\Users\Administrator\.android\debug.keystore。
在我们正式发布项目的时候是不能使用debug.keystore的。开发过程中我们也可以使用发布模式运行。可以通过如下设置:
BuildVariants-Build Variant-debug/release
如果项目需要细分开发dev和生产pro版本,每个版本中都包含debug和release模式,可以这么设置:
就细分成四种模式:
release模式需要配置签名才能运行,这时就需要一个keystore
如果没有就需要创建,已经创建过keystore请跳过此步骤
第一步: Build --->> Generate Signed APK
第二步:Create New···(已经创建过keystore选Choose existing···)
第三步:填写相关信息
设置keystore路径、密码,设置key:别名、密码、有效期,证书等
Key store path:存放路径
Key
Alias:别名
Validity(years):有效期(一般默认25年)
Certificate:证书
First and Last Name:姓名
Organization Unit:组织单位
Organization:组织
City or Locality:城市或地区
State or Province:州或省
Country Code(XX):国家代码(XX),中国:86
第四步:输入key、keystore密码
第五步:选择发布app的路径,默认即可 选择release方式发布,V1必须勾选!!
OK,发布成功,可以到 刚才设置的目标文件夹下面找到发布的apk
那对一些人来说,这样也太麻烦了,每次都得输入相关信息,还得进行选择,那么有更简单快捷的方法吗?答案是有的。
我们可以在项目的app目录下的build.gradle中进行签名的配置。
2.release模式配置keystore
Project structure-signing,输入已创建的keystore信息
使得签名生效需配置Build Types
点击OK即可,然后查看对应build.gradle的配置文件应该是这样的。当然了,你也可以通过直接在build.gradle里面写下面这段。
signingConfigs {
release {
keyAlias 'androiddebugkey'
keyPassword 'android'
storeFile file('C:/Users/ssc/.android/debug.keystore')
storePassword 'android'
}
}
·········
buildTypes {
release {
//是否混淆
minifyEnabled true
//是否移除无用资源
zipAlignEnabled true
//混淆的配置文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
上述的配置虽然配置简单,但是存在不安全性,假如你的项目是开源的,你把签名文件的配置密码之类的信息用明文写在build.gradle里面,那是不是很不安全呢?
可以将签名文件的配置密码之类的信息直接写在local.properties下,因为在Git版本控制的项目中,我们可以看到我们项目project模式根目录下有一个.gitignore的文件,里面的配置大概如下所示
我们可以看到/local.properties,意思就是说local.properties默认是不添加到版本控制里面的,因为local.properties存储的是我们环境资源的一些相关信息,如sdk的路径。故我们可以在local.properties下配置签名信息而不用担心密钥外泄。对于开源项目来说,是非常好的。
在local.properties下直接添加相关信息
在build.gradle里,为了不用明文显示,我们首先要获得key的相关配置,所以我们可以在app的build.gradle里
android {}之上新增代码
def keystoreFilepath = ''
def keystorePSW = ''
def keystoreAlias = ''
def keystoreAliasPSW = ''
// default keystore file, PLZ config file path in local.properties
def keyfile = file('s.keystore.temp')
Properties properties = new Properties()
// local.properties file in the root director
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)
}
app/build.gradle下的signingConfigs可以改为:
1 2 3 4 5 6 7 8 |
|
设置后Signing中keystore值无需关心
相应的,buildTypes也可以配置成这样
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// signingConfig signingConfigs.release
//签名文件存在,则签名
if (keyfile.exists()) {
println("WITH -> buildTypes -> release: using jks key")
signingConfig signingConfigs.release
} else {
println("WITH -> buildTypes -> release: using default key")
}
23 }
}
到此,前面配置完成。
部分内容转载自:http://www.cnblogs.com/details-666/p/keystore.html并进行更新。
附:查询keystore的相关信息,如查看sha1的值;可以在运行窗口,定位到keystore所在的路径,执行cd C:\Users\ssc\.android
执行这条语句后就能显示Key的所有信息(以android默认keystore为例)
keytool -list -v -keystore xxx.jks
Android studio(windows平台上)更新到2.3版本以后,在没有充分了解它的新变化的情况下,使用的时候难免会遇到一些问题,比如gradle的问题可能是大家最常见的,不过解决的一般思路和之前(例如2.1更新到2.2之类的)没太大区别,本文要说不是gradle的问题,而是给apk正式签名后安装失败的问题。
附录:
签名打包遇到问题
1.
项目在正式上线之前一般都要有正式签名,也就是发布release版本的apk,而不再使用默认的debug版签名文件----debug.keystore。最常用的方式就是通过Android studio的工具栏里的Build-->Generate Signed APK...方式去签名。更多的步骤不再赘述,按照提示一步步的往下走就可以,相信大家都知道了。
这种方式签名后的apk就是发布版(release)的apk,android studio2.3之前是可以直接安装到设备上的,安装方式之一就是在docs命令行里用adb install
就如画圈的地方,2.3以前应该是没有的(印象中是没有,如果有的话是我记错了,见谅),多了这些选项的话不选择是无法继续下去的,选择的话,我当时看到V2和apk有关,V1和jar有关,在没有弄明白区别的时候果断选择V2的方式,然后点击了Finish.等了一会,apk打包好了,我用adb install命令安装这个apk的时候却遇到这样的问题:
对,就是说没有签名证书!但是我确实是签了名了啊,而且相应的.jks文件也是存在的。我通过手动编辑gradle文件进行签名的话再安装也是OK的。于是我clean,rebuild,新建项目,重启studio...各种方式都试了,然后通过这种方式签名打包后的apk仍然存在这个问题。于是只能上网找答案,然后就发现了问题确实是在上述画圈的地方:把V1单独勾选或者V1和V2都勾选的话,再打包就是OK的,也就是说只要勾选了V1就行,生成的apk就可以正常安装...晕。
2.升级完Android Studio2.3后,打包release出现的错误
Error:Execution failed for task ':qq:lintVitalRelease'.
> Lint found fatal errors while assembling a release target.
To proceed, either fix the issues identified by lint, or modify your build script as follows:
...
android {
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
}
...
解决方法:
在app的build.gradle中添加如下代码,重新Generate Signed APK即可
android{
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
build.gradle文件:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
混淆文件proguard-rules.pro:
-optimizationpasses 7 #指定代码的压缩级别 0 - 7
-dontusemixedcaseclassnames #是否使用大小写混合
-dontskipnonpubliclibraryclasses #如果应用程序引入的有jar包,并且想混淆jar包里面的class
-dontpreverify #混淆时是否做预校验(可去掉加快混淆速度)
-verbose #混淆时是否记录日志(混淆后生产映射文件 map 类名 -> 转化后类名的映射
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #淆采用的算法
-ignorewarnings #屏蔽警告
-keep public class * extends android.app.Activity #所有activity的子类不要去混淆
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService #指定具体类不要去混淆
-keepclasseswithmembernames class * {
native ; #保持 native 的方法不去混淆
}
-keepclasseswithmembers class * {
public (android.content.Context, android.util.AttributeSet); #保持自定义控件类不被混淆,指定格式的构造方法不去混淆
}
-keepclasseswithmembers class * {
public (android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View); #保持指定规则的方法不被混淆(Android layout 布局文件中为控件配置的onClick方法不能混淆)
}
-keep public class * extends android.view.View { #保持自定义控件指定规则的方法不被混淆
public (android.content.Context);
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclassmembers enum * { #保持枚举 enum 不被混淆
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable { #保持 Parcelable 不被混淆(aidl文件不能去混淆)
public static final android.os.Parcelable$Creator *;
}
-keepnames class * implements java.io.Serializable #需要序列化和反序列化的类不能被混淆(注:Java反射用到的类也不能被混淆)
-keepclassmembers class * implements java.io.Serializable { #保护实现接口Serializable的类中,指定规则的类成员不被混淆
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient ;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keepattributes Signature #过滤泛型(不写可能会出现类型转换错误,一般情况把这个加上就是了)
-keepattributes *Annotation* #假如项目中有用到注解,应加入这行配置
-keep class **.R$* { *; } #保持R文件不被混淆,否则,你的反射是获取不到资源id的
-keep class **.Webview2JsInterface { *; } #保护WebView对HTML页面的API不被混淆
-keepclassmembers class * extends android.webkit.WebViewClient { #如果你的项目中用到了webview的复杂操作 ,最好加入
public void *(android.webkit.WebView,java.lang.String,android.graphics.Bitmap);
public boolean *(android.webkit.WebView,java.lang.String);
}
-keepclassmembers class * extends android.webkit.WebChromeClient { #如果你的项目中用到了webview的复杂操作 ,最好加入
public void *(android.webkit.WebView,java.lang.String);
}
#对WebView的简单说明下:经过实战检验,做腾讯QQ登录,如果引用他们提供的jar,若不加防止WebChromeClient混淆的代码,oauth认证无法回调,反编译基代码后可看到他们有用到WebChromeClient,加入此代码即可。
-keepclassmembernames class com.cgv.cn.movie.common.bean.** { *; } #转换JSON的JavaBean,类成员名称保护,使其不被混淆
##################################################################
# 下面都是项目中引入的第三方 jar 包。第三方 jar 包中的代码不是我们的目标和关心的对象,故而对此我们全部忽略不进行混淆。
##################################################################
#-libraryjars /libs/android-support-v4.jar
-dontwarn android.support.v4.**
-keep class android.support.v4.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment
#-libraryjars /libs/pdf.jar
-dontwarn com.neusoft.android.pdf.**
-dontwarn com.example.pdfactivity04.**
-keep class com.neusoft.android.pdf.** { *;}
-keep class com.example.pdfactivity04.** { *;}
-dontwarn com.itextpdf.**
-dontwarn org.apache.**
-keep class com.itextpdf.**{*;}
-keep class org.apache.**{*;}
-dontwarn com.google.**
-keep class com.google.**{*;}
-dontwarn com.tencent.**
-keep class com.tencent.**{*;}
-dontwarn com.lidroid.**
-keep class com.lidroid.**{*;}
-keep class com.duicky.TestProvider{*;}
#-dontwarn com.ui.**
#-keep class com.ui.**{*;}
#-dontwarn com.turui.**
#-keep class com.turui.**{*;}
#-dontwarn com.idcard.**
#-keep class com.idcard.**{*;}
-dontwarn com.i2trust.**
-keep class com.i2trust.**{*;}
-dontwarn com.hisign.**
-keep class com.hisign.**{*;}
-dontwarn com.ccit.**
-keep class com.ccit.**{*;}
-dontwarn com.plk.bluetoothlesdk.**
-keep class com.plk.bluetoothlesdk.**{*;}
-dontwarn org.kobjects.**
-keep class org.kobjects.**{*;}
-dontwarn org.ksoap2.**
-keep class org.ksoap2.**{*;}
-dontwarn org.kxml2.**
-keep class org.kxml2.**{*;}
-dontwarn org.xmlpull.**
-keep class org.xmlpull.**{*;}
-dontwarn org.nanohttpd.**
-keep class org.nanohttpd.**{*;}
-dontwarn com.sensetime.senseid.sdk.**
-keep class com.sensetime.senseid.sdk.**{*;}
#-libraryjars /libs/commons-codec-1.3.jar
#-libraryjars /libs/commons-httpclient-3.1.jar
#-libraryjars /libs/commons-logging-1.1.jar
#-libraryjars /libs/zxing.jar
#-libraryjars /libs/httpclient-4.3.6.jar
#-libraryjars /libs/httpcore-4.3.2.jar
#-libraryjars /libs/httpmime-4.3.5.jar
#-libraryjars /libs/itextpdf.jar
#-libraryjars /libs/libammsdk.jar
#-libraryjars /libs/xUtils-2.6.14.jar
#-libraryjars /libs/livedetectCTID.jar
#-libraryjars /libs/i2trustauthensdk.jar
#-libraryjars /libs/plkbluetoothlesdk.jar
#-libraryjars /libs/ldap.jar
#-libraryjars /libs/ksoap2-android-assembly-3.6.0-jar-with-dependencies.jar
#-libraryjars /libs/MKeySDK.jar