android_tools/bundletool/
mod.rs

1mod build_apks;
2mod build_bundle;
3mod extract_apks;
4mod get_device_spec;
5mod get_size_total;
6mod install_apks;
7
8pub use build_apks::*;
9pub use build_bundle::*;
10pub use extract_apks::*;
11pub use get_device_spec::*;
12pub use get_size_total::*;
13pub use install_apks::*;
14
15use crate::{bundletool, error::*};
16use std::{
17    path::{Path, PathBuf},
18    process::Command,
19};
20
21const BUNDLETOOL_VERSION: &str = "1.8.2";
22
23/// ## Bundletool
24/// `bundletool` is the underlying tool that Android Studio, the Android Gradle plugin,
25/// and Google Play use to build an Android App Bundle, and convert an app bundle into
26/// the various APKs that are deployed to devices. `Bundletool` is also available to you
27/// as a command line tool, so you can build app bundles yourself and recreate
28/// Google Play's server-side build of your app's APKs.
29///
30///
31/// ## Download bundletool
32/// If you haven't already done so, download bundletool from the [`GitHub repository`].
33///
34///
35/// ## Install bundletool
36/// In variable environments needs to create new variable `BUNDLETOOL_PATH` and add
37/// path to the `bundletool`
38///
39/// [`GitHub repository`](https://github.com/google/bundletool/releases)
40#[derive(Clone, Copy)]
41pub struct Bundletool;
42
43impl Bundletool {
44    /// Generate an APK set for all device configurations your app supports from your app
45    /// bundle
46    pub fn build_apks(self, bundle: &Path, output: &Path) -> BuildApks {
47        BuildApks::new(bundle, output)
48    }
49
50    /// Generate AAB file from generated zip modules to specified path.
51    /// Notice, that zip module must contents files in protobuf format
52    pub fn build_bundle(self, modules: &[PathBuf], output: &Path) -> BuildBundle {
53        BuildBundle::new(modules, output)
54    }
55
56    /// To measure the estimated download sizes of APKs in an APK set as they would be
57    /// served compressed over-the-wire, use the get-size total
58    pub fn get_size_total(self, apks: &Path) -> GetSizeTotal {
59        GetSizeTotal::new(apks)
60    }
61
62    /// Extract device-specific APKs from an existing APK set
63    /// If you have an existing APK set and you want to extract from it a subset of APKs
64    /// that target a specific device configuration, you can use the extract-apks
65    /// command and specify a device specification JSON
66    pub fn extract_apks(self, apks: &Path, output_dir: &Path, device_spec: &Path) -> ExtractApks {
67        ExtractApks::new(apks, output_dir, device_spec)
68    }
69
70    /// Use the install-apks command and specify the path of the APK set to deploy your
71    /// app from an APK set
72    pub fn install_apks(self, apks: PathBuf) -> InstallApks {
73        InstallApks::new(&apks)
74    }
75
76    /// Generate and use device specification JSON files.
77    /// Bundletool is capable of generating an APK set that targets a device configuration
78    /// specified by a JSON file. To first generate a JSON file for a connected
79    /// device, run the command
80    pub fn get_device_spec(self, output: &Path) -> GetDeviceSpec {
81        GetDeviceSpec::new(output)
82    }
83}
84
85/// Find `bundletool` jar file in home directory then set environment variable and initialize it
86pub fn bundletool() -> Result<Command> {
87    let mut bundletool_init = Command::new("java");
88    bundletool_init.arg("-jar");
89    if let Ok(bundletool_path) = std::env::var("BUNDLETOOL_PATH") {
90        bundletool_init.arg(bundletool_path);
91    } else {
92        let env_version =
93            std::env::var("BUNDLETOOL_VERSION").unwrap_or_else(|_| BUNDLETOOL_VERSION.to_string());
94        let bundletool_file = format!("bundletool-all-{}.jar", env_version);
95        let bundletool_file_path = dirs::home_dir()
96            .ok_or(Error::UnableToAccessHomeDirectory)?
97            .join(bundletool_file);
98        if bundletool_file_path.exists() {
99            bundletool_init.arg(bundletool_file_path);
100        } else {
101            return Err(Error::BundletoolNotFound);
102        }
103    }
104    Ok(bundletool_init)
105}