最近在学习撸撸的代码规范和写法,有些心得,准备好好写一写~包括了多渠道打版(以前有写过方法),工厂模式,mvp,以及最近刚封装出来的多渠道多版本展示不同页面的manifestPlaceholders的配置方法,大家应该也碰到过线上和线下环境的切换换地址,换私钥的头大问题,本篇就来解决这些问题。

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

android:name="JPUSH_APPKEY"

android:value="${jush_appkey_value}" />

android:name="SHOUCANG_CONFIG0"

android:value="${SHOUCANG_CONFIG_VALUE0}" />

build.gradle:buildTypes {

release {

//自定义buildconfig字段

buildConfigField("boolean", "APP_ENV", "true")

//指定签名为release

signingConfig signingConfig.release

//是否开启混淆

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

//是否zip优化

zipAlignEnabled true

//删除一些无用资源

shrinkResources false

//

manifestPlaceholders = [

"jush_appkey_value": "release key"

]

}

debug {

//自定义buildconfig字段

buildConfigField("boolean", "APP_ENV", "true")

//指定签名为release

signingConfig signingConfig.release

//是否开启混淆

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

//是否zip优化

zipAlignEnabled true

//删除一些无用资源

shrinkResources false

//

manifestPlaceholders = [

"jush_appkey_value": "debug key"

]

}

}

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

在程序入口出打上log,用来输出key的值:/**

* 在程序入口出打上log,用来输出key的值bufen

*/

private void jpush_key_manifest_xml_string() {

String jpush_appkey;

try {

ApplicationInfo appInfo = getPackageManager()

.getApplicationInfo(getPackageName(),

PackageManager.GET_META_DATA);

jpush_appkey = appInfo.metaData.getString("JPUSH_APPKEY");

Log.e("jpush_appkey", "jpush_appkey=" + jpush_appkey);

} catch (PackageManager.NameNotFoundException e) {

e.printStackTrace();

}

}

接下来给大家介绍多版本多页面多apk的配置切换方法:举个例子:如果你要一次性打七个版本,而且七个版本都是不同的页面,但是页面各个模块大体一样,只是顺序和大小不同,你要怎么做,别告诉我写七个页面分别打版哈~太low了~you know~这里就利用多版本打版和manifestPlaceholders来实现需求。

首先是build.gradle:apply plugin: 'com.android.application'

apply plugin: 'android-apt'

def demo = '0000';//DemoAPK

def demo1 = '0001';//DemoAPK1

def demo2 = '0002';//DemoAPK2

def demo3 = '0003';//DemoAPK3

def demo4 = '0004';//DemoAPK4

def demo5 = '0005';//DemoAPK5

def demo6 = '0006';//DemoAPK6

android {

signingConfigs {

debug {

keyAlias '****'

keyPassword '****'

storeFile file('签名文件.jks路径')

storePassword '****'

}

release {

keyAlias '****'

keyPassword '****'

storeFile file('签名文件.jks路径')

storePassword '****'

}

}

compileSdkVersion 25

buildToolsVersion "25.0.2"

sourceSets {

main {

jniLibs.srcDirs = ['libs']

}

}

packagingOptions {

exclude 'META-INF/DEPENDENCIES'

exclude 'META-INF/NOTICE'

exclude 'META-INF/LICENSE'

exclude 'META-INF/LICENSE.txt'

exclude 'META-INF/NOTICE.txt'

}

defaultConfig {

applicationId "com.shining.p010_recycleviewall"

minSdkVersion 18

targetSdkVersion 23

versionCode 1

versionName "1.0"

multiDexEnabled true

renderscriptTargetApi 19

renderscriptSupportModeEnabled true

ndk {

moduleName "native-modbus-jni,libxmediaplayer"

ldLibs "log", "z", "m", "android", "c"

abiFilters "armeabi", "armeabi-v7a", "x86"

}

sourceSets.main {

jni.srcDirs = []

//LOCAL_LDFLAGS += -fuse-ld=bfd

//jni.srcDirs 'src/main/jni'

jniLibs.srcDir 'src/main/libs'

}

signingConfig signingConfigs.debug

manifestPlaceholders = [

SHOUCANG_CONFIG_VALUE0: ".shoucang.factorys.ShoucangFactory0"

]

}

buildTypes {

release {

minifyEnabled true

zipAlignEnabled true

shrinkResources false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

signingConfig signingConfigs.debug

}

}

def int minSdk = 18;

def int targetSdk = 23;

def String appId = 'com.shining.p010_recycleviewall';

def int vCode = 1;

def String vNameCode = vCode + "";

productFlavors {

//demo

DemoAPK {

minSdkVersion minSdk

applicationId appId

targetSdkVersion targetSdk

versionCode vCode

versionName "DemoAPK_" + "T_" + demo

multiDexEnabled true

renderscriptTargetApi 19

renderscriptSupportModeEnabled true

ndk {

moduleName "native-modbus-jni,libxmediaplayer"

ldLibs "log", "z", "m", "android", "c"

abiFilters "armeabi", "armeabi-v7a", "x86"

}

sourceSets.main {

jni.srcDirs = []

jniLibs.srcDir 'src/main/libs'

}

signingConfig signingConfigs.debug

}

//demo1

DemoAPK1 {

minSdkVersion minSdk

applicationId appId

targetSdkVersion targetSdk

versionCode vCode

versionName "DemoAPK1_" + "T_" + demo1

multiDexEnabled true

renderscriptTargetApi 19

renderscriptSupportModeEnabled true

ndk {

moduleName "native-modbus-jni,libxmediaplayer"

ldLibs "log", "z", "m", "android", "c"

abiFilters "armeabi", "armeabi-v7a", "x86"

}

sourceSets.main {

jni.srcDirs = []

jniLibs.srcDir 'src/main/libs'

}

signingConfig signingConfigs.debug

}

//demo2

DemoAPK2 {

minSdkVersion minSdk

applicationId appId

targetSdkVersion targetSdk

versionCode vCode

versionName "DemoAPK2_" + "T_" + demo2

multiDexEnabled true

renderscriptTargetApi 19

renderscriptSupportModeEnabled true

ndk {

moduleName "native-modbus-jni,libxmediaplayer"

ldLibs "log", "z", "m", "android", "c"

abiFilters "armeabi", "armeabi-v7a", "x86"

}

sourceSets.main {

jni.srcDirs = []

jniLibs.srcDir 'src/main/libs'

}

signingConfig signingConfigs.debug

}

//demo3

DemoAPK3 {

minSdkVersion minSdk

applicationId appId

targetSdkVersion targetSdk

versionCode vCode

versionName "DemoAPK3_" + "T_" + demo3

multiDexEnabled true

renderscriptTargetApi 19

renderscriptSupportModeEnabled true

ndk {

moduleName "native-modbus-jni,libxmediaplayer"

ldLibs "log", "z", "m", "android", "c"

abiFilters "armeabi", "armeabi-v7a", "x86"

}

sourceSets.main {

jni.srcDirs = []

jniLibs.srcDir 'src/main/libs'

}

signingConfig signingConfigs.debug

}

//demo4

DemoAPK4 {

minSdkVersion minSdk

applicationId appId

targetSdkVersion targetSdk

versionCode vCode

versionName "DemoAPK4_" + "T_" + demo4

multiDexEnabled true

renderscriptTargetApi 19

renderscriptSupportModeEnabled true

ndk {

moduleName "native-modbus-jni,libxmediaplayer"

ldLibs "log", "z", "m", "android", "c"

abiFilters "armeabi", "armeabi-v7a", "x86"

}

sourceSets.main {

jni.srcDirs = []

jniLibs.srcDir 'src/main/libs'

}

signingConfig signingConfigs.debug

}

//demo5

DemoAPK5 {

minSdkVersion minSdk

applicationId appId

targetSdkVersion targetSdk

versionCode vCode

versionName "DemoAPK5_" + "T_" + demo5

multiDexEnabled true

renderscriptTargetApi 19

renderscriptSupportModeEnabled true

ndk {

moduleName "native-modbus-jni,libxmediaplayer"

ldLibs "log", "z", "m", "android", "c"

abiFilters "armeabi", "armeabi-v7a", "x86"

}

sourceSets.main {

jni.srcDirs = []

jniLibs.srcDir 'src/main/libs'

}

signingConfig signingConfigs.debug

}

//demo6

DemoAPK6 {

minSdkVersion minSdk

applicationId appId

targetSdkVersion targetSdk

versionCode vCode

versionName "DemoAPK6_" + "D_" + demo6

multiDexEnabled true

renderscriptTargetApi 19

renderscriptSupportModeEnabled true

ndk {

moduleName "native-modbus-jni,libxmediaplayer"

ldLibs "log", "z", "m", "android", "c"

abiFilters "armeabi", "armeabi-v7a", "x86"

}

sourceSets.main {

jni.srcDirs = []

jniLibs.srcDir 'src/main/libs'

}

signingConfig signingConfigs.debug

}

}

// 自定义输出配置

applicationVariants.all { variant ->

variant.outputs.each { output ->

def outputFile = output.outputFile

if (outputFile != null && outputFile.name.endsWith('.apk')) {

//                def fileName = "UerbT_v${variant.versionName}_${releaseTime()}_${variant.flavorName}.apk"

def fileName = "${variant.versionName}.apk"

output.outputFile = new File(outputFile.parent, fileName)

}

}

}

productFlavors.all { flavor ->

def currentMode = flavor.versionName.split("_")[2]

def currentEnvironment = flavor.versionName.split("_")[1]

def stValue = true

// t == currentEnvironment 以前的判断条件

if (currentEnvironment.endsWith("T")) {//判断是否为测试版 是否以T结尾

stValue = false

} else {

stValue = true

}

if (currentMode == demo) {

flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory", STATISTICS_VALUE: stValue]

} else if (currentMode == demo1) {

flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory1", STATISTICS_VALUE: stValue]

} else if (currentMode == demo2) {

flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory2", STATISTICS_VALUE: stValue]

} else if (currentMode == demo3) {

flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory3", STATISTICS_VALUE: stValue]

} else if (currentMode == demo4) {

flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory4", STATISTICS_VALUE: stValue]

} else if (currentMode == demo5) {

flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory5", STATISTICS_VALUE: stValue]

} else if (currentMode == demo6) {

flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory6", STATISTICS_VALUE: stValue]

}

}

}

dependencies {

compile fileTree(include: ['*.jar'], dir: 'libs')

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {

exclude group: 'com.android.support', module: 'support-annotations'

})

compile 'com.android.support:appcompat-v7:25.3.0'

compile 'com.android.support:recyclerview-v7:25.3.0'

compile 'com.android.support:design:25.3.0'

compile 'com.android.support:cardview-v7:25.3.0'

// local jar file

compile files('libs/alipay-sdk-java20161226110022.jar')

compile files('libs/alipay-sdk-java20161226110022-source.jar')

compile files('libs/commons-logging-1.1.1.jar')

compile files('libs/commons-logging-1.1.1-sources.jar')

//the third file

compile 'com.jakewharton:butterknife:8.2.1'

apt 'com.jakewharton:butterknife-compiler:8.2.1'

testCompile 'junit:junit:4.12'

compile 'com.geeklx:library_hios:1.0.4'

compile project(':glin')

compile 'com.github.bumptech.glide:glide:3.7.0'

compile 'com.alibaba:fastjson:1.2.17'

compile 'com.squareup.okio:okio:1.9.0'

compile 'com.squareup.okhttp3:okhttp:3.4.1'

compile 'com.nineoldandroids:library:2.4.0'

compile files('libs/libammsdk.jar')

}

接着就是多版本的代码判断书写:@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

//TODO 多版本切换 写此方法bufen

which_version();

//        ShoucangConfig0.config();//manifestPlaceholders的妙用

super.onCreate(savedInstanceState);

}

private void which_version() {

if (ConstantNetUtil.VERSION_APK == NetConfig.version_name0) {

ShoucangConfig.config();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name1) {

ShoucangConfig1.config();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name2) {

ShoucangConfig2.config();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name3) {

ShoucangConfig3.config();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name4) {

ShoucangConfig4.config();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name5) {

ShoucangConfig5.config();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name6) {

ShoucangConfig6.config();

}

}

//TODO 多版本模式bufen

SparseArrayCompat> array = which_version_fragment_config();//demo

private SparseArrayCompat> which_version_fragment_config() {

if (ConstantNetUtil.VERSION_APK == NetConfig.version_name0) {

return ShoucangConfig.getFragments();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name1) {

return ShoucangConfig1.getFragments();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name2) {

return ShoucangConfig2.getFragments();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name3) {

return ShoucangConfig3.getFragments();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name4) {

return ShoucangConfig4.getFragments();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name5) {

return ShoucangConfig5.getFragments();

} else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name6) {

return ShoucangConfig6.getFragments();

}

return ShoucangConfig.getFragments();

}

这样跑完apk你会发现会有神奇的事情发生,如下图:(不同的apk版本出来的页面也是不同的,但是只用了一份代码。)

图1:

图2:

这样做的好处在于,如果你的apk版本很多,需要给很多合作厂商提供定制化页面,就可以用上了~

卧槽,今天喷了好多,希望大家回去自己细化一下,能帮到你~

地址:https://github.com/geeklx/MyApplication/tree/master/p027_daojishi_manifestPlaceholders

android studio manifestplaceholders,Android Studio - 第四十五期 Gradle manifestPlaceholders相关推荐

  1. 第四十五期:万亿级日访问量下,Redis在微博的9年优化历程

    Redis在微博内部分布在各个应用场景,比如像现在春晚必争的"红包飞"活动,还有像粉丝数.用户数.阅读数.转评赞.评论盖楼.广告推荐.负反馈.音乐榜单等等都有用到Redis. 作者 ...

  2. 第四十五期:程序员未来干什么?做架构还是做管理?

    很多程序员应该都会有这个疑问,尤其是工作经验不多的,对未来充满了期待.在我职业生涯的早期,比较偏重于走管理路线:现在呢,成了公司的架构师,当然也会承担一部分的管理工作. 很多程序员应该都会有这个疑问, ...

  3. IBM发布第一个有100个量子比特的量子计算机; 研究人员创建动态对称性以改进量子比特 | 全球量子科技与工业快讯第四十五期

    IBM发布第一个拥有100个量子比特的量子计算机 IBM最新的量子计算芯片,在11月15日发布,这建立了一个里程碑,其封装了127个量子比特(qubit),这使得它成为第一个比特达到3位数的此类设备. ...

  4. 拓扑排序排课系统_木犀互联网技术周刊(第四十五期): 分布式系统简介

    分布式系统(distributed system) 什么是分布式系统? 分布式系统是由一组通过网络进行通信.为了完成共同的任务而协调工作的计算机节点组成的系统.分布式系统的出现是为了用廉价的.普通的机 ...

  5. android相册幻灯片功能,玩机教程 篇四十五:「MIUI玩机技巧63」MIUI相册新增“幻灯片播放”功能...

    玩机教程 篇四十五:「MIUI玩机技巧63」MIUI相册新增"幻灯片播放"功能 2020-02-17 16:15:35 0点赞 0收藏 0评论 本帖主要解决2大问题: 1) 功能科 ...

  6. 孤荷凌寒自学python第四十五天Python初学基础基本结束的下阶段预安装准备

    孤荷凌寒自学python第四十五天Python初学基础基本结束的下阶段预安装准备 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天本来应当继续学习Python的数据库操作,但根据过去我自学 ...

  7. 【Microsoft Azure 的1024种玩法】四十五.在Azure中快速创建Azure AD Domain Services

    [简介] Azure Active Directory (Azure AD) 是一种基于云的标识和访问管理服务. Azure Active Directory 可帮助相关企业访问内部资源,例如企业 I ...

  8. Python编程基础:第四十五节 方法链Method Chaining

    第四十五节 方法链Method Chaining 前言 实践 前言 方法链是指一个对象一次调用其自身的多个方法,通常写作对象.方法1.方法2.由于这种调用方法看起来像一个链条,所以我们将其称作方法链. ...

  9. 四十五、深入Java的网络编程(上篇)

    @Author:Runsen @Date:2020/6/8 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

最新文章

  1. [译]深入理解JVM
  2. 怎样定义最小 可遗传神经网络
  3. Sorm进阶(1):storm实现github提交数监控看板
  4. 在使用DBCA时报错,第二个节点无法启动数据库实例
  5. 一个使用:focus-within伪类实现的button选中动画效果
  6. linux系统中变量,Linux系统中的环境变量知识详解
  7. 记一次面试腾讯的奇葩经历
  8. RabbitMQ学习之基于spring-rabbitmq的消息异步发送
  9. html背景图适应div_CSS实现背景图片屏幕自适应
  10. HDU-2082 找单词 母函数
  11. Linux Netfilter 防火墙模块爆新漏洞,攻击者可获取root权限
  12. Eddy Cue称FBI可能会要求苹果激活iPhone摄像头并打开麦克风
  13. micropython教程nucleo-f767zi开发板_Micropython教程之TPYBoard开发板制作电子时钟(萝卜学科编程教育)...
  14. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南)(热身赛)
  15. 天啊!才几天没去看新闻,WinCE就有这么“爆炸”的新闻了?
  16. 外观检验人员一致性(Kappa)分析
  17. 计算机中低级语言和高级语言的区别?
  18. CAD绘图次序快捷键是什么?怎么用?
  19. flash 批量编译发布fla 文件
  20. Linux 自检和 SystemTap

热门文章

  1. VC++ MFC橡皮筋技术
  2. Android使用webview获取百度百家号网站源码
  3. 基于JAVA某医院门诊预约系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
  4. [激光原理与应用-18]:《激光原理与技术》-4- 激光产生技术 - 粒子数反转与“光”强放大的基本原理
  5. 详细解说IMU惯性测量单元
  6. elementSelect 选择器多选名称过长撑开变高,超出选择框,有多个时并会撑开原始高度优化方式
  7. Random Forest(随机森林)在软件缺陷预测领域的应用及其特点
  8. 家用中央空调保养与不保养的区别在哪里?
  9. 借助定时器,每100毫秒宽和高都+2px
  10. Linux教程——常见Linux发行版本有哪些?