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}