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