• Android 使用 Gradle 多渠道打包


    安卓开发完毕。对于一个开放应用而言,我们须要公布到不同的应用市场,同一时候我们也须要统计不同市场的用户下载量。

    (通过启动应用后获取不同市场apk中的不同值来区分)

    以下用一个详细的实例来说明:
    1、在AndroidManifest.xml的application内加入meta-data标签

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name">
    
        <meta-data
            android:name="APP_CHANNEL"
            android:value="${APP_CHANNEL_VALUE}" />
    
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
    
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    2、改动build.gradle文件,在android {} 中加入

    android {
    
        // 打包渠道List
        productFlavors {
            wandoujia {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "豌豆荚"]
            }
            cn360 {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "360"]
            }
            baidu {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "百度"]
            }
            tencent {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "应用宝"]
            }
            sougou {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "搜狗市场"]
            }
        }
    
    }

    或者使用以下方法,直接使用flavor的name做为${APP_CHANNEL_VALUE}

    android {
    
        // 打包渠道List
        productFlavors {
            wandoujia {}
            cn360 {}
            baidu {}
            tencent {}
            sougou {}
        }
    
        // 批量处理,直接使用flavor的name作为APP_CHANNEL_VALUE的值
        productFlavors.all { flavor ->
            flavor.manifestPlaceholders = [APP_CHANNEL_VALUE: name]
        }
    
    }

    这样就完毕了。运行 gradle assembleRelease 喝口茶坐等便可。
    完毕后,到build/outputs/apk中就能够看到各种渠道包。

    有关assemble可用的命令还有:

    gradle assembleDebug    //全部Debug版本号
    gradle assembleRelease  //全部Release版本号
    gradle assembleBaidu    //指定渠道的DebugRelease版本号
    gradle assembleBaiduDebug   //指定渠道的Debug版本号
    gradle assembleBaiduRelease //指定渠道的Release版本号
    gradle build    //全部渠道的DebugRelease版本号

    最后附上我的 MainActivity 和 build.gradle

    package com.example.myandroid;
    
    import android.app.Activity;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageManager;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.os.Bundle;
    import android.widget.Toast;
    
    /**
     * 应用入口
     *
     * @author SHANHY(365384722@QQ.COM)
     * @date   2015年12月30日
     */
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            String channel = getAppMetaData("APP_CHANNEL");
            if(channel != null)
                Toast.makeText(this, channel, Toast.LENGTH_SHORT).show();
        }
    
        /**
         * 获取Application以下的metaData
         * 
         * @param name
         * @return
         * @author SHANHY
         * @date   2015年12月30日
         */
        public String getAppMetaData(String meta_name){
            try {
                ApplicationInfo appInfo = this.getPackageManager()
                        .getApplicationInfo(getPackageName(),PackageManager.GET_META_DATA);
                return appInfo.metaData.getString(meta_name);
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

    完整的 build.gradle 脚本

    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.0.0-alpha3'
        }
    }
    
    apply plugin: 'com.android.application'
    
    dependencies {
        compile fileTree(dir: 'libs', include: '*.jar')
    }
    
    android {
        compileSdkVersion 14
        buildToolsVersion "23.0.2"
    
        defaultConfig {
            // 能够手动改动例如以下一些配置。无需改动不论什么代码便能够生成相应配置的apk
            applicationId "com.example.myandroid.aaa"
            minSdkVersion 8
            targetSdkVersion 21
            versionCode 200
            versionName "2.0.0"
    
            // dex突破65535限制
            multiDexEnabled true
            // 默认打包渠道(官方)
            manifestPlaceholders = [APP_CHANNEL_VALUE: "官方"]
        }
    
        // 打包渠道List
        productFlavors {
            myself {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "官方"]
            }
            wandoujia {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "豌豆荚"]
            }
            cn360 {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "360"]
            }
            baidu {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "百度"]
            }
            tencent {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "应用宝"]
            }
            sougou {
                manifestPlaceholders = [APP_CHANNEL_VALUE: "搜狗市场"]
            }
        }
    
        // 打包渠道List
        //productFlavors {
        //  myself {}
        //  wandoujia {}
        //  cn360 {}
        //  baidu {}
        //  tencent {}
        //  sougou {}
        //}
    
        // 批量处理,直接使用flavor的name作为APP_CHANNEL_VALUE的值(也能够不使用该方法,在productFlavors中逐一配置)
        //productFlavors.all { flavor ->
        //  flavor.manifestPlaceholders = [APP_CHANNEL_VALUE: name]
        //}
    
        lintOptions {
            abortOnError false
        }
    
        sourceSets {
            main {
                manifest.srcFile 'AndroidManifest.xml'
                java.srcDirs = ['src']
                resources.srcDirs = ['src']
                aidl.srcDirs = ['src']
                renderscript.srcDirs = ['src']
                res.srcDirs = ['res']
                assets.srcDirs = ['assets']
            }
    
            // Move the tests to tests/java, tests/res, etc...
            instrumentTest.setRoot('tests')
    
            // Move the build types to build-types/<type>
            // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
            // This moves them out of them default location under src/<type>/... which would
            // conflict with src/ being used by the main source set.
            // Adding new build types or product flavors should be accompanied
            // by a similar customization.
            debug.setRoot('build-types/debug')
            release.setRoot('build-types/release')
        }
    
        //签名信息
        signingConfigs {
            debug{
                // No Debug Config
            }
    
            release {
                storeFile file("xxxxx.key")
                storePassword "xxxxx"
                keyAlias "xxxxx"
                keyPassword "xxxxx"
            }
        }
        buildTypes {
            //Debug模式
            debug {
                // 显示LOG,在java代码中的调用方式为:BuildConfig.LOG_DEBUG。AS工具能够在BuildConfig.java中新增这个字段,假设还要兼容使用eclipse,不建议使用新增字段,由于eclipse在clean后会又一次生成BuildConfig.java(默认使用BuildConfig.DEBUG能满足须要就不要特殊处理了)
                //buildConfigField "boolean", "LOG_DEBUG", "true"
    
                versionNameSuffix "-debug"
                // 不开启混淆
                minifyEnabled false
                // 不须要ZIP优化
                zipAlignEnabled false
                // 不须要资源压缩
                shrinkResources false
                // signingConfig 
                signingConfig signingConfigs.debug
            }
    
            //Release模式
            release {
                // 不显示LOG
                //buildConfigField "boolean", "LOG_DEBUG", "true"
    
                minifyEnabled true
                zipAlignEnabled true
                // 资源压缩,移除没用的资源文件
                shrinkResources true
                // 混淆文件配置
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                // 签名信息配置(假设上面配置了defaultConfig则能够不用指定signingConfig)
                signingConfig signingConfigs.release
    
                applicationVariants.all { variant ->
                    variant.outputs.each { output ->
                        def outputFile = output.outputFile
                        if (outputFile != null && outputFile.name.endsWith('.apk')) {
                            // 输出apk名称为myandroid_v1.0.0_2015-12-30_baidu.apk
                            def fileName = "myandroid_v${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk"
                            output.outputFile = new File(outputFile.parent, fileName)
                        }
                    }
                }
            }
        }
    }
    
    // 声明一个方法,获取打包时间
    def releaseTime() {
        return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
    }
    
  • 相关阅读:
    LeetCode 31 Next Permutation / 60 Permutation Sequence [Permutation]
    LeetCode 15 3Sum [sort] <c++>
    LeetCode 81 Search in Rotated Sorted Array II [binary search] <c++>
    LeetCode 33 Search in Rotated Sorted Array [binary search] <c++>
    LeetCode 80 Remove Duplicates from Sorted Array II [Array/auto] <c++>
    将博客搬至CSDN
    leetcode
    (转载) 图像领域常用资源
    Unity3D 之 C# 脚本
    Kinect 人机交互开发实践
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7281408.html
Copyright © 2020-2023  润新知