### Install apkeep from the latest git commit Source: https://github.com/efforg/apkeep/blob/master/README.md Installs apkeep from the latest commit in the official repository. Useful for getting unreleased features. ```shell cargo install --git https://github.com/EFForg/apkeep.git ``` -------------------------------- ### Install apkeep from crates.io Source: https://github.com/efforg/apkeep/blob/master/README.md Installs the latest published version of apkeep from crates.io. Requires Rust to be installed first. ```shell cargo install apkeep ``` -------------------------------- ### apkeep download examples Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/apkpure.md Shows various apkeep commands for downloading an app: default source, specific architecture, multiple architectures, specific version, and listing versions as JSON. ```shell # Default source; download to current directory apkeep -a com.instagram.android . # Specific architecture variant apkeep -a com.instagram.android -o 'arch=x86' . # Multiple architectures (default equivalent) apkeep -a com.instagram.android -o 'arch=arm64-v8a;armeabi-v7a;armeabi;x86;x86_64' . # Specific version apkeep -a com.instagram.android@1.2.3 . # List versions as JSON apkeep -l -a com.instagram.android -o output_format=json ``` -------------------------------- ### apkeep usage examples for Huawei AppGallery Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/huawei-app-gallery.md Usage examples for downloading apps from Huawei AppGallery using apkeep. The first downloads a single app, the second processes multiple apps from a CSV with a concurrency of 2. Note that -o options are silently ignored for this source. ```shell # Basic download apkeep -a com.elysiumlabs.newsbytes -d huawei-app-gallery . # Multiple apps from a CSV, 2 at a time apkeep -c apps.csv -d huawei-app-gallery -r 2 . ``` -------------------------------- ### Usage example of constants in a module Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/consts.md Shows how the constants are consumed internally in a module, e.g., src/download_sources/fdroid.rs. Demonstrates accessing FDROID_REPO, FDROID_INDEX_FINGERPRINT, and FDROID_SIGNATURE_BLOCK_FILE_REGEX. ```rust // src/download_sources/fdroid.rs let repo = consts::FDROID_REPO.to_string(); let fingerprint = Vec::from(consts::FDROID_INDEX_FINGERPRINT); let re = Regex::new(consts::FDROID_SIGNATURE_BLOCK_FILE_REGEX).unwrap(); ``` -------------------------------- ### apkeep Google Play download examples Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/google-play.md These shell commands demonstrate various apkeep invocations for downloading apps from Google Play, including obtaining a long-lived AAS token from a single-use OAuth token, downloading with AAS or AUTH tokens, specifying device profile, locale, split APK, additional files, and a custom device properties file. The commands assume the apkeep binary is installed and credentials are provided. ```shell # Obtain a long-lived AAS token from a single-use OAuth token apkeep -e 'someone@gmail.com' --oauth-token oauth2_4/... # Download with an AAS token apkeep -a com.instagram.android -d google-play -e 'someone@gmail.com' -t some_aas_token . # Download with an AUTH token from a dispenser, auto-accepting ToS apkeep -a com.instagram.android -d google-play -e 'dispenser_email@gmail.com' --auth-token 'ya29.a0...' --accept-tos . # Device profile, locale, split APK and additional files apkeep -a com.instagram.android -d google-play -o device=ad_g3_pro,locale=es_MX,split_apk=true,include_additional_files=true -e 'someone@gmail.com' -t some_aas_token . # Custom device properties file (e.g. exported from Aurora Store) apkeep -a com.instagram.android -d google-play -o device=default,device_properties_file=/path/to/device.properties -e 'someone@gmail.com' -t some_aas_token . ``` -------------------------------- ### Typical apkeep invocations Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/cli.md Shows three common ways to use the apkeep executable: downloading a single app from the default source, specifying a source with per-source options, and listing versions instead of downloading. Use these as a starting point for typical CLI usage. ```shell # Default source (apk-pure), single app apkeep -a com.instagram.android . # Explicit source with per-source options apkeep -a org.mozilla.fennec_fdroid -d f-droid -o repo=https://cloudflare.f-droid.org/repo . # List versions instead of downloading apkeep -l -a org.mozilla.fennec_fdroid -d f-droid ``` -------------------------------- ### apkeep error handling example Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/apkpure.md Demonstrates that apkeep does not abort on per-app failures, printing an error message and skipping the app. ```shell $ apkeep -a com.nonexistent.example . Invalid app response for com.nonexistent.example. Skipping... ``` -------------------------------- ### Using progress_wrapper in google_play download (src/download_sources/google_play.rs) Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/util.md Example of passing the progress wrapper to a download call. The wrapper is used only when the download stream reports a known length. ```rust // src/download_sources/google_play.rs match gpa.download(&app_id, None, split_apk, include_dex_metadata, include_additional_files, Path::new(outpath), Some(&progress_wrapper(mp_dl1))).await { ``` -------------------------------- ### Download with multiple architecture variants from APKPure Source: https://github.com/efforg/apkeep/blob/master/USAGE-apkpure.md Downloads the app with package name com.instagram.android to the current directory, specifying multiple architectures separated by semicolons. This example shows the default arch option. ```shell apkeep -a com.instagram.android -o 'arch=arm64-v8a;armeabi-v7a;armeabi;x86;x86_64' . ``` -------------------------------- ### apkeep F-Droid usage examples Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/fdroid.md Shows common apkeep invocations for the F-Droid repository: simple download, custom repo with fingerprint and entry-point disabling, version and architecture selection, skipping index verification for debugging, and JSON version listing. ```shell # Simple download from the default F-Droid repo apkeep -a org.mozilla.fennec_fdroid -d f-droid . # Mirror, custom repo with fingerprint, disable entry-point spec apkeep -a org.torproject.android -d f-droid -o repo=https://guardianproject.info/fdroid/repo?fingerprint=B7C2EEFD8DAC7806AF67DFCD92EB18126BC08312A7F2D6F3862E46013C7A6135,use_entry=false . # Version + architecture selection apkeep -a org.videloan.vlc@3.5.4 -d f-droid -o arch=arm64-v8a . # Debugging only: skip index verification apkeep -a org.torproject.android -d f-droid -o repo=https://guardianproject.info/fdroid/repo,verify-index=false . # JSON version listing apkeep -l -a org.mozilla.fennec_fdroid -d f-droid -o output_format=json ``` -------------------------------- ### apkeep Google Play ToS error output Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/google-play.md This example shows the error output when a ToS requirement is not accepted. The first line is the error from the gpapi crate, followed by a message to read the ToS and a hint to pass the --accept-tos flag. This output is printed by the source at src/download_sources/google_play.rs:71. ```shell $ apkeep -a com.instagram.android -d google-play -e email -t token . [gpapi error text] Please read the ToS here: https://play.google.com/about/play-terms/index.html If you accept, please pass the --accept-tos flag. ``` -------------------------------- ### main function entry point (Rust) Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/main.md The tokio async entry point for apkeep. It parses CLI arguments, selects the download source, builds the app list, and dispatches to download or list-version functions. Exits with status 1 on validation/configuration failures. ```rust #[tokio::main] async fn main() { ``` -------------------------------- ### Download app with AUTH token Source: https://github.com/efforg/apkeep/blob/master/USAGE-google-play.md Download an app using an AUTH token from a token dispenser. The --accept-tos flag is recommended for first-time use with a new account. ```shell apkeep -a com.instagram.android -d google-play -e 'dispenser_email@gmail.com' --auth-token 'ya29.a0...' --accept-tos . ``` -------------------------------- ### Run apkeep release version with cargo run --release -- ARGS Source: https://github.com/efforg/apkeep/blob/master/HACKING.md Builds and runs apkeep in release mode, passing the provided arguments to the tool. ```shell cargo run --release -- ARGS ``` -------------------------------- ### apkeep validation error output Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/cli.md Example of the error message displayed by clap when required arguments are missing, such as unknown flags, conflicting -t/--auth-token, or missing required -a/-c/OUTPATH. Shows the expected usage syntax. ```shell $ apkeep error: the following required arguments were not provided: --app or --csv Usage: apkeep <-a app_id[@version] | -c csv [-f field] [-v version_field]> [-d download_source] [-r parallel] OUTPATH For more information, try '--help'. ``` -------------------------------- ### request_aas_token function signature Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/google-play.md Exchanges a single-use Google OAuth token (typically starts with `oauth2_4/`) for a long-lived AAS token. Prints the AAS token to stdout on success; on failure prints an error message to stdout without exiting the process. ```rust pub async fn request_aas_token( email: &str, oauth_token: &str, mut options: HashMap<&str, &str>, ) { ``` -------------------------------- ### Create directory if not exists Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/config.md Creates `config_dir` if it does not already exist. A pre-existing directory is considered success. Returns `Err(ConfigDirError::CouldNotCreate)` if `fs::create_dir` fails. ```rust pub fn create_dir(config_dir: &PathBuf) -> Result<(), ConfigDirError> { if !config_dir.is_dir() { fs::create_dir(config_dir).map_err(|_| { ConfigDirError::CouldNotCreate } )?; } Ok(()) } ``` -------------------------------- ### Docker run command for apkeep stable image Source: https://github.com/efforg/apkeep/blob/master/_autodocs/configuration.md Run the apkeep Docker image with the stable tag, mounting a host directory to /output and passing the -a flag with a package name and the /output path. The image entrypoint is the apkeep binary, so all CLI flags apply unchanged. ```bash docker run --rm -v output_path:/output ghcr.io/efforg/apkeep:stable -a com.instagram.android /output ``` -------------------------------- ### List versions in JSON format Source: https://github.com/efforg/apkeep/blob/master/USAGE-fdroid.md Lists available versions in JSON format by passing the output_format=json option. ```shell apkeep -l -a org.mozilla.fennec_fdroid -d f-droid -o output_format=json ``` -------------------------------- ### Resolve and prepare config directory Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/config.md Resolves the platform config directory and ensures the `apkeep` subdirectory exists inside it. Returns `Err(ConfigDirError::NotFound)` if `dirs::config_dir()` returns `None`, or `Err(ConfigDirError::CouldNotCreate)` if the base config directory or the `apkeep/` subdirectory could not be created. ```rust pub fn config_dir() -> Result { let mut config_dir = dirs::config_dir().ok_or(ConfigDirError::NotFound)?; create_dir(&config_dir)?; config_dir.push("apkeep"); create_dir(&config_dir)?; Ok(config_dir) } ``` -------------------------------- ### Create F-Droid custom repo config directories Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/config.md Creates the `fdroid-custom-repos` subdirectory and a hashed subdirectory for a custom repository. Exits with an error if the config directory cannot be resolved or created. ```rust // src/download_sources/fdroid.rs (retrieve_index_or_exit) let mut config_dir = config::config_dir().map_err(display_error_and_exit).unwrap(); if custom_repo { config_dir.push("fdroid-custom-repos"); config::create_dir(&config_dir).map_err(display_error_and_exit).unwrap(); config_dir.push(format!("{}", s.finish())); // DefaultHasher hash of the repo URL config::create_dir(&config_dir).map_err(display_error_and_exit).unwrap(); } ``` -------------------------------- ### Constructing version-specific regex Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/consts.md Demonstrates how the download_apps function prefixes the APKPURE_DOWNLOAD_URL_REGEX with a version-specific matcher. ```rust let regex_string = format!("[[:^digit:]]{}:(?s:.)+?{}", regex::escape(&app_version), crate::consts::APKPURE_DOWNLOAD_URL_REGEX); ``` -------------------------------- ### Download an APK using Docker Source: https://github.com/efforg/apkeep/blob/master/README.md Runs apkeep in a Docker container to download a single APK to a chosen output directory. Mounts the output directory to /output. ```shell docker run --rm -v output_path:/output ghcr.io/efforg/apkeep:stable -a com.instagram.android /output ``` -------------------------------- ### Module wiring: mod declarations and use statements Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/main.md Declares the cli, config, consts, util, and download_sources modules, and imports the DownloadSource type and the four download source modules (google_play, fdroid, apkpure, huawei_app_gallery). ```rust mod cli; use cli::DownloadSource; mod config; mod consts; mod util; mod download_sources; use download_sources::google_play; use download_sources::fdroid; use download_sources::apkpure; use download_sources::huawei_app_gallery; ``` -------------------------------- ### create_dir Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/config.md Creates the specified configuration directory if it does not already exist. A pre-existing directory is considered success. ```APIDOC ## Function: `create_dir` ### Description Creates the specified configuration directory if it does not already exist. A pre-existing directory is considered success. ### Method N/A (Rust function) ### Endpoint N/A ### Parameters #### Function Parameters - **`config_dir`** (`&PathBuf`) - Required - Directory to ensure exists ### Request Example N/A ### Response #### Success Response - **`Ok(())`** - The directory exists or was created successfully. - **`Err(ConfigDirError::CouldNotCreate)`** - `fs::create_dir` failed. #### Response Example N/A ``` -------------------------------- ### Run apkeep with cargo run -- ARGS Source: https://github.com/efforg/apkeep/blob/master/HACKING.md Builds and runs apkeep in debug mode, passing the provided arguments to the tool. ```shell cargo run -- ARGS ``` -------------------------------- ### Creating progress bars with MultiProgress (usage pattern) Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/util.md Shows the pattern of creating one `Rc` per download run and handing the wrapper to each download task. The callback updates the bar and finishes it when complete. ```rust let mp = Rc::new(MultiProgress::new()); // ... inside each future ... let cb = match length { Some(length) => Some(progress_wrapper(mp)(fname.clone(), length)), None => None, }; match dl.download(&cb).await { Ok(_) => mp_log.suspend(|| println!("{} downloaded successfully!", app_string)), // ... } ``` -------------------------------- ### app() function definition Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/cli.md Defines the clap Command for apkeep with metadata: name, version, author, about, and custom usage string. Call get_matches() to parse arguments. ```rust pub fn app() -> Command { Command::new("apkeep") .version(env!("CARGO_PKG_VERSION")) .author("William Budington ") .about("Downloads APKs from various sources") .override_usage("apkeep <-a app_id[@version] | -c csv [-f field] [-v version_field]> [-d download_source] [-r parallel] OUTPATH") ... } ``` -------------------------------- ### Implement FromStr for DownloadSource Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/cli.md Parses a string into a `DownloadSource` using clap's value matching, which is case-insensitive and accepts unambiguous prefixes. Unknown values produce `Err(String)` with message `Invalid variant: `. ```rust impl std::str::FromStr for DownloadSource { type Err = String; fn from_str(s: &str) -> Result { for variant in Self::value_variants() { if variant.to_possible_value().unwrap().matches(s, false) { return Ok(*variant); } } Err(format!("Invalid variant: {}", s)) } } ``` -------------------------------- ### Multiple apps from CSV with parallel downloads Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/main.md Downloads multiple apps from a CSV file where app IDs are in column 2 and versions in column 3, with 3 parallel downloads and a 500 ms delay before each request. ```shell apkeep -c apps.csv -f 2 -v 3 -r 3 -s 500 -d f-droid /output ``` -------------------------------- ### http_headers - Build fixed User-Agent header Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/huawei-app-gallery.md Returns a reqwest::header::HeaderMap with a single fixed User-Agent identifying the client as the Huawei AppGallery Android SDK (UpdateSDK##4.0.1.300##Android##Pixel 2##com.huawei.appmarket##12.0.1.301). ```rust fn http_headers() -> HeaderMap { let mut headers = HeaderMap::new(); headers.insert("User-Agent", HeaderValue::from_static("UpdateSDK##4.0.1.300##Android##Pixel 2##com.huawei.appmarket##12.0.1.301")); headers } ``` -------------------------------- ### client_api_body - Build URL-encoded form body Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/huawei-app-gallery.md Builds the application/x-www-form-urlencoded request body for the store client API. The only variable part is app_id, substituted into the percent-encoded pkgInfo.params[0].package JSON field. Everything else (device deviceSpecParams, locale en_US, serviceCountry=IE, method client.updateCheck, etc.) is hard-coded. ```rust fn client_api_body(app_id: &str) -> String { format!("agVersion=12.0.1&brand=Android&buildNumber=QQ2A.200405.005.2020.04.07.17&density=420&deviceSpecParams=%7B%22abis%22%3A%22arm64-v8a%2Carmeabi-v7a%2Carmeabi%22%2C...&pkgInfo=%7B%22params%22%3A%5B%7B%22isPre%22%3A0%2C%22maple%22%3A0%2C%22oldVersion%22%3A%221.0%22%2C%22package%22%3A%22{}%22%2C%22pkgMode%22%3A0%2C%22shellApkVer%22%3A0%2C%22targetSdkVersion%22%3A19%2C%22versionCode%22%3A1%7D%5D%7D&resolution=1080_1794&sdkVersion=4.0.1.300&serviceCountry=IE&serviceType=0&supportMaple=0&ts=1649970862661&ver=1.2&version=12.0.1.301&versionCode=120001301", app_id) } ``` -------------------------------- ### Use custom device properties file Source: https://github.com/efforg/apkeep/blob/master/USAGE-google-play.md Use a custom device properties file, e.g., one exported from Aurora Store's spoof manager. ```shell apkeep -a com.instagram.android -d google-play -o device=default,device_properties_file=/path/to/device.properties . ``` -------------------------------- ### List available versions from APKPure Source: https://github.com/efforg/apkeep/blob/master/USAGE-apkpure.md Lists the available versions for the app com.instagram.android. The first command specifies a specific architecture (x86), while the second lists versions without architecture filtering. ```shell apkeep -l -a com.instagram.android -o 'arch=x86' apkeep -l -a com.instagram.android ``` -------------------------------- ### config_dir Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/config.md Resolves the platform config directory and ensures the `apkeep` subdirectory exists inside it. Returns the path to the `apkeep` directory. ```APIDOC ## Function: `config_dir` ### Description Resolves the platform config directory and ensures the `apkeep` subdirectory exists inside it. Returns the path to the `apkeep` directory. ### Method N/A (Rust function) ### Endpoint N/A ### Parameters #### Function Parameters - None ### Request Example N/A ### Response #### Success Response - **`Ok(path)`** - The existing/created directory `/apkeep`. - **`Err(ConfigDirError::NotFound)`** - `dirs::config_dir()` returned `None`. - **`Err(ConfigDirError::CouldNotCreate)`** - The base config directory or the `apkeep/` subdirectory could not be created. #### Response Example N/A ``` -------------------------------- ### Build apkeep release version with cargo build --release Source: https://github.com/efforg/apkeep/blob/master/HACKING.md Builds the apkeep binaries in release mode with optimizations. The compiled binaries are placed in a new `target/` directory. ```shell cargo build --release ``` -------------------------------- ### Specify device profile Source: https://github.com/efforg/apkeep/blob/master/USAGE-google-play.md Specify a different device profile using the -o option. Available devices are listed in the device.properties file. ```shell apkeep -a com.instagram.android -d google-play -o device=ad_g3_pro -e 'someone@gmail.com' -t some_aas_token . ``` -------------------------------- ### Build apkeep with cargo build Source: https://github.com/efforg/apkeep/blob/master/HACKING.md Builds the apkeep binaries in debug mode. The compiled binaries are placed in a new `target/` directory. ```shell cargo build ``` -------------------------------- ### list_versions function signature Source: https://github.com/efforg/apkeep/blob/master/_autodocs/api-reference/huawei-app-gallery.md Synchronous-styled stub for listing versions on Huawei AppGallery. AppGallery does not expose historical versions, so this function prints a message for each app indicating that old versions are not available. ```rust pub async fn list_versions(apps: Vec<(String, Option)>) { ```