Android StudioV3.2.1的两种模式及签名配置、apk打包混淆

我们使用Android Studio 运行我们的app,无非两种模式:debug和release模式。

debug模式

debug模式使用一个默认的debug.keystore进行签名。

这个默认签名(keystore)是不需要密码的,它的默认位置在C:\Users\<用户名>\.Android\debug.keystore,如果不存在Android studio会自动创建它。

例如我的debug.keystore就在C:\Users\Administrator\.android\debug.keystore。

release模式

在我们正式发布项目的时候是不能使用debug.keystore的。开发过程中我们也可以使用发布模式运行。可以通过如下设置:

BuildVariants-Build Variant-debug/release

如果项目需要细分开发dev和生产pro版本,每个版本中都包含debug和release模式,可以这么设置:

就细分成四种模式:

release模式需要配置签名才能运行,这时就需要一个keystore

如果没有就需要创建,已经创建过keystore请跳过此步骤

1.创建keystore,并生成我们的apk(打包)

 第一步: 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

signingConfigs {

       release {

           keyAlias keystoreAlias

           keyPassword keystoreAliasPSW

           storeFile keyfile

           storePassword keystorePSW

       }

   }

  

设置后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 <apk绝对路径>命令去安装到连接到PC上的Android设备。但是,Android studio2.3以后这种方式打包apk的话就有了些变化:

就如画圈的地方,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 <methods>;  #保持 native 的方法不去混淆
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);  #保持自定义控件类不被混淆,指定格式的构造方法不去混淆
}

-keepclasseswithmembers class * {
    public <init>(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 <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(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 <fields>;
    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



猜你喜欢

转载自blog.csdn.net/P876643136/article/details/84786560