Android 在手机上安装debug和replace两个版本

前言:

今天项目集成了极光推送,但是极光推送没有沙箱环境,线上生产环境又不能进行测试,所以需要专门打包一个debug的版本,用于测试;还有:在用到一个第三方sdk,但是这个sdk并没有区分开发环境和线上环境,这时候我们就可能会申请两个不同的key标识,而且很多key标识都只能在androidmanifest里面配置。所以每次上线生成apk就必须手动去更改key标识,如果渠道版本少也还好,打包速度快也还行,需要区分环境的的key标识相对较少也还不错 ,但是如果你一项都沾不到边,到时忘记哪个key忘记替换了,那后期就会很麻烦;

  • 先在androidmanifest文件配置一个节点,这里以极光为例
   

build.gradle写法

    buildTypes {
        release {
            signingConfig signingConfigs.release
            // 如果没有提供混淆规则文件,则设置默认的混淆规则文件(SDK/tools/proguard/proguard-android.txt)
            pseudoLocalesEnabled false
            // 不显示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //Zipalign优化
            zipAlignEnabled true
            // 移除无用的resource文件
            shrinkResources true
            //是否Debug
            debuggable false
            //  minifyEnabled true relase 为true
            //是否混淆
            minifyEnabled true
            //加载默认混淆配置文件
            proguardFile 'C:/workSpace/project/patient/proguard-rules.pro'
            manifestPlaceholders = [JPUSH_APPKEY_VALUE: "......108f7c76dd",
                                    APP_NAME:"@string/app_name"


            ]

        }
        debug {

            signingConfig signingConfigs.debug
            // 如果没有提供混淆规则文件,则设置默认的混淆规则文件(SDK/tools/proguard/proguard-android.txt)
            pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用
            // 不显示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //Zipalign优化
            zipAlignEnabled false
            // 移除无用的resource文件
            shrinkResources false
            //是否开启debug
            debuggable true
            //  minifyEnabled true
            //加载默认混淆配置文件
            minifyEnabled false
            //proguardFile 'C:/workSpace/project/patient/proguard-rules.pro'
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            applicationIdSuffix ".debug"
            manifestPlaceholders = [JPUSH_APPKEY_VALUE: "..........49377a7",
                                    APP_NAME:"@string/app_name_debug"

            ]

        }
    }

在bulidtypes节点下有release节点和debug节点,正式签名时就会走release节点的下编译脚本,调试签名时就会走debug节点。
本文主要点就是红框标记的manifestPlaceholders的用法,jpush_appkey对应的就是之前在androidmanifest文件配置的${jpush_appkey}的这个值。


Android 在手机上安装debug和replace两个版本_第1张图片
image.png

其实就是一个HashMap的对象,我们在build.gradle中写入,然后映射到AndroidMainfest.xml中,HashMap对象放置在activityInfo.metaData中,我们可以通过activityInfo.metaData.keyset()查看所有设置的值

我们在程序入口出打上log,用来检验key的值,可以直接写在application中

 String jpush_appkey;
        try {
            ApplicationInfo appInfo = getPackageManager()
                    .getApplicationInfo(getPackageName(),
                            PackageManager.GET_META_DATA);
            jpush_appkey = appInfo.metaData.getString("JPUSH_APPKEY");
            Log.w("jpush_appkey=" , jpush_appkey);
                   } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

但是这样我们还不能生成两个包,生成两个包,就是必须要包名不一样才可以,也就是ApplicationID值不一样

Application ID

每个Android app都有一个唯一的application ID,就像Java包名一样,例如com.example.myapp。 此ID可在设备和Google Play商店中唯一标识您的应用。 如果要上传新版app,application ID(以及sign用的证书)必须与旧版本的APK相同,如果您变更application ID,Google Play商店会将APK视为完全不同的 app。 因此,一旦发布应用程序,您就不应更改application ID。
application ID是使用模块build.gradle文件中的applicationId属性定义的,如下所示:

 defaultConfig {
        applicationId "com.test.com"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 25
        versionName "1.0.6"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
        //原因是Android系统定义总方法数是一个short int,short int 最大值为65536。解决这个问题的方案是:
        ndk {
            //选择要添加的对应cpu类型的.so库。
            abiFilters 'armeabi-v7a'
            // 'armeabi'

//              ,'x86', 'x86_64', 'mips', 'mips64','armeabi-v8a', 'x86', 'x86_64', 'armeabi-v7a'
        }
        vectorDrawables.useSupportLibrary = true
        signingConfig signingConfigs.release
        //  multiDexKeepProguard file("./tinker_multidexkeep.pro") //keep specific classes using proguard syntax

    }

当您在Android Studio中创建新项目时,applicationId与在setup过程中选择的the Java-style package name完全匹配。 但是,application ID和包名称在这一点之外是彼此独立的。 你可以更改程序包名称(代码命名空间),它不会影响application ID,反之亦然(但是,一旦发布应用程序,您就不应该更改application ID)。 但是,更改包名称有一些你应该注意的后果,请参阅修改包名称的部分。

虽然application ID看起来像一个传统的Java package name,但application ID的命名规则有一些限制:

  1. 它必须至少有两个片段(一个或多个点)。
  2. 每个片段必须以字母开头。
  3. 所有字符必须为字母数字或下划线[a-zA-Z0-9_]。

注意:application ID以前直接绑定到包名称; 因此一些Android API在其方法名称和参数名称中使用术语“包名称”,但这实际上是application ID。 例如,Context.getPackageName()方法返回application ID。 没有必要在app代码之外分享代码的真实包名。

警告:如果您正在使用WebView,请考虑在application ID中使用您的程序包名称作为前缀;

更改build variants的application ID

当为应用程序构建APK时,构建工具使用build.gradle文件中的defaultConfig块中定义的application ID来标记APK(如下所示)。 但是,如果您想要创建不同版本的应用以在Google Play商店中显示为单独的商家信息(例如“免费”和“专业版”),则需要分别创建具有不同application ID的独立的build variant。
在这种情况下,每个build variant应定义为单独的product flavor。 对于productFlavors {}块中的每个flavor,您可以重新定义applicationId属性,或者可以使用applicationIdSuffix将片段添加到默认application ID后面,如下所示:


Android 在手机上安装debug和replace两个版本_第2张图片
image.png

这样,“free”product flavor的application ID为“com.example.myapp.free”。
您还可以使用applicationIdSuffix根据您的build type附加片段,如下所示:


Android 在手机上安装debug和replace两个版本_第3张图片
image.png

因为Gradle在product flavor之后应用build type配置,所以“free debug”build variant的application ID现在是“com.example.myapp.free.debug”。 当您希望在同一设备上同时创建debug和release版本时,这是非常有用的,因为没有两个APK可以具有相同的application ID。

请注意,具有不同application ID的APK会被视为Google Play商店中不同的app。 因此,如果您想使用相同的app清单来分发多个APK,而每个APK都指定不同的device configuration(例如API等级),则必须为每个build variant使用相同的application ID,但是为每个APK提供不同的versionCode。 有关详细信息,请阅读有关Multiple APK支持。

警告:为了与以前的SDK tools兼容,如果未在build.gradle文件中定义applicationId属性,build tools将使用AndroidManifest.xml文件中的包名称作为application ID。 在这种情况下,重构包名称也会更改application ID。

提示:如果您需要在manifest file中引用应用程序ID,则可以在任何manifest attribute中使用$ {applicationId}占位符。 在构建期间,Gradle将此标记重新放置为实际application ID。 有关更多信息,请参阅将Build Variables注入到Manifest。

更改application ID以进行测试

默认情况下,build tools会使用指定build variant的application ID应用到您的instrumentation测试APK, 附加.test。 例如,com.example.myapp.free build variant的测试APK的application ID为com.example.myapp.free.test。

虽然没有必要,但您可以通过在defaultConfig或productFlavor块中定义testApplicationId属性来更改 application ID。

注意:为了避免与测试中的app发生名称冲突,build tools会为测试APK生成R类,并使用基于test application ID的命名空间,而不是manifest file中定义的包名称。

更改包名称

虽然默认情况下项目的程序包名称与application ID相匹配,但你可以更改它。 但是,如果要更改程序包名称,请注意程序包名称(由项目目录结构定义)应始终与AndroidManifest.xml文件中的package attribute相匹配,如下所示:




Android build tools使用package attribute来做两件事情:

  1. 它将此名称应用为应用程序生成的R.java类的命名空间。
    示例:使用上面的manifest,R类将是com.example.myapp.R。
  2. 它使用它来解析在manifest file中声明的任何相关类名。
    示例:使用上面的manifest,声明为的activity被解析为com.example.myapp.MainActivity。

因此,package attribute中的名称应该始终与项目的activities和app代码中的基本包名称匹配。 当然,你可以在项目中有子包,但是这些文件必须使用package attribute中的命名空间导入R.java类,并且manifest中声明的任何应用程序组件必须添加缺少的子包名称(或者使用完整包名称)。

如果你想完全重构你的包名,一定要更新package attribute。 只要您使用Android Studio's tools 重命名和重构您的软件包,则这些就会自动保持同步。 (如果它们不保持同步,您的应用代码无法解析R类,因为它不在同一个包中,而且manifest将无法识别activities或其他组件。)

您必须始终在项目的主AndroidManifest.xml文件中指定package attribute。 如果您有其他清单文件(例如对于product flavor 或者 build type),请注意,由最高优先级manifest file提供的软件包名称始终用于最终合并的manifest。 有关更多信息,请参阅合并多个清单文件。

还有一件事要知道:虽然manifest包名称和Gradle applicationId可能有不同的名称,但build tools会在构建结束时将application ID复制到APK的最终manifest file中。 所以如果你在构建之后检查你的AndroidManifest.xml文件,不要惊讶包属性已经改变。 package attribute是Google Play商店和Android平台实际用来识别app的地方。

需要到谷歌的开发中心阅读文档,自己想办法

你可能感兴趣的:(Android 在手机上安装debug和replace两个版本)