android_tools/aapt2/
optimize.rs

1use super::aapt2_tool;
2use crate::error::*;
3use std::path::{Path, PathBuf};
4
5/// Preforms resource optimizations on an APK
6#[derive(Clone, Default)]
7pub struct Aapt2Optimize {
8    output_apk: PathBuf,
9    output_dir: PathBuf,
10    config_xml_file: Option<PathBuf>,
11    apk_artifacts: bool,
12    target_densities: Option<String>,
13    resources_config_path: Option<PathBuf>,
14    configs_to_include: Option<String>,
15    split: Option<PathBuf>,
16    keep_artifacts: Option<String>,
17    enable_sparse_encoding: bool,
18    collapse_resource_name: bool,
19    shorten_resource_paths: bool,
20    resource_path_shortening_map: Option<PathBuf>,
21    verbose: bool,
22    help: bool,
23}
24
25impl Aapt2Optimize {
26    /// Initialize aapt2 optimize then specifies path to the aapt2 link output APK and
27    /// Path to the output directory (for splits)
28    pub fn new(output_apk: &Path, output_dir: &Path) -> Self {
29        Self {
30            output_apk: output_apk.to_owned(),
31            output_dir: output_dir.to_owned(),
32            ..Default::default()
33        }
34    }
35
36    /// Specifies path to XML configuration file
37    pub fn config_xml_file(&mut self, config_xml_file: &Path) -> &mut Self {
38        self.config_xml_file = Some(config_xml_file.to_owned());
39        self
40    }
41
42    /// Print the multi APK artifacts and exit
43    pub fn apk_artifacts(&mut self, apk_artifacts: bool) -> &mut Self {
44        self.apk_artifacts = apk_artifacts;
45        self
46    }
47
48    /// Comma separated list of the screen densities that the APK will be optimized for.
49    /// All the resources that would be unused on devices of the given densities will be
50    /// removed from the APK
51    pub fn target_densities(&mut self, target_densities: &str) -> &mut Self {
52        self.target_densities = Some(target_densities.to_owned());
53        self
54    }
55
56    /// Path to the `resources.cfg` file containing the list of resources and directives
57    /// to each resource. ```Format: type/resource_name#[directive][,directive]```
58    pub fn resources_config_path(&mut self, resources_config_path: &Path) -> &mut Self {
59        self.resources_config_path = Some(resources_config_path.to_owned());
60        self
61    }
62
63    /// Comma separated list of configurations to include. The default is all
64    /// configurations
65    pub fn configs_to_include(&mut self, configs_to_include: &str) -> &mut Self {
66        self.configs_to_include = Some(configs_to_include.to_owned());
67        self
68    }
69
70    /// Split resources matching a set of configs out to a Split APK.
71    /// Syntax:
72    /// ```sh
73    /// `path/to/output.apk;<config>[,<config>[...]].`
74    /// ```
75    /// On Windows, use a semicolon `;` separator instead
76    pub fn split(&mut self, split: &Path) -> &mut Self {
77        self.split = Some(split.to_owned());
78        self
79    }
80
81    /// Comma separated list of artifacts to keep.
82    /// If none are specified, all artifacts will be kept
83    pub fn keep_artifacts(&mut self, keep_artifacts: &str) -> &mut Self {
84        self.keep_artifacts = Some(keep_artifacts.to_owned());
85        self
86    }
87
88    /// Enables encoding sparse entries using a binary search tree. This decreases APK
89    /// size at the cost of resource retrieval performance
90    pub fn enable_sparse_encoding(&mut self, enable_sparse_encoding: bool) -> &mut Self {
91        self.enable_sparse_encoding = enable_sparse_encoding;
92        self
93    }
94
95    /// Collapses resource names to a single value in the key string pool.
96    /// Resources can be exempted using the `no_collapse` directive in a file specified by
97    /// `--resources-config-path`
98    pub fn collapse_resource_name(&mut self, collapse_resource_name: bool) -> &mut Self {
99        self.collapse_resource_name = collapse_resource_name;
100        self
101    }
102
103    /// Shortens the paths of resources inside the APK
104    pub fn shorten_resource_paths(&mut self, shorten_resource_paths: bool) -> &mut Self {
105        self.shorten_resource_paths = shorten_resource_paths;
106        self
107    }
108
109    /// Path to output the map of old resource paths to shortened paths
110    pub fn resource_path_shortening_map(
111        &mut self,
112        resource_path_shortening_map: &Path,
113    ) -> &mut Self {
114        self.resource_path_shortening_map = Some(resource_path_shortening_map.to_owned());
115        self
116    }
117
118    /// Enables verbose logging
119    pub fn verbose(&mut self, verbose: bool) -> &mut Self {
120        self.verbose = verbose;
121        self
122    }
123
124    /// Displays this help menu
125    pub fn help(&mut self, help: bool) -> &mut Self {
126        self.help = help;
127        self
128    }
129
130    /// Executes aapt2 optimize with arguments
131    pub fn run(self) -> Result<()> {
132        let mut aapt2 = aapt2_tool()?;
133        aapt2.arg("optimize");
134        aapt2.arg("-o").arg(&self.output_apk);
135        aapt2.arg("-d").arg(&self.output_dir);
136        if let Some(config_xml_file) = self.config_xml_file {
137            aapt2.arg("-x").arg(config_xml_file);
138        }
139        if self.apk_artifacts {
140            aapt2.arg("-p");
141        }
142        if let Some(target_densities) = self.target_densities {
143            aapt2.arg("--target_densities").arg(target_densities);
144        }
145        if let Some(resources_config_path) = self.resources_config_path {
146            aapt2
147                .arg("--resources_config_path")
148                .arg(resources_config_path);
149        }
150        if let Some(configs_to_include) = self.configs_to_include {
151            aapt2.arg("-c").arg(configs_to_include);
152        }
153        if let Some(split) = self.split {
154            aapt2.arg("--split").arg(split);
155        }
156        if let Some(keep_artifacts) = self.keep_artifacts {
157            aapt2.arg("--keep-artifacts").arg(keep_artifacts);
158        }
159        if self.enable_sparse_encoding {
160            aapt2.arg("--enable-sparse-encoding");
161        }
162        if self.collapse_resource_name {
163            aapt2.arg("--collapse-resource-name");
164        }
165        if self.shorten_resource_paths {
166            aapt2.arg("--shorten-resource-paths");
167        }
168        if let Some(resource_path_shortening_map) = self.resource_path_shortening_map {
169            aapt2
170                .arg("--resource-path-shortening-map")
171                .arg(resource_path_shortening_map);
172        }
173        if self.verbose {
174            aapt2.arg("-v");
175        }
176        if self.help {
177            aapt2.arg("-h");
178        }
179        aapt2.output_err(true)?;
180        Ok(())
181    }
182}