android_tools_rs/bundletool/
build_bundle.rs

1use crate::error::*;
2use std::path::{Path, PathBuf};
3use std::process::Command;
4
5/// ## Build your app bundle using bundletool
6/// To build your app bundle, you use the bundletool build-bundle command, as shown below:
7///
8/// ```xml
9/// bundletool build-bundle --modules=base.zip --output=mybundle.aab
10/// ```
11///
12/// ## Note
13/// If you plan to publish the app bundle, you need to sign it using jarsigner. You can
14/// not use apksigner to sign your app bundle.
15#[derive(Debug, PartialEq, PartialOrd)]
16pub struct BuildBundle {
17    modules: Vec<PathBuf>,
18    output: PathBuf,
19    config: Option<PathBuf>,
20    metadata_file: Option<PathBuf>,
21}
22
23impl BuildBundle {
24    /// Specifies the list of module ZIP files bundletool should use to build your app
25    /// bundle.
26    ///
27    /// Specifies the path and filename for the output *.aab file.
28    pub fn new(modules: &[PathBuf], output: &Path) -> Self {
29        Self {
30            modules: modules.to_vec(),
31            output: output.to_owned(),
32            config: None,
33            metadata_file: None,
34        }
35    }
36
37    /// Specifies the path to an optional configuration file you can use to customize the
38    /// build process. To learn more, see the section about [`customizing downstream APK
39    /// generation`].
40    ///
41    /// [`customizing downstream APK generation`]::https://developer.android.com/studio/build/building-cmdline#bundleconfig
42    pub fn config(&mut self, config: &Path) -> &mut Self {
43        self.config = Some(config.to_owned());
44        self
45    }
46
47    /// Instructs bundletool to package an optional metadata file inside your app bundle.
48    /// You can use this file to include data, such as ProGuard mappings or the complete
49    /// list of your app's DEX files, that may be useful to other steps in your toolchain
50    /// or an app store.
51    ///
52    /// target-bundle-path specifies a path relative to the root of the app bundle where
53    /// you would like the metadata file to be packaged, and local-file-path specifies the
54    /// path to the local metadata file itself.
55    pub fn metadata_file(&mut self, metadata_file: &Path) -> &mut Self {
56        self.metadata_file = Some(metadata_file.to_owned());
57        self
58    }
59
60    pub fn run(&self) -> Result<()> {
61        let mut build_bundle = Command::new("java");
62        build_bundle.arg("-jar");
63        if let Ok(bundletool_path) = std::env::var("BUNDLETOOL_PATH") {
64            build_bundle.arg(bundletool_path);
65        } else {
66            return Err(Error::BundletoolNotFound);
67        }
68        build_bundle.arg("build-bundle");
69        build_bundle.arg("--modules");
70        build_bundle.arg(
71            self.modules
72                .iter()
73                .map(|v| v.to_string_lossy().to_string())
74                .collect::<Vec<String>>()
75                .join(","),
76        );
77        build_bundle.arg("--output").arg(&self.output);
78        if let Some(config) = &self.config {
79            build_bundle.arg("--config").arg(config);
80        }
81        if let Some(metadata_file) = &self.metadata_file {
82            build_bundle.arg("--metadata-file").arg(metadata_file);
83        }
84        build_bundle.output_err(true)?;
85        Ok(())
86    }
87}