在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里面设置。所以上面这些作为参考就可以了。