android studio打包發佈以及生成jar,aar包

        在android studio中生成aar包,其實過程還是比較麻煩的,首先需要在需要生成aar包的module項目下的build.gradle文件裏面將apply plugin:‘com.android.application’替換成apply plugin:‘com.android.library’,然後需要注意,如果build.gradle裏面有applicationId的話,需要先註釋掉,因爲這個會影響aar包的生成。最後點擊build->rebuild project然後在module的build->outputs->aar下就會生成aar包了,例如我的是app-debug.aar,另外,其實在build->intermediates->bundles下會生成相應的版本的aar包項目,例如是debug版本的,下面會有一個debug項目。最後如果將apply plugin:'com.android.application'替換成apply plugin: 'com.android.library'那麼最後整個項目都是不可運行的,需要替換回來,這點需要注意!
        在android studio中生成jar包其實跟生成aar包的過程是一樣的,因爲生成aar包的過程會包含生成jar包,而這個jar包其實就是module的build->intermediates->bundles下的項目中的classes.jar。
        所以說apply plugin: 'com.android.library'其實意思是生成庫文件的意思,庫文件在android studio裏面有兩種:jar,aar。


        最後需要注意的是applicationId這個東西,這裏涉及到兩個概念:applicationId,packageName。
        每一個app的包名都是app在設備和應用商店的唯一標誌。同時,它被用來命名資源類的包和解析類的名稱R文件,Activity文件的包名。
        但是我們注意到一個問題,那就是如果發佈多個版本的app,例如debug版本,release,alpha版本,那麼包名如果一樣那麼版本就容易出現更新出錯,或者app被不同版本的app替代的情況。
        考慮到不同版本的唯一標識,以及R文件,.java文件的包名。這裏解決的方案就是,在設備以及商店中使用的是applicationId,也就是說,AndroidManifest文件中,以及商店中使用的是applicationId。而apk內部R文件的引用,以及.java的使用使用的是packageName。ps:AndroidManifest文件是一份證明文件,也是apk添加到設備中時,設備作爲參考的文件,設備通過他來詢問使用者是否給予權限,以及記錄apk的問一標誌。
        我們可以在build.gradle文件中指定applicationId,例如:defaultConfig{applicationId ‘com.example.administrator.application’}


        總的來說,就是applicationId是app的唯一標識,而packageName僅僅是包名!


        這裏先講講多渠道打包。多渠道打包需要在先在AndroidManifest中添加例如<meta-data android:name="KEY_CHANNEL" android:value="CHANNEL_ID" />的PlaceHolder,這裏CHANNEL_ID就是渠道標誌,多渠道打包就是讓這個標誌自動發生變化。這裏,其實詳細過程應該如下:


1.AndroidManifest下添加<meta-data android:name="KEY_CHANNEL" android:value="${CHANNEL_ID_VALUE}"的PlaceHolder


2.build.gradle下設置productFlavors,也就是
android{
productFlavors{


han{
manifestPlaceholders=[CHANNEL_ID_VALUE:"han"]
}
baidu{
manifestPlaceholders=[CHANNEL_ID_VALUE:"baidu"]
}


}
}
或者使用另外一種更加簡潔的方式:
android{
productFlavors{


han{}
baidu{}


}


productFlavors.all{
flavor->flavor.manifestPlaceholders=[CHANNEL_ID_VALUE:name]
}


}


其實,整個過程就是使用AndroidManifest的聲明作用,在AndroidManifest中聲明一個key-value,value是一個指針,然後再build.gradle中value指針被賦予一個實際值。然後就可以生成多個apk了。






        另外,其實可以在productFlavors的不同版本里面是可以設置applicationId的。


        另外,在productFlavors中還可以設置applicationIdSuffix給當前版本的applicationId添加後綴,形成自己的applicationId。

        Build Variants窗口裏面會有運行的項目的信息,裏面每個module都會在裏面,我們可以切換每個module的運行方式,一般使用debug,但是可以切換到例如release等其他模式。這在多渠道打包中很有用,需要特別注意!


        最後,其實還可以使用variant進行多渠道發佈。採用的是動態替換渠道字符串的方式,生成各渠道的AndroidManifest文件並打包。

        前面的步驟是一樣的,最後一步在build.gradle下配置的是如下:

//替換AndroidManifest.xml的UMENG_CHANNEL_VALUE字符串爲渠道名稱 By Remex Huang
android.applicationVariants.all{ variant -> 
    variant.processManifest.doLast{

        //之前這裏用的copy{},我換成了文件操作,這樣可以在v1.11版本正常運行,並保持文件夾整潔
        //${buildDir}是指build文件夾
        //${variant.dirName}是flavor/buildtype,例如GooglePlay/release,運行時會自動生成
        //下面的路徑是類似這樣:build/manifests/GooglePlay/release/AndroidManifest.xml
        def manifestFile = "${buildDir}/manifests/${variant.dirName}/AndroidManifest.xml"

        //將字符串UMENG_CHANNEL_VALUE替換成flavor的名字
        def updatedContent = new File(manifestFile).getText('UTF-8').replaceAll("UMENG_CHANNEL_VALUE", "${variant.productFlavors[0].name}")
        new File(manifestFile).write(updatedContent, 'UTF-8')

        //將此次flavor的AndroidManifest.xml文件指定爲我們修改過的這個文件
        variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.dirName}/AndroidManifest.xml")
    }    
}
另外,這裏前面使用的方式是:

android.applicationVariants.all{ variant -> 
    println "${variant.productFlavors[0].name}"
    variant.processManifest.doLast{
        copy{
            from("${buildDir}/manifests"){
                include "${variant.dirName}/AndroidManifest.xml"
            }
            into("${buildDir}/manifests/$variant.name")

            filter{
                String line -> line.replaceAll("UMENG_CHANNEL_VALUE", "${variant.productFlavors[0].name}")
            }

            variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml")
        }    
   }
}
這種方式在gradle1.11裏面無法正常運行,所以才改用上一種方法,其實都是操作字符串跟文件而已。另外需要注意的是,

println "${variant.productFlavors[0].name}"
輸出的是productFlavors裏面的每一個版本的名字,這裏productFlavors[0]是因爲productFlavors可以有多個,而實際上我們只需要一個,所以實際上productFlavors[0]指的是build.gradle文件下的productFlavors{},而name則是裏面的版本元素的名字,所以最後輸出的是版本的名字。

        所以這種方法實際上就是操作AndroidManifest,將<meta-data android:name="KEY_CHANNEL" android:value="CHANNEL_ID_VALUE" />元素裏面的value值替換掉。詳細過程是讀取AndroidManifest字符串,然後將字符串的CHANNEL_ID_VALUE替換成版本的名字了。也就是說,這裏AndroidManifest字符串的replaceAll方法相當於productFlavors的manifestPlaceholders。


        其實最後這些方法都未必會使用,因爲太麻煩了。最簡單的使用方式是在project structure裏面設置。所以上面這些作爲參考就可以了。













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章