项目中导入本地AAR的方法,首先增加本地libs目录作为本地仓库:
repositories {
flatDir {
dirs 'libs'
}
}
然后增加文件依赖,譬如libs/test.aar
dependencies {
implementation(name:'test', ext: 'aar')
}
repositories {
flatDir {
dirs 'libs'
}
}
然后增加文件依赖,譬如libs/test.aar
dependencies {
implementation(name:'test', ext: 'aar')
}
$ curl -s "https://get.sdkman.io" | bash遗憾的是由于众所周知的国内网络环境问题导致资源始终下载不下来。强制终止安装后,还引发了一个问题:由于部分本地文件已经创建,重新尝试安装时会误判SDKMAN已经安装,但是却无法运行SDKMAN:
......
Looking for a previous installation of SDKMAN...
SDKMAN found.
======================================================================================================
You already have SDKMAN installed.
SDKMAN was found at:
/Users/daemon/.sdkman
Please consider running the following if you need to upgrade.
$ sdk selfupdate force
======================================================================================================
因此再次尝试安装,需要首先删除本地已有的文件和目录:
$ cd ~ $ rm -r .sdkman由于无法正常安装,因此需要使用代理:
$ export http_proxy="http://127.0.0.1:8087/" $ export https_proxy="http://127.0.0.1:8087/" $ curl -s "https://get.sdkman.io" | bash $ unset http_proxy $ unset https_proxy好了,这下安装好了,所有的文件都在 $HOME/.sdkman 目录下,后面安装的开发工具SDK也是存放在这个目录
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
$ sdk version
SDKMAN 5.7.3+337
$ sdk selfupdate
$ sdk list
================================================================================
Available Candidates
================================================================================
q-quit /-search down
j-down ?-search up
k-up h-help
--------------------------------------------------------------------------------
Ant (1.10.1) https://ant.apache.org/
......
可以查看SDKMAN支持管理的所有开发工具SDK列表。
$ sdk list gradle
================================================================================
Available Gradle Versions
================================================================================
5.0 4.4 2.14.1 1.11
5.0-rc-5 4.3.1 2.14 1.10
5.0-rc-4 4.3 2.13 1.9
5.0-rc-3 4.2.1 2.12 1.8
5.0-rc-2 4.2 2.11 1.7
5.0-rc-1 4.1 2.10 1.6
4.10.3 4.0.2 2.9 1.5
4.10.2 4.0.1 2.8 1.4
4.10.1 4.0 2.7 1.3
4.10 3.5.1 2.6 1.2
4.9 3.5 2.5 1.1
4.8.1 3.4.1 2.4 1.0
4.8 3.4 2.3 0.9.2
4.7 3.3 2.2.1 0.9.1
4.6 3.2.1 2.2 0.9
4.5.1 3.2 2.1 0.8
4.5 3.1 2.0 0.7
4.4.1 3.0 1.12
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
可以看到所有gradle的版本
$ sdk install gradle
也可以指定安装的版本号:
$ sdk install gradle 5.0
$ sdk use gradle 5.0
使用use只能在当前shell环境有效
$ sdk default gradle 5.0
$ sdk current gradle
$ sdk uninstall gradle 5.0
copy {
from zipTree(srcFile)
into file(upzipDir)
}
第三步,根据渠道号,在解压后的apk目录下的META-INFO文件夹下创建空文件task("zip_" + variant.name + "_" + channelName, type: Zip)
from upzipDir
archiveName = targetArchiveName
destinationDir targetout
}
基本流程如上,下面给出具体实现:# app/gradle.properties targetout=targetout然后渠道号采用读取json配置文件的方法,配置文件放在app项目根目录下,名称为,channels.json,示例如下:
{
"channels": [
{
"channelName": "xiaomi"
},
{
"channelName": "yingyongbao"
},
{
"channelName": "taobao"
}
]
}
下面是主要的脚本文件:
apply plugin: 'com.android.application'
android {
.......
buildType {
debug {
minifyEnabled false
}
release {
minifyEnabled true
zipAlignEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// 自定义的构建结果输出目录,构建前删除目录并重建
File target = new File(rootDir, project.targetout);
target.deleteDir()
target.mkdir()
// 读取json配置文件,转换为Channels类,类定义在脚本末尾
def channelsMap = new groovy.json.JsonSlurper().parse(file("channels.json"))
Channels channels = new Channels(channelsMap)
applicationVariants.all { variant ->
variant.assemble << {
variant.outputs.each { output ->
// 默认构建apk文件输出的路径,解压目录放在同级目录下
File oriFile = output.outputFile
String oriPath = oriFile.getAbsolutePath();
if (oriPath.endsWith(".apk")) {
oriPath = oriPath.substring(0, oriPath.length() - 4)
}
File upzipDir = new File(oriPath);
// 解压apk文件
copy {
from zipTree(oriFile)
into file(upzipDir)
}
// 挨个处理多渠道
channels.channels.each { channel ->
// 读取渠道名称
def channelName = channel.channelName
// 组装渠道文件名称,并创建空文件
def channelFileName = "channel_" + channelName
def dir = new File(upzipDir, "META-INF")
File channelFile = new File(dir, channelFileName)
channelFile.createNewFile()
// 定义重新压缩的apk的文件名称
String targetArchiveName = applicationId + "-v" + versionName + "-" + channelName + "-" + variant.buildType.name + ".apk"
// 重新压缩渠道包
task("zip_" + variant.name + "_" + channelName, type: Zip) {
from oriPath
archiveName = targetArchiveName
destinationDir target
}.execute()
// 删除之前创建的渠道空文件,便于下一个渠道包的生成
channelFile.delete()
}
}
}
}
}
// 单个渠道属性定义
class Channel {
String channelName;
}
// 渠道列表属性定义
class Channels {
List<channel> channels;
@Override
String toString() {
return "channels:" + channels
}
}
以上为多渠道打包脚本的实现,下面就是渠道号的获取了
try {
final ZipFile z = new ZipFile(context.getApplicationInfo().sourceDir);
Enumeration e = z.entries();
while (e.hasMoreElements()) {
final ZipEntry entry = e.nextElement();
if (entry.getName().startsWith("META-INF/channel_")) {
channelId = entry.getName().split("_")[1];
Log.e("tag", "渠道号: " + channelId);
break;
}
}
} catch (IOException e) {
e.printStack();
}
android {
variantFilter { variant ->
if (variant.buildType.name.equals("release") && variant.flavors.get(0).name.equals("mock")) {
variant.setIgnore(true)
}
}
}
Log等级 Android log 等级在 android/log.h 中定义如下: typedef enum android_LogPriority { /** For internal use only. */ ANDROID_LOG_UNKNOWN =...