Android Studio - 第四十五期 Gradle manifestPlaceholders

简介:

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

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

1
2
3
4
5
6
7
<meta-data
             android:name= "JPUSH_APPKEY"
             android:value= "${jush_appkey_value}"  />
 
<meta-data
             android:name= "SHOUCANG_CONFIG0"
             android:value= "${SHOUCANG_CONFIG_VALUE0}"  />

    build.gradle:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
  * 在程序入口出打上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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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' )
 
 
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
     @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<Class<?  extends  BaseFragment>> array = which_version_fragment_config(); //demo
 
     private  SparseArrayCompat<Class<?  extends  BaseFragment>> 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:

wKioL1l5c6aCAbdJAAEIYRkyE5o544.png

    图2:

wKioL1l5c8jDsbnCAAEFluNEz6s494.png

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

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

    wKiom1l5dRTRUWpqAAOaFWzNfo4818.png









本文转自 吴雨声 51CTO博客,原文链接:http://blog.51cto.com/liangxiao/1951381,如需转载请自行联系原作者

目录
相关文章
|
1月前
|
SQL 人工智能 Dart
Android Studio的插件生态非常丰富
Android Studio的插件生态非常丰富
65 1
|
1月前
|
Ubuntu Linux Android开发
Android Studio支持多种操作系统
Android Studio支持多种操作系统
70 1
|
2月前
|
Android开发
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
|
4月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
339 1
|
1月前
|
前端开发 数据处理 Android开发
Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍
本文深入探讨了Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍,以及具体操作步骤、常见问题解决、高级调试技巧、团队协作中的调试应用和未来发展趋势,旨在帮助开发者提高调试效率,提升应用质量。
51 8
|
1月前
|
数据可视化 开发工具 Android开发
Android Studio
Android Studio
102 1
|
2月前
|
Android开发
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
|
2月前
|
Java Unix Linux
Android Studio中Terminal运行./gradlew clean build提示错误信息
遇到 `./gradlew clean build`命令执行出错时,首先应检查错误信息的具体内容,这通常会指向问题的根源。从权限、环境配置、依赖下载、版本兼容性到项目配置本身,逐一排查并应用相应的解决措施。记住,保持耐心,逐步解决问题,往往复杂问题都是由简单原因引起的。
367 2
|
2月前
|
Java Android开发 Windows
玩转安卓之配置gradle-8.2.1
为安卓开发配置Gradle 8.2.1,包括下载和解压Gradle、配置环境变量、修改配置文件以增加国内镜像,以及在Android Studio中配置Gradle和JDK的过程。
112 0
玩转安卓之配置gradle-8.2.1
|
3月前
|
XML IDE 开发工具
🔧Android Studio高级技巧大公开!效率翻倍,编码不再枯燥无味!🛠️
【9月更文挑战第11天】在软件开发领域,Android Studio凭借其强大的功能成为Android开发者的首选IDE。本文将揭示一些提升开发效率的高级技巧,包括自定义代码模板、重构工具、高级调试技巧及多模块架构。通过对比传统方法,这些技巧不仅能简化编码流程,还能显著提高生产力。例如,自定义模板可一键插入常用代码块;重构工具能智能分析并安全执行代码更改;高级调试技巧如条件断点有助于快速定位问题;多模块架构则提升了大型项目的可维护性和团队协作效率。掌握这些技巧,将使你的开发之旅更加高效与愉悦。
74 5