Android studio gradle 打包 那些事

时间:2022-09-30 22:20:25

总结了一下 目前觉得比较好用的gradle 和一些打包 经验。放在这里。

首先说下 渠道号 这个概念,我们经常会统计我们的api 访问来源 是来自于那个app store,这有利于 我们针对性的推广。也可以知道用户的分布情况,目前我们的做法通常是这样的:

Android studio gradle 打包 那些事

然后在我们的自定义application里面 定义一个函数 来取得这个渠道号

 package com.example.administrator.gradletest;

 import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; /**
* Created by Administrator on 2015/12/7.
*/
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
} private String getChannel(Context context) {
try {
PackageManager pm = context.getPackageManager(); ApplicationInfo appInfo = pm.getApplicationInfo(context.getPackageName(),PackageManager.GET_META_DATA);
return appInfo.metaData.getString("channel"); } catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return "";
}
}

然后再到gradle 脚本里面 动态更改manifest编译时的 meta data里面的值,这个方法是目前流传最广也是使用最多的方法,但是有个缺陷是速度太慢了。

随着我们app的扩展,本身我们编译一次就要很久的时间,然后你想想 至少还要分为debug和release2个版本,然后各种渠道 什么360 pp 百度 豌豆荚 锤子 小米 华为

之类7788 起码20个以上的渠道 再加上debug 和release 你想想 动不动 就是40几个版本,你要是再在gradle 修改脚本来做这件事,后果就是你编译一次 产出

就要很久很久,因为你每次修改完manifest文件里的meta data 都会重新编译一次,太浪费时间了!

所以我们采用下面的方法:

首先我们可以看一下 apk 这个文件 解压缩以后的结构:

Android studio gradle 打包 那些事

看一下这个就知道了,我们可以想一下 能否把我们的渠道号 放到这个路径下面呢?让我们的android app代码来读取这个文件路径下的渠道号,然后想办法在build出来的apk里面直接在这个路径下

放一个渠道号不就行了么?这样只用build 一次,修改n次 即可得到我们需要的n个渠道包了!

首先我们来修改我们的app代码:

 package com.example.administrator.gradletest;

 import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.util.Log; import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; /**
* Created by Administrator on 2015/12/7.
*/
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
} //这段代码的作用就是遍历自己的apk包 把包里的文件名全找到
//然后找到某个META-INF/mtchannel_xiaomishangcheng 这样格式的文件即可
//然后把xiaomishangcheng 这个字符串提取出来返回就是得到的渠道号了
private String getChannelByFile(Context context) {
ApplicationInfo appinfo = context.getApplicationInfo();
String sourceDir = appinfo.sourceDir;
String ret = "";
ZipFile zipfile = null;
try {
zipfile = new ZipFile(sourceDir);
Enumeration<?> entries = zipfile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry) entries.nextElement());
String entryName = entry.getName();
Log.v("burning","entryName=="+entryName);
if (entryName.startsWith("META-INF/mtchannel")) {
ret = entryName;
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (zipfile != null) {
try {
zipfile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} String[] split = ret.split("_");
if (split != null && split.length >= 2) {
return ret.substring(split[0].length() + 1); } else {
return "";
}
} //
//
// private String getChannel(Context context) {
// try {
// PackageManager pm = context.getPackageManager();
//
// ApplicationInfo appInfo = pm.getApplicationInfo(context.getPackageName(),PackageManager.GET_META_DATA);
// return appInfo.metaData.getString("channel");
//
// } catch (PackageManager.NameNotFoundException e) {
// e.printStackTrace();
// }
// return "";
// }
}

好,然后我们来编写脚本,这个脚本也很简单,拿到build出来的apk以后 就打开这个zip文件,然后往里面写一个我们规定好的那个格式的文件即可:

注意这是python代码,当然你如果不会python 用java也可以做。

 # coding=UTF-8
import zipfile
#这个就是你build完以后输出的apk包的路径
apkpath = 'C:/Users/Administrator/GradleTest/app/build/outputs/apk/app-debug.apk'
#这个就是随便建立一个空文件就可以了 一会要把这个文件写入apk
emptypath = 'C:/Users/Administrator/GradleTest/app/build\outputs/apk/none'
zipped = zipfile.ZipFile(apkpath, 'a', zipfile.ZIP_DEFLATED)
#这个就是用format的方法 给上面那个空文件重命名一下。
empty_channel_file = "META-INF/mtchannel_{channel}".format(channel='xiaomishangcheng')
#命名结束以后 就直接把这个空文件写入到apk中即可
zipped.write(emptypath,empty_channel_file)

你看,这样就可以完成我们快速生成渠道包的功能了,哪怕你有1000个渠道包需要打,你也只需要编译一次,然后稍微修改一下这个脚本,即可自动生成1000个渠道包。

然后接着看下一个:

如何配置签名信息,大家都知道android的 签名资源一般都是很宝贵的,一个组  可能只有1-2个 管理者能拿到那个原始的keystore。所以我们当然不能在我们的版本库

里面上传这个keystore文件 对吧,尤其做开源项目的时候更是如此,所以有下面的解决方法:

Android studio gradle 打包 那些事

你看 我们可以把签名文件定义在外面~~

然后继续修改build.gradle文件,就是你要打版本的 那个project下的build.gradle文件,别改错了!

 apply plugin: 'com.android.application'

 android {
compileSdkVersion 23
buildToolsVersion "23.0.1" //配置签名信息
signingConfigs{
release{
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
defaultConfig {
applicationId "com.example.administrator.gradletest"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
//告诉gradle 打release版本的时候使用的签名信息
signingConfig signingConfigs.release
//无效资源不要打包进release版本
shrinkResources true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
} dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
}

混淆开关你们自己决定开不开~~

最后说一下 多渠道打包的gradle问题,前面那个 python脚本 已经告诉了大家 如何针对渠道号这一需求 进行多渠道打包。

有兴趣的人可以扩展一下那个脚本,把apk的命名也可以规范一下。这是比较好的习惯。

当然了 关于多渠道打包 还有一种情况就是 比如某些应用市场 或者 某些渠道 非要让你加入他们的sdk什么的 才让你发布

那针对于这种情况,我们python 脚本 直接修改apk 这个zip包 就搞不定了。这种情况就需要 用gradle来解决。下面给出一个例子,

以后大家可以针对性的 也进行配置!

我们假设 现在要发2个版本,一个版本 要用EventBus的代码 还有一个版本不需要。

apply plugin: 'com.android.application'

android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
//这里我们定义了2个渠道版本 一个是modifyDev 这个dev包就是会打包进去eventbus的
//还有一个dev包 则是不会把eventbus打包进去
productFlavors {
"modifyDev" {
}
"dev"{ }
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
//命名规则,这个就是主要演示一下groovy闭包操作的
//前面我们知道多渠道打包还是用python来完成速度是最快的
output.outputFile = new File(
output.outputFile.parent,
"custom-${variant.buildType.name}-${variant.versionName}-${variant.productFlavors[0].name}.apk".toLowerCase())
//把unaligned apk删除掉 看着碍眼
File unaligned=output.packageApplication.outputFile
unaligned.delete() }
} signingConfigs{
release{
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
defaultConfig {
applicationId "com.example.administrator.gradletest"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
//我们当然也可以针对debug版本进行配置 这里就省略不进行特殊配置
debug { }
release {
//告诉gradle 打release版本的时候使用的签名信息
signingConfig signingConfigs.release
//无效资源不要打包进release版本
shrinkResources true
//release版本我们把扰码打开
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
} dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
//注意看这个地方我们使用的是provided 这样我们在写代码的时候就可以引用这个包下面的所有代码了
provided 'de.greenrobot:eventbus:2.4.0'
//但实际上你看只有 modifyDev 这个Flavor 会真正的Compile进去 其他默认情况下 是不会Compile进去的
modifyDevCompile 'de.greenrobot:eventbus:2.4.0'
}

然后看下我们activity的代码 就增加了一行:

 try {
Class.forName("de.greenrobot.event.EventBus");
Log.v("MainActivity","加载到EventBus包");
} catch (ClassNotFoundException e) {
Log.v("MainActivity","找不到EventBus包");
e.printStackTrace();
}

然后我们选择devRelease 作为我们的build varint看一下日志输出什么:

Android studio gradle 打包 那些事

发现 这里是找不到eventBus这个包的。

然后我们看下modifyDevRelease 看看是什么效果:

Android studio gradle 打包 那些事

发现 这个eventBus已经打进去了~~

到这,基本上android studio gradle 和 python配合打包的一些主要部分就讲解结束了。

Android studio gradle 打包 那些事的更多相关文章

  1. Android 使用Android Studio &plus; Gradle 或 命令行 进行apk签名打包

    官方文档:https://developer.Android.com/tools/publishing/app-signing.html 1. 默认为debug mode,使用的签名文件在: $HOM ...

  2. &lbrack;转&rsqb;加速Android Studio&sol;Gradle构建

    加速Android Studio/Gradle构建 android android studio gradle   已经使用Android Studio进行开发超过一年,随着项目的增大,依赖库的增多, ...

  3. Android studio 自定义打包apk名

    Android Studio打包应用默认生成的apk名称是:app-release.apk .如果我们要让生成的apk名跟我们版本包名有联系的话,那我们就要自定义生成的apk名了 需要在build.g ...

  4. &lbrack;Android Studio&rsqb; Android studio 多渠道打包&lpar;超简洁版&rpar;

    [Android Studio] Android studio 多渠道打包(超简洁版) 转载:http://xuyazhou.com/archives/461 http://relex.me/usin ...

  5. Android studio gradle配置完整版(转)

    Android studio gradle配置完整版https://my.oschina.net/u/1471093/blog/539075 Android studio 自定义打包apk名 - pe ...

  6. Android studio 使用心得&lpar;四&rpar;—android studio 多渠道打包&lpar;二&rpar;

    Android studio 使用心得(四)—android studio 多渠道打包 这篇文章讲了一种打包方式.是直接在android studio 里面可视化操作,结合配置文件.我个人觉得严格上来 ...

  7. 解决Android Studio Gradle Build Running慢的问题

    Android Studio方便好用,但是Android Studio Gradle Build Running很慢 解决方法: C:\Users\你的用户名\.gradle 目录下新建一个文件名为 ...

  8. 解决Android Studio Gradle Build特别慢的问题

    解决Android Studio Gradle Build 特别慢的问题 C:\Users\你的用户名\.gradle目录下新建一个文件名为gradle.properties的文件.内容为:org.g ...

  9. android studio gradle 两种更新方法更新

    android studio gradle 两种更新方法更新 第一种.Android studio更新 第一步:在你所在项目文件夹下:你项目根目录gradlewrappergradle-wrapper ...

随机推荐

  1. &lbrack;译&rsqb;Mongoose指南 - 验证

    开始前记住下面几点 Validation定义在SchemaType中 Validation是一个内部的中间件 当document要save前会发生验证 验证不会发生在空值上 除非对应的字段加上了 re ...

  2. Android 获取手机Mac地址,手机名称

    /** * 获取手机mac地址<br/> * 错误返回12个0 */ public static String getMacAddress(Context context) { // 获取 ...

  3. RAC 移动 OCR

    1.查看是否有OCR备份 # ocrconfig -showbackup 如果没有就备份一份 # ocrconfig -export /oracle/bak/ocr/ocr_11291433_exp. ...

  4. Windows7 搜索功能关闭了,怎么重新打开

    你的搜索功能被关闭了,打开cmd.exe,进入windows\system32输入OptionalFeatures.exe,里面有搜索功能选项,选择他.重新启动.

  5. 设计模式10---设计模式之原型模式(Prototype)

    1.场景模式 考虑这样一个实际应用:订单处理系统 里面有一个保存订单的功能,当产品数量超过1000份以后,拆成两份订单,再超,那么就再拆.直到每份订单不超过1000为止,订单有两种,一个是个人订单,一 ...

  6. JavaScript内置对象-Array

    ▓▓▓▓▓▓ 大致介绍 除了Object之外,Array类型恐怕就是JavaScript种最常用的类型了,JavaScript中的数组与其他语言中的数组有很大的区别,例如,数组的每一项可以存放任何值, ...

  7. 一脸懵逼学习基于CentOs的Hadoop集群安装与配置

    1:Hadoop分布式计算平台是由Apache软件基金会开发的一个开源分布式计算平台.以Hadoop分布式文件系统(HDFS)和MapReduce(Google MapReduce的开源实现)为核心的 ...

  8. 现代编译原理--第六章(中间树 IR Tree 含源码)

    (转载请表明出处   http://www.cnblogs.com/BlackWalnut/p/4559717.html ) 这一章,就虎书而言,理论知识点是及其少的,就介绍了为什么要有一个中间表示树 ...

  9. HTML day48

    前端知识之HTML内容   HTML介绍 Web服务本质 import socket#引入套接字模块 sk = socket.socket()#实例化一个套接字对象 sk.bind(("12 ...

  10. m函数与m文件的命名

    问题 创建函数test_image,按照定义方式进行调用,一直出现下图所示的错误, 调试的过程中一直提示输入参数太多,可是test_image这个函数的输入个数和调用这个函数的输入输出数目是一致的,然 ...