当前位置:网站首页>The elegant combination of walle and Jianbao
The elegant combination of walle and Jianbao
2022-06-30 09:02:00 【Silent Pinocchio】
Multi channel packaging scheme , Now it is basically divided into Flavors And meituan walle The plan .
At first, my personal choice was Flavors The plan , stay gradle Configuration of the flavors, But soon found the disadvantages , Packing is slow , Especially execution assemble Mission , The six channels have been compiled for about ten minutes , This is absolutely unacceptable . Then they began to adopt meituan's walle, Here's the address first :
Blog address :https://tech.meituan.com/2017/01/13/android-apk-v2-signature-scheme.html
Github:https://github.com/Meituan-Dianping/walle
The principle of meituan's multi-channel packaging is also easy to understand :
Wally passed in Apk Medium
APK Signature Block
Add customized channel information to the block to generate channel package , Thus, the generation efficiency of channel package is improved ,
Walle The configuration and use of are also very simple , No more introduction here , Please see the official document for details .
After multi-channel packaging , How to reinforce is still a problem , My reinforcement scheme adopts 360 Reinforcement scheme of reinforcement treasure , Reinforce one by one , It makes me feel like a waste of time , too troublesome , It's also true, a little low.
My initial idea was to pass a task Mission , To rely on walle Of assembleReleaseChannels Mission , Then traverse the multi-channel output path to traverse the multi-channel apk, For traversal reinforcement . Then it is found through practice , This scheme is not feasible , Reinforcement will report The following mistakes
Upload failed 10418 Submitted too often , Please try again later
Because the channel information is written in APK Signature Block
In block ,apk The other information is the same , Reinforcement will also report the error of repeatedly submitting the same documents .
Upload failed 10419 The same documents are submitted frequently , Please try again later
besides , The reinforcement process can not avoid every apk All the upload , strengthening , download , The process of signing .
In addition to the problem of reinforcement , There will also be a serious problem , After re signing , The channel information fails . On this question , stay walle Of github It also explains this problem :
Wiki:https://github.com/Meituan-Dianping/walle/wiki/360 Reinforcement failure ?
stay Wiki in There are also great gods who have given solutions , But need Python Environmental Science , Forgive me for being a little lazy , This process makes me feel a little cumbersome .
This is not the optimal solution I want , So I found another way .
In the use of Walle In the process I found :
stay assembleReleaseChannels Mission It will be executed before execution assembleRelease Mission , This means that assembleReleaseChannels It depends on assembleRelease The task to perform ,assembleRelease The task will be outputs Build... Under the directory release package , then walle I'm using this apk To write multi-channel , that , Can we be in this primitive release apk Do something , take Multi channel packaging -> strengthening Process of Turn into strengthening -> Multi channel packaging . In this way, only the original apk Reinforce once , Then write the channel information , This greatly shortens the time of reinforcement , most important of all , Reinforce first , Write channel information after reinforcement , In this way, the channel information will not be covered .
The multi-channel packaging function is mainly composed of walle Plugins complete , So let's mainly look at this part of the process .
walle Project source code ,library moudle It is mainly open to users to read channel information , The concrete realization is in payload_reader in ,payload_writer moudle Its function is to write channel information ,walle-cli yes walle Command line program provided ,plugin It is the main plug-in of multi-channel packaging .
stay plugin in ,groovy Under the catalogue is The main implementation source code of the plug-in .
GradlePlugin It is the entrance of plug-in execution , Extension Mainly Gradle Configuration information ,ChannelMaker It's the main thing task Realization .
The realization of the plan , Mainly through modification Extension and ChannelMaker To achieve .
First look Extension
class Extension {
static final String DEFAULT_APK_FILE_NAME_TEMPLATE = '${appName}-${buildType}-${channel}.apk'
File apkOutputFolder
String apkFileNameFormat
File channelFile;
File configFile;
String variantConfigFileName;
......
}
Do these fields look familiar , you 're right , Just when we are gradle in To configure walle Information about
walle {
apkOutputFolder = new File("${project.buildDir}/outputs/channels")
apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}- ${buildTime}-${flavorName}.apk'
//configFile And channelFile There must be one between the two , Otherwise, the channel package cannot be generated . When both exist, priority should be given to configFile
channelFile = new File("${project.getProjectDir()}/channel")
//configFile = new File("${project.getProjectDir()}/config.json")
}
We pass through here , You can configure the information of the reinforcement treasure
class Extension {
static final String DEFAULT_APK_FILE_NAME_TEMPLATE = '${appName}-${buildType}-${channel}.apk'
File apkOutputFolder
String apkFileNameFormat
File channelFile;
File configFile;
String variantConfigFileName;
// Reinforcement treasure jar route
String jiaguPath
// Reinforcement treasure user name
String jiaguUser
// Reinforcement treasure password
String jiaguPwd
}
And then the corresponding , We can do that gradle The corresponding configuration is carried out in
walle {
// Specify the output path of the channel package
apkOutputFolder = new File("${project.buildDir}/outputs/channels");
// Customized channel package APK File name for
apkFileNameFormat = '${appName}-${channel}-${buildType}-v${versionName}-${buildTime}.apk';
// Channel profile
channelFile = new File("${project.getProjectDir()}/channel")
jiaguPath ="/Users/wyl/Downloads/360jiagubao_mac/jiagu/jiagu.jar"
jiaguUser ="182xxxxx10"
jiaguPwd ="xixxxa1"
}
Then we'll see ChannelMaker
Here's the main thing packaging Method .
Extension extension = Extension.getConfig(targetProject);
This is what we got at gradle Information in configuration .
def iterator = variant.outputs.iterator();
while (iterator.hasNext()) {
def it = iterator.next();
def apkFile = it.outputFile
def apiIdentifier = null;
if (!it.outputs[0].filters.isEmpty()) {
def tempIterator = it.outputs[0].filters.iterator();
while (tempIterator.hasNext()) {
FilterData filterData = tempIterator.next();
if (filterData.filterType == "ABI") {
apiIdentifier = filterData.identifier
break;
}
}
}
if (apkFile == null || !apkFile.exists()) {
throw new GradleException("${apkFile} is not existed!");
}
}
Here is the result of traversing the build apk, Then on apk Conduct space judgment verification .
In fact, we know here , That's enough , Because the follow-up multi-channel , The channel number is written based on this apk To operate , As long as we add a reinforced process here, we can meet our needs .
First, create a folder , To store our reinforced apk file
def appFilePath = project.getProjectDir().absolutePath + "/build/outputs/jiagu"
File appDoc = new File(appFilePath)
if (!appDoc.exists()) appDoc.mkdir()
The method to get the signature is GrdlePlugin in It has been given to , You can use it directly
SigningConfig getSigningConfig(BaseVariant variant) {
return variant.buildType.signingConfig == null ? variant.mergedFlavor.signingConfig : variant.buildType.signingConfig;
}
Then the reinforcement operation can be carried out
if (extension.jiaguPath != null && extension.jiaguUser != null && extension.jiaguPwd != null) {
project.exec {
it.commandLine("java", "-jar", extension.jiaguPath, "-login", extension.jiaguUser, extension.jiaguPwd)
}
project.exec {
it.commandLine("java", "-jar", extension.jiaguPath, "-importsign", signingConfig.storeFile, signingConfig.storePassword, signingConfig.keyAlias, signingConfig.keyPassword)
}
def iterator = variant.outputs.iterator();
while (iterator.hasNext()) {
def it = iterator.next();
def apkFile = it.outputFile
project.exec {
it.commandLine("java", "-jar", extension.jiaguPath, "-jiagu", apkFile, appFilePath, "-autosign")
}
}
}
Then by traversing through the folder apk file , We can reinforce our apk Multi channel .
File[] files = appDoc.listFiles()
for (i in 0..<files.size()) {
File apkFile = files[i]
if (apkFile == null || !apkFile.exists()) {
throw new GradleException("${apkFile} is not existed!");
}
checkV2Signature(apkFile)
.......
}
The subsequent process is the same as the original process .
I'm through maven plug-in unit Publish the plug-in locally To test
In the plug-in directory build.gradle The dependence maven plug-in unit
apply plugin: 'maven'
Then configure the publishing information :
group = 'com.xl.channel-plugin'
version = "1.0.0"
// Package and upload to local
uploadArchives {
repositories {
flatDir {
dirs '../repo/'
}
}
}
Click this task , Publish plug-ins .
At the root gradle in Introduce warehouse address and plug-in
repositories {
google()
mavenCentral()
flatDir {
dirs './repo/'
}
}
classpath 'com.xl.channel-plugin:channel_plugin:1.0.0'
//app Of build.gradle in
apply plugin: 'xl-channel'
Then on walle To configure
walle {
// Specify the output path of the channel package
apkOutputFolder = new File("${project.buildDir}/outputs/channels");
// Customized channel package APK File name for
apkFileNameFormat = '${appName}-${channel}-${buildType}-v${versionName}-${buildTime}.apk';
// Channel profile
channelFile = new File("${project.getProjectDir()}/channel")
jiaguPath ="/Users/wyl/Downloads/360jiagubao_mac/jiagu/jiagu.jar"
jiaguUser ="182xxlxlxl10"
jiaguPwd ="xixixixi"
}
Then execute this task Let's test our results
Last in build/outputs Under the table of contents , One or two folders will be generated ,jiagu and channles .jiagu Stored reinforced apk,channels The storage is multi-channel apk.
thus , This plan is completed by standing on the shoulders of giants , Thanks to meituan walle.
Code address :https://github.com/WngYilei/ChannelReinforce
If you have any questions, please leave a message to discuss .
边栏推荐
- 100 lines of code and a voice conversation assistant
- Interpretation of orientedrcnn papers
- Duplicate entry '2' for key 'primary appears in JPA‘
- Be careful of this hole in transmittable thread local
- Detectron2 source code reading 3-- encapsulating dataset with mapper
- Axure make menu bar effect
- How can we get a satisfactory salary? These routines still need to be mastered
- 127.0.0.1、0.0.0.0和localhost
- Flink Exception -- No ExecutorFactory found to execute the application
- C # get the current timestamp
猜你喜欢
Esp32 things (3): overview of the overall system design
Axure make menu bar effect
A troubleshooting of CPU bottom falling
Using appbarlayout to realize secondary ceiling function
维基媒体基金会公布新商业产品“维基媒体企业”首批客户
Concatapter tutorial
Wechat development tool (applet)
Based on svelte3 X desktop UI component library svelte UI
Advanced technology management -- how managers design and build echelons
asdsadadsad
随机推荐
Metasploit practice - SSH brute force cracking process
TiDB 6.0:让 TSO 更高效丨TiDB Book Rush
El input limit can only input numbers
Redis design and Implementation (III) | interaction between server and client (event IO model)
CUDA realizes matrix multiplication
Flink SQL custom connector
Is it safe to open an account? How can anyone say that it is not reliable.
A troubleshooting of CPU bottom falling
[cmake] make command cannot be executed normally
Pytorch BERT
Opencv learning notes-day6-7 (scroll bar operation demonstration is used to adjust image brightness and contrast, and createtrackbar() creates a scroll bar function)
C#訪問SQL Server數據庫兩種方式的比較(SqlDataReader vs SqlDataAdapter)
Occasionally, Flink data is overstocked, resulting in checkpoint failure
Vite project require syntax compatibility problem solving require is not defined
Mmdet line by line code interpretation of positive and negative sample sampler
Opencv learning notes -day8 (keyboard typing (waitkey()); Wait for typing) action: triggers some action when the appropriate character is typed using the keyboard)
Comparaison de deux façons d'accéder à la base de données SQL Server (sqldatareader vs sqldataadapter)
Flink Sql -- toAppendStream doesn‘t support consuming update and delete changes which
Opencv learning notes -day1 (image reading display imread, imshow, namedwindow)
127.0.0.1, 0.0.0.0 and localhost