In project development, with the growth of business, it is often necessary to make some custom modifications to package code or resources during apK compilation, such as hot fix, plug-in generation, non-buried point statistics, channel package generation and so on.
But the company project business developers are basically rarely exposed to the relevant technology, here to learn the attitude, to implement a set of 7ZIP compression apK resource file Gradle plug-in.
APK thin combat resources custom 7Z compression
APK slim in the industry has a lot of mature open source technology to reflect the solution, such as Meituan Android App package slim optimization practice in detail in this blog. Here we start from resource compression, using 7z tools, to achieve a set of their own resource compression Gradle plug-in.
A brief introduction to Gradle plug-ins
Generally, simple logic can be written in a build.gradle file, but for ease of management and reuse, the plug-in can be isolated as a project. After compiling the independent Gradle plugin, we can publish it to the local Maven repository or jCenter for reference by other projects.
Introduction to project Structure
Gradle plug-ins can be developed using Android Studio or IntelliJ. AS development requires you to create your own plug-in project structure, while IntelliJ can automatically generate the project structure, but some operations are not easy to use.
As shown in the figure below, we use IntelliJ New to create a project and boot it to generate our initial project structure and gradle-wrapper.
The standard project structure is as follows:
If you are developing with as, you need to create the above structure manually. As you can see from the project, it supports both Groovy and Java, and of course from IntelliJ creating the project boot, it also supports Kotlin. Each language has its own language characteristics. For example, we develop Gradle plug-in, develop in Groovy where we interact with project build and compile, and develop the core code of business in the language we are good at (Java). Here, we use 7zip to implement with Java encapsulation.
The resources folder is important because the files in this folder indicate the entry to the plug-in and the name of the plug-in reference. If you export the Maven library and cannot find your own plug-in reference, you can first check that the file structure is correct.
apk-shrink.properties
implementation-class=win.canking.gradle.ShrinkPlugin
Copy the code
Apply the plugin 'apk - the shrinkCopy the code
When build. Gradle parsing the apply plugin, will find win. Canking. Gradle. ShrinkPlugin, start executing the apply * * * * method ()
Possible problems with the project
1, publish local Maven, build. Gradle configuration as follows
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'maven'
group 'win.canking.gradle'
version '1.0.1'
archivesBaseName = 'apk-shrink'//ArtifactId defaults to project module name compileGroovy {sourceCompatibility = 1.7
targetCompatibility = 1.7
options.encoding = "UTF-8"
}
dependencies {
compile gradleApi()
compile localGroovy()
compile 'com. Android. Tools. Build: gradle: 2.1.0'} uploadArchives {repositories. The mavenDeployer {/ / documents released to the following directory repository (url: uri ('.. /.. /ChargeHelperPro/gradleplugin/'))}}Copy the code
Execute the following code to generate a local Maven library
gradlew -p {module name} clean build uploadArchives --info
Copy the code
2, different JDK compilation issues, pay special attention, need to configure sourceCompatibility
Check the export directory to see if maven has been generated. The directory structure is as follows:
Decompile the generated JAR package to see if the packaging is correct.
APK User-defined resource compression
APK package structure
An APK file is essentially a ZIP file that can be decompressed using a decompression tool to see the internal structure.
name | desp |
---|---|
res | Resource file, where the resources are mapped to the project R file, generating the reference ID |
assets | Static resource files are accessed using AssetManager |
lib | Third package JAR or native SO library |
META-INF | Signature information, cert.rsa cert.sf manifrst.mf |
AndroidManifest | Project manifest file, including four components, package information, permissions, etc |
classes.dex | Java class file is an Android execution file generated by the DX tool |
resources.arsc | A compiled binary resource file that contains code references to resources |
Resource file compression
aapt l -v xxx.apk
Copy the code
It can be seen from the figure that some resource files in APK are stored and in an uncompressed state. We can reprocess APK and compress files with a tool of high compression ratio (7zip) to achieve the purpose of slim down.
Obtain the 7zip tool path
To obtain the 7zip tool directory on the PC, run “which 7za”
ProcessBuilder pb = new ProcessBuilder(new String[]{"which"."7za"});
String sevenZipPath = "";
try {
Process process = pb.start();
InputStreamReader ir = new InputStreamReader(process.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
String tmp;
while((tmp = input.readLine()) ! = null) {if (tmp.endsWith(File.separator + "7za")) {
sevenZipPath = tmp;
Log.a("Shrink"."7zip path:" + sevenZipPath);
}
}
process.waitFor();
process.destroy();
} catch (Exception e) {
Log.e("Error"."no shrink" + e.getMessage());
return;
}
Copy the code
Define the type of file to compress:
public class CompressInfo {
public Set<String> compressFilesPattern;
private CompressInfo() {
this.compressFilesPattern = new HashSet<>();
}
public static CompressInfo init() {
CompressInfo info = new CompressInfo();
info.compressFilesPattern.add(".png");
info.compressFilesPattern.add(".jpg");
info.compressFilesPattern.add(".JPG");
info.compressFilesPattern.add(".jpeg");
info.compressFilesPattern.add(".gif");
info.compressFilesPattern.add(".arsc");
returninfo; }}Copy the code
Call 7za to compress the object file
private static void do7zip(String srcDirPath, String outZipPath, String sevenZipPath)
throws IOException, InterruptedException {
String srcFilesPath = new File(srcDirPath).getAbsolutePath() + File.separator + "*";
outZipPath = new File(outZipPath).getAbsolutePath();
ProcessBuilder pb = new ProcessBuilder(new String[]{sevenZipPath, "a"."-tzip", outZipPath, srcFilesPath, "-mx9"});
Process process = pb.start();
InputStreamReader ir = new InputStreamReader(process.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
String line;
while((line = input.readLine()) ! = null) { Log.d(input.getLineNumber() +":" + line);
}
process.waitFor();
process.destroy();
}
Copy the code
Specify task to perform the compression task
@Override
void apply(Project project) {
Log.d("shrink apply")
if (project.getPlugins().hasPlugin(AppPlugin)) {
def config = project.extensions.create(SHRINK_CONFIG, ShrinkExtension)
project.afterEvaluate {
project.tasks.matching {
println it.name
it.name.startsWith('packageRelease')
} each {
t ->
t.doLast {
if (config.enable) {
Log.d("shrink start...")
GradleMrg.do7zipCompressApk(config.apkPath)
Log.d("shrink EDN")}}}}}}Copy the code
Note: This Demo depends on the compilation process of the project, so you need to configure related compression parameters in your own project build.gradle:
shrinkConfig {
enable = true
apkPath = '/PATH/App-release.apk'// Can be automatically obtained by the code method}Copy the code
You can also customize a separate task that does not depend on the compile process.
Compression effect comparison:
This case source code to submit to GitHub, welcome to exchange learning and star.
Welcome to reprint, please indicate the source: Changxing E station Canking.win