use super::aapt2_tool;
use crate::error::{CommandExt, Error, Result};
use std::path::{Path, PathBuf};
#[derive(Debug, Default)]
pub struct Aapt2Link {
inputs: Vec<PathBuf>,
compiled_res: Option<PathBuf>,
output_apk: PathBuf,
manifest: PathBuf,
android_jar: Option<PathBuf>,
assets: Option<PathBuf>,
individual_flat: Option<PathBuf>,
package_id: Option<String>,
allow_reserved_package_id: bool,
java: Option<PathBuf>,
proguard_options: Option<PathBuf>,
proguard_main_dex: Option<PathBuf>,
proguard_conditional_keep_rules: bool,
proguard_minimal_keep_rules: bool,
no_auto_version: bool,
no_version_vectors: bool,
no_version_transitions: bool,
no_resource_deduping: bool,
no_resource_removal: bool,
enable_sparse_encoding: bool,
package_identifier: bool,
suggested_strings: bool,
config: Vec<String>,
preferred_density: Option<i32>,
product: Option<PathBuf>,
output_to_dir: Option<PathBuf>,
no_xml_namespaces: bool,
min_sdk_version: Option<u32>,
target_sdk_version: Option<u32>,
version_code: Option<u32>,
version_code_major: Option<u32>,
version_name: Option<String>,
replace_version: bool,
compile_sdk_version_code: Option<u32>,
compile_sdk_version_name: Option<String>,
shared_lib: bool,
static_lib: bool,
proto_format: bool,
no_static_lib_packages: bool,
non_final_ids: bool,
no_proguard_location_reference: bool,
emit_ids: Option<PathBuf>,
stable_ids: Option<PathBuf>,
private_symbols: Option<String>,
custom_package: Option<PathBuf>,
extra_packages: Option<PathBuf>,
add_javadoc_annotation: Option<String>,
output_text_symbols: Option<PathBuf>,
auto_add_overlay: bool,
override_styles_instead_of_overlaying: bool,
rename_manifest_package: Option<String>,
rename_resources_package: Option<String>,
rename_instrumentation_target_package: Option<String>,
extensions: Vec<String>,
no_compress: bool,
keep_raw_values: bool,
no_compress_regex: Option<String>,
warn_manifest_validation: bool,
split: Option<PathBuf>,
strict_visibility: bool,
exclude_sources: bool,
trace_folder: Option<String>,
merge_only: bool,
verbose: bool,
help: bool,
}
impl Aapt2Link {
pub fn new(inputs: &[PathBuf], output_apk: &Path, manifest: &Path) -> Self {
Self {
inputs: inputs.to_vec(),
compiled_res: None,
output_apk: output_apk.to_owned(),
manifest: manifest.to_owned(),
..Default::default()
}
}
pub fn new_from_compiled_res(
compiled_res: Option<PathBuf>,
output_apk: &Path,
manifest: &Path,
) -> Self {
Self {
inputs: Vec::new(),
compiled_res,
output_apk: output_apk.to_owned(),
manifest: manifest.to_owned(),
..Default::default()
}
}
pub fn proguard_main_dex(&mut self, proguard_main_dex: PathBuf) -> &mut Self {
self.proguard_main_dex = Some(proguard_main_dex);
self
}
pub fn proguard_minimal_keep_rules(&mut self, proguard_minimal_keep_rules: bool) -> &mut Self {
self.proguard_minimal_keep_rules = proguard_minimal_keep_rules;
self
}
pub fn no_resource_removal(&mut self, no_resource_removal: bool) -> &mut Self {
self.no_resource_removal = no_resource_removal;
self
}
pub fn package_identifier(&mut self, package_identifier: bool) -> &mut Self {
self.package_identifier = package_identifier;
self
}
pub fn product(&mut self, product: PathBuf) -> &mut Self {
self.product = Some(product);
self
}
pub fn no_xml_namespaces(&mut self, no_xml_namespaces: bool) -> &mut Self {
self.no_xml_namespaces = no_xml_namespaces;
self
}
pub fn version_code_major(&mut self, version_code_major: u32) -> &mut Self {
self.version_code_major = Some(version_code_major);
self
}
pub fn version_name(&mut self, version_name: String) -> &mut Self {
self.version_name = Some(version_name);
self
}
pub fn replace_version(&mut self, replace_version: bool) -> &mut Self {
self.replace_version = replace_version;
self
}
pub fn compile_sdk_version_code(&mut self, compile_sdk_version_code: u32) -> &mut Self {
self.compile_sdk_version_code = Some(compile_sdk_version_code);
self
}
pub fn shared_lib(&mut self, shared_lib: bool) -> &mut Self {
self.shared_lib = shared_lib;
self
}
pub fn static_lib(&mut self, static_lib: bool) -> &mut Self {
self.static_lib = static_lib;
self
}
pub fn no_static_lib_packages(&mut self, no_static_lib_packages: bool) -> &mut Self {
self.no_static_lib_packages = no_static_lib_packages;
self
}
pub fn no_proguard_location_reference(
&mut self,
no_proguard_location_reference: bool,
) -> &mut Self {
self.no_proguard_location_reference = no_proguard_location_reference;
self
}
pub fn private_symbols(&mut self, private_symbols: String) -> &mut Self {
self.private_symbols = Some(private_symbols);
self
}
pub fn override_styles_instead_of_overlaying(
&mut self,
override_styles_instead_of_overlaying: bool,
) -> &mut Self {
self.override_styles_instead_of_overlaying = override_styles_instead_of_overlaying;
self
}
pub fn rename_resources_package(&mut self, rename_resources_package: String) -> &mut Self {
self.rename_resources_package = Some(rename_resources_package);
self
}
pub fn android_jar(&mut self, android_jar: PathBuf) -> &mut Self {
self.android_jar = Some(android_jar);
self
}
pub fn assets(&mut self, assets: PathBuf) -> &mut Self {
self.assets = Some(assets);
self
}
pub fn individual_flat(&mut self, individual_flat: PathBuf) -> &mut Self {
self.individual_flat = Some(individual_flat);
self
}
pub fn package_id(&mut self, package_id: String) -> &mut Self {
self.package_id = Some(package_id);
self
}
pub fn allow_reserved_package_id(&mut self, allow_reserved_package_id: bool) -> &mut Self {
self.allow_reserved_package_id = allow_reserved_package_id;
self
}
pub fn java(&mut self, java: PathBuf) -> &mut Self {
self.java = Some(java);
self
}
pub fn proguard_options(&mut self, proguard_options: PathBuf) -> &mut Self {
self.proguard_options = Some(proguard_options);
self
}
pub fn proguard_conditional_keep_rules(
&mut self,
proguard_conditional_keep_rules: bool,
) -> &mut Self {
self.proguard_conditional_keep_rules = proguard_conditional_keep_rules;
self
}
pub fn no_auto_version(&mut self, no_auto_version: bool) -> &mut Self {
self.no_auto_version = no_auto_version;
self
}
pub fn no_version_vectors(&mut self, no_version_vectors: bool) -> &mut Self {
self.no_version_vectors = no_version_vectors;
self
}
pub fn no_version_transitions(&mut self, no_version_transitions: bool) -> &mut Self {
self.no_version_transitions = no_version_transitions;
self
}
pub fn no_resource_deduping(&mut self, no_resource_deduping: bool) -> &mut Self {
self.no_resource_deduping = no_resource_deduping;
self
}
pub fn enable_sparse_encoding(&mut self, enable_sparse_encoding: bool) -> &mut Self {
self.enable_sparse_encoding = enable_sparse_encoding;
self
}
pub fn suggested_strings(&mut self, suggested_strings: bool) -> &mut Self {
self.suggested_strings = suggested_strings;
self
}
pub fn config(&mut self, config: String) -> &mut Self {
self.config.push(config);
self
}
pub fn preferred_density(&mut self, preferred_density: i32) -> &mut Self {
self.preferred_density = Some(preferred_density);
self
}
pub fn output_to_dir(&mut self, output_to_dir: &Path) -> &mut Self {
self.output_to_dir = Some(output_to_dir.to_path_buf());
self
}
pub fn min_sdk_version(&mut self, min_sdk_version: u32) -> &mut Self {
self.min_sdk_version = Some(min_sdk_version);
self
}
pub fn target_sdk_version(&mut self, target_sdk_version: u32) -> &mut Self {
self.target_sdk_version = Some(target_sdk_version);
self
}
pub fn version_code(&mut self, version_code: u32) -> &mut Self {
self.version_code = Some(version_code);
self
}
pub fn compile_sdk_version_name(&mut self, compile_sdk_version_name: String) -> &mut Self {
self.compile_sdk_version_name = Some(compile_sdk_version_name);
self
}
pub fn proto_format(&mut self, proto_format: bool) -> &mut Self {
self.proto_format = proto_format;
self
}
pub fn non_final_ids(&mut self, non_final_ids: bool) -> &mut Self {
self.non_final_ids = non_final_ids;
self
}
pub fn emit_ids(&mut self, emit_ids: PathBuf) -> &mut Self {
self.emit_ids = Some(emit_ids);
self
}
pub fn stable_ids(&mut self, stable_ids: PathBuf) -> &mut Self {
self.stable_ids = Some(stable_ids);
self
}
pub fn custom_package(&mut self, custom_package: PathBuf) -> &mut Self {
self.custom_package = Some(custom_package);
self
}
pub fn extra_packages(&mut self, extra_packages: PathBuf) -> &mut Self {
self.extra_packages = Some(extra_packages);
self
}
pub fn add_javadoc_annotation(&mut self, add_javadoc_annotation: String) -> &mut Self {
self.add_javadoc_annotation = Some(add_javadoc_annotation);
self
}
pub fn output_text_symbols(&mut self, output_text_symbols: PathBuf) -> &mut Self {
self.output_text_symbols = Some(output_text_symbols);
self
}
pub fn auto_add_overlay(&mut self, auto_add_overlay: bool) -> &mut Self {
self.auto_add_overlay = auto_add_overlay;
self
}
pub fn rename_manifest_package(&mut self, rename_manifest_package: String) -> &mut Self {
self.rename_manifest_package = Some(rename_manifest_package);
self
}
pub fn rename_instrumentation_target_package(
&mut self,
rename_instrumentation_target_package: String,
) -> &mut Self {
self.rename_instrumentation_target_package = Some(rename_instrumentation_target_package);
self
}
pub fn no_compress(&mut self, no_compress: bool) -> &mut Self {
self.no_compress = no_compress;
self
}
pub fn keep_raw_values(&mut self, keep_raw_values: bool) -> &mut Self {
self.keep_raw_values = keep_raw_values;
self
}
pub fn extension(&mut self, extension: String) -> &mut Self {
self.extensions.push(extension);
self
}
pub fn no_compress_regex(&mut self, no_compress_regex: String) -> &mut Self {
self.no_compress_regex = Some(no_compress_regex);
self
}
pub fn warn_manifest_validation(&mut self, warn_manifest_validation: bool) -> &mut Self {
self.warn_manifest_validation = warn_manifest_validation;
self
}
pub fn split(&mut self, split: PathBuf) -> &mut Self {
self.split = Some(split);
self
}
pub fn strict_visibility(&mut self, strict_visibility: bool) -> &mut Self {
self.strict_visibility = strict_visibility;
self
}
pub fn trace_folder(&mut self, trace_folder: String) -> &mut Self {
self.trace_folder = Some(trace_folder);
self
}
pub fn exclude_sources(&mut self, exclude_sources: bool) -> &mut Self {
self.exclude_sources = exclude_sources;
self
}
pub fn merge_only(&mut self, merge_only: bool) -> &mut Self {
self.merge_only = merge_only;
self
}
pub fn verbose(&mut self, verbose: bool) -> &mut Self {
self.verbose = verbose;
self
}
pub fn help(&mut self, help: bool) -> &mut Self {
self.help = help;
self
}
pub fn run(&self) -> Result<PathBuf> {
let mut aapt2 = aapt2_tool()?;
aapt2.arg("link");
if !self.inputs.is_empty() {
self.inputs.iter().for_each(|input| {
aapt2.arg(input);
});
} else if let Some(compiled_res) = &self.compiled_res {
let paths = std::fs::read_dir(compiled_res)
.map_err(|_| Error::CompiledResourcesNotFound)?
.flat_map(|e| e.map(|x| x.path()))
.collect::<Vec<_>>();
paths.iter().for_each(|input| {
if !input.ends_with("AndroidManifest.xml") {
aapt2.arg(input);
}
});
}
aapt2.arg("-o").arg(&self.output_apk);
aapt2.arg("--manifest").arg(&self.manifest);
if let Some(android_jar) = &self.android_jar {
aapt2.arg("-I").arg(android_jar);
}
if let Some(assets) = &self.assets {
aapt2.arg("-A").arg(assets);
}
if let Some(individual_flat) = &self.individual_flat {
aapt2.arg("-R").arg(individual_flat);
}
if let Some(package_id) = &self.package_id {
aapt2.arg("--package-id").arg(package_id);
}
if self.allow_reserved_package_id {
aapt2.arg("--allow-reserved-package-id");
}
if let Some(java) = &self.java {
aapt2.arg("--java").arg(java);
}
if let Some(proguard_options) = &self.proguard_options {
aapt2.arg("--proguard").arg(proguard_options);
}
if self.proguard_conditional_keep_rules {
aapt2.arg("--proguard-conditional-keep-rules");
}
if self.no_auto_version {
aapt2.arg("--no-auto-version");
}
if self.no_version_vectors {
aapt2.arg("--no-version-vectors");
}
if self.no_version_transitions {
aapt2.arg("--no-version-transitions");
}
if self.no_resource_deduping {
aapt2.arg("--no-resource-deduping");
}
if self.enable_sparse_encoding {
aapt2.arg("--enable-sparse-encoding");
}
if self.suggested_strings {
aapt2.arg("-z");
}
if !self.config.is_empty() {
aapt2.arg("-c").arg(self.config.join(","));
}
if let Some(preferred_density) = self.preferred_density {
aapt2
.arg("--preferred-density")
.arg(preferred_density.to_string());
}
if let Some(output_to_dir) = &self.output_to_dir {
aapt2.arg("--output-to-dir").arg("-o").arg(output_to_dir);
}
if let Some(min_sdk_version) = self.min_sdk_version {
aapt2
.arg("--min-sdk-version")
.arg(min_sdk_version.to_string());
}
if let Some(target_sdk_version) = self.target_sdk_version {
aapt2
.arg("--target-sdk-version")
.arg(target_sdk_version.to_string());
}
if let Some(version_code) = &self.version_code {
aapt2.arg("--version-code").arg(version_code.to_string());
}
if let Some(compile_sdk_version_name) = &self.compile_sdk_version_name {
aapt2
.arg("--compile-sdk-version-name")
.arg(compile_sdk_version_name);
}
if self.proto_format {
aapt2.arg("--proto-format");
}
if self.non_final_ids {
aapt2.arg("--non-final-ids");
}
if let Some(emit_ids) = &self.emit_ids {
aapt2.arg("--emit-ids").arg(emit_ids);
}
if let Some(stable_ids) = &self.stable_ids {
aapt2.arg("--stable-ids").arg(stable_ids);
}
if let Some(custom_package) = &self.custom_package {
aapt2.arg("--custom-package").arg(custom_package);
}
if let Some(extra_packages) = &self.extra_packages {
aapt2.arg("--extra-packages").arg(extra_packages);
}
if let Some(add_javadoc_annotation) = &self.add_javadoc_annotation {
aapt2
.arg("--add-javadoc-annotation")
.arg(add_javadoc_annotation);
}
if let Some(output_text_symbols) = &self.output_text_symbols {
aapt2.arg("--output-text-symbols").arg(output_text_symbols);
}
if self.auto_add_overlay {
aapt2.arg("--auto-add-overlay");
}
if let Some(rename_manifest_package) = &self.rename_manifest_package {
aapt2
.arg("--rename-manifest-package")
.arg(rename_manifest_package);
}
if let Some(rename_instrumentation_target_package) =
&self.rename_instrumentation_target_package
{
aapt2
.arg("--rename-instrumentation-target-package")
.arg(rename_instrumentation_target_package);
}
self.extensions.iter().for_each(|extension| {
aapt2.arg("-0").arg(extension);
});
if let Some(split) = &self.split {
aapt2.arg("--split").arg(split);
}
if self.verbose {
aapt2.arg("-v");
}
if self.help {
aapt2.arg("-h");
}
if let Some(proguard_main_dex) = &self.proguard_main_dex {
aapt2.arg("--proguard-main-dex").arg(proguard_main_dex);
}
if self.proguard_minimal_keep_rules {
aapt2.arg("--proguard-minimal-keep-rules");
}
if self.no_resource_removal {
aapt2.arg("--no-resource-removal");
}
if self.package_identifier {
aapt2.arg("-x");
}
if let Some(product) = &self.product {
aapt2.arg("--product").arg(product);
}
if self.no_xml_namespaces {
aapt2.arg("--no-xml-namespaces");
}
if let Some(version_code_major) = &self.version_code_major {
aapt2
.arg("--version-code-major")
.arg(version_code_major.to_string());
}
if let Some(version_name) = &self.version_name {
aapt2.arg("--version-name").arg(version_name);
}
if self.replace_version {
aapt2.arg("--replace-version");
}
if let Some(compile_sdk_version_code) = &self.compile_sdk_version_code {
aapt2
.arg("--compile-sdk-version-code")
.arg(compile_sdk_version_code.to_string());
}
if self.shared_lib {
aapt2.arg("--shared-lib");
}
if self.static_lib {
aapt2.arg("--static-lib");
}
if self.no_static_lib_packages {
aapt2.arg("--no-static-lib-packages");
}
if self.no_proguard_location_reference {
aapt2.arg("--no-proguard-location-reference");
}
if let Some(private_symbols) = &self.private_symbols {
aapt2.arg("--private-symbols").arg(private_symbols);
}
if self.override_styles_instead_of_overlaying {
aapt2.arg("--override-styles-instead-of-overlaying");
}
if let Some(rename_resources_package) = &self.rename_resources_package {
aapt2
.arg("--rename-resources-package")
.arg(rename_resources_package);
}
if self.no_compress {
aapt2.arg("--no-compress");
}
if self.keep_raw_values {
aapt2.arg("--keep-raw-values");
}
if let Some(no_compress_regex) = &self.no_compress_regex {
aapt2.arg("--no-compress-regex").arg(no_compress_regex);
}
if self.warn_manifest_validation {
aapt2.arg("--warn-manifest-validation");
}
if self.strict_visibility {
aapt2.arg("--strict-visibility");
}
if self.exclude_sources {
aapt2.arg("--exclude-sources");
}
if let Some(trace_folder) = &self.trace_folder {
aapt2.arg("--trace-folder").arg(trace_folder);
}
if self.merge_only {
aapt2.arg("--merge-only");
}
aapt2.output_err(true)?;
Ok(self.output_apk.clone())
}
}