Gradle的一些技巧和遇到的問題

全局變量的使用

在多個module的狀況下,不一樣module的build.gradle文件中有部分配置項相似,或者依賴的類庫,有部分是相同的,在維護上不是很方便,這個時候就能夠考慮統一配置。在項目根目錄的build.gradle文件中添加如下代碼和android{}同級
ext {
    //全局變量控制,可在module中的build.gradle文件經過rootProject.ext.xxx開頭來使用
    compileSdkVersion = 24
    buildToolsVersion = '24.0.3'
    supportVersion = '24.2.1'
}

 

 

配置打包用的簽名

主要有接過度享或者受權登陸功能的都應該知道,像微信或者微博的分享和受權登陸提供sdk,只有在指定的簽名下才能生效,而咱們平時開發都習慣使用默認的androidkeystore打包簽名,這個時候想要測試分享或者登陸功能就須要手動去打包指定keystore的簽名。很是影響開發效率,這個時候能夠經過配置gradle,根據release或者是debug打包指定的簽名。

項目根目錄新建一個簽名用到的密碼管理文件signing.propertiesjava

signing.alias=dou361            #release
signing.password=dou361            #release
signing.jjdxm_alias=dou361        #debug
signing.jjdxm_password=dou361    #debug

在主程序build.gradle的apply plugin: 'com.android.application'下面添加android

Properties props = new Properties()
props.load(new FileInputStream(file(rootProject.file("signing.properties"))))

在android{}節點裏面添加微信

signingConfigs {
    release {
        keyAlias props['signing.alias']
        keyPassword props['signing.password']
        storeFile file(rootProject.file("debug.keystore"))
        storePassword props['signing.password']
    }

    debug {
        keyAlias props['signing.jjdxm_alias']
        keyPassword props['signing.jjdxm_password']
        storeFile file(rootProject.file("debug.keystore"))
        storePassword props['signing.jjdxm_password']
    }
}
buildTypes {
    debug {
        signingConfig signingConfigs.debug
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }

    release {
        signingConfig signingConfigs.release
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

  

 
 

運行不一樣的接口環境的apk

項目能夠經過定義多個不一樣的productFlavors來實現應用的不一樣定製版本,每個Flavor與buildTypes配合產出對應的一種輸出類型的apk文件,新建的項目初始化只有一個默認的Flavor:defaultConfig
   productFlavors {
        //接口正式環境仍是測試環境
        env_public {
            buildConfigField "boolean", "isTestEnv", "false"
        }

        env_test {
            buildConfigField "boolean", "isTestEnv", "true"
        }
    }

  

 跟buildTypes結合就有四種Build Variants(構建變種)。能夠不修改代碼直接運行相應的apk

會自動運行到BuildConfig裏,能夠判斷不一樣的值去加載不一樣的接口環境app

 /**
     * 是否測試環境
     */
    public static boolean isTest() {
        return BuildConfig.isTestEnv;
    }

ServiceInfoManager.getInstance().setEnv(IqbConfig.isTest() ? ServiceInfoManager.Environment.TestEnv : ServiceInfoManager.Environment.PublicEnv);

  

BuildConfig.DEBUG 始終爲 false

       BuildConfig.java 是編譯時自動生成的,而且每一個 Module 都會生成一份,以該 Module 的 packageName 爲 BuildConfig.java 的 packageName。因此若是你的應用有多個 Module 就會有多個 BuildConfig.java 生成,編譯時被依賴的 Module 默認會提供 Release 版給其餘 Module 或工程使用,這就致使該 BuildConfig.DEBUG 會始終爲 false。
       AndroidManifest.xml 中 application 節點的 android:debuggable 值是不一樣的。Debug 包值爲 true,Release 包值爲 false,這是編譯自動修改的。能夠經過 ApplicationInfo 的這個屬性去判斷是不是 Debug 版本。
public class AppUtils {
 
    private static Boolean isDebug = null;
 
    public static boolean isDebug() {
        return isDebug == null ? false : isDebug.booleanValue();
    }
    public static void syncIsDebug(Context context) {
        if (isDebug == null) {
            isDebug = context.getApplicationInfo() != null &&
                    (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        }
    }
}
//在本身的 Application 內調用進行初始化
AppUtils.syncIsDebug(getApplicationContext());

  


 混淆

不想混淆的類須要一個個添加到 proguard-rules.pro(或 proguard.cfg) 中嗎?這樣會致使 proguard 配置文件變得雜亂無章,同時須要團隊全部成員對其語法有所瞭解。
解決方法1:
//新建表示統一標識的註解 NotProguard
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
public @interface NotProguard {
 
}

NotProguard 是個編譯時註解,不會對運行時性能有任何影響。可修飾類、方法、構造函數、屬性。maven

而後在Proguard 配置文件中過濾被這個註解修飾的元素,表示不混淆被 NotProguard 修飾的類、屬性和方法。
# Keep annotated by NotProguard
-keep @cn.trinea.android.lib.annotation.NotProguard class * {*;}
-keep,allowobfuscation @interface cn.trinea.android.lib.annotation.NotProguard
-keepclassmembers class * {
    @cn.trinea.android.lib.annotation.NotProguard *;
}

解決方法2:函數

## keep 不想要混淆的類
-keep class com.xx.xx.base.utils.ProguardKeep {*;}
-keep class * implements com.xx.xx.base.utils.ProguardKeep {*;}

/**
 * 實現這個接口的類不會進行混淆
 *  proguard keep
 */
public interface ProguardKeep  {
}

  


 

找不到so

新建jniLibs,將so放進來
sourceSets {
    main {
        jniLibs.srcDir 'jniLibs'
    }
}

  


 

配置gradle離線工做 

在gradle中引用第三方模塊時採用maven方式依賴,每次打開Android Studio或者點擊sync按鈕時,都會去maven中央倉庫去取第三方的庫文件,通常是jar或者aar文件。若是下載完能夠配置 gradle離線工做 ,勾選gradle會使得速度更快,但同時存在一個問題,若是須要從網上加載第三方庫,會沒法下載,因此酌情使用。因此須要沒有的第三方模塊記得把這個關了。
external libraries下的庫在C:\Users\用戶名\.gradle\caches\modules-2\files-2.1下,或者右擊某個庫下面的某個類,點擊file path就能夠查看

 

 

直接運行release版本 

有時候調試SDK必需要用release版本,例如地圖、登陸,可是每次打包混淆太麻煩,但願能在IDE中直接跑出release版本的應用,簡單來講就是在debug模式下產生release版本的
//配置keystore簽名
signingConfigs {
        release {
            storeFile file("KeyStore")
            storePassword "98765432"
            keyAlias "lyly"
            keyPassword "98765432"
        }
}

appbuildTypes {
        debug {
            signingConfig signingConfigs.release
        }
        release {
            signingConfig signingConfigs.release
        }
    }

這樣編譯出來的debug版本直接用的是正式簽名。性能

 
 
 

依賴包重複的問題

遇到這樣的一個錯誤:com.android.dex.DexException: Multiple dex files define XXXX,通常狀況下,是咱們項目中引用了重複的庫或者jar包引發的,咱們找到去掉便可解決

com.loonggg.saoyisao.lib:1.1.0 這個依賴裏引用了第三方zxing。com.timmy.qrcode.lib:1.4.1這個依賴裏也引用了zxing這個庫,在com.timmy.qrcode.lib:1.4.1的依賴裏添加語句 exclude group: ‘com.google.zxing’,意思是編譯的時候將group爲com.google.zxing的全部library都去除在外,這樣com.timmy.qrcode.lib:1.4.1就會自動去引用com.loonggg.saoyisao.lib:1.1.0項目裏的zxing依賴了。這樣問題就解決了。
 
 
 

過濾日誌

^(?!.*(你要過濾掉的tag)).*$
^(?!.*(UserConnection|BroadcastConnection)).*$
 

 

 
 

根據Build.BRAND 字段判斷不一樣機型Rom

public class Rom {

    private Rom() {
        //no instance
    }

    /**
     * 是不是Oppo
     */
    public static final boolean IS_OPPO;
    /**
     * 是不是Vivo
     */
    public static final boolean IS_VIVO;
    /**
     * 是不是華爲,注意不包括華爲榮耀
     */
    public static final boolean IS_HUAWEI;
    /**
     * 是不是華爲榮耀
     */
    public static final boolean IS_HUAWEI_HONOR;
    /**
     * 是不是三星
     */
    public static final boolean IS_SAMSUNG;
    /**
     * 是不是努比亞
     */
    public static final boolean IS_NUBIA;

    static {

        final String brand = Build.BRAND.toUpperCase();

        IS_OPPO = brand.equalsIgnoreCase("OPPO");
        IS_VIVO = brand.equalsIgnoreCase("VIVO");
        IS_HUAWEI = brand.equalsIgnoreCase("HUAWEI");

        IS_HUAWEI_HONOR = brand.contains("HONOR");
        IS_SAMSUNG = brand.contains("SAMSUNG");

        IS_NUBIA = brand.contains("NUBIA");
    }

}

  


Module單獨運行

經過在組件工程下的gradle.properties文件中設置一個isRunAlone的變量來區分不一樣的場景,在組件的build.gradle開頭這樣寫:
if(isRunAlone.toBoolean()){    
  apply plugin: 'com.android.application'
}else{  
  apply plugin: 'com.android.library'
}
相關文章
相關標籤/搜索