Skip to content

Commit

Permalink
Merge pull request #93 from dodorare/android-services
Browse files Browse the repository at this point in the history
Add android services support
  • Loading branch information
Heezay committed Jun 2, 2022
2 parents ce243d6 + 31d758d commit 60727e7
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 177 deletions.
5 changes: 4 additions & 1 deletion crossbundle/cli/src/cargo_manifest.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crossbundle_tools::types::{
android_manifest::{UsesFeature, UsesPermission, UsesPermissionSdk23},
android_manifest::{Service, UsesFeature, UsesPermission, UsesPermissionSdk23},
*,
};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -41,6 +41,9 @@ pub struct Metadata {
/// Declares a single hardware or software android feature that is used by the application
pub android_features: Option<Vec<UsesFeature>>,

/// Android service to place in AndroidManifest.xml.
pub android_service: Option<Vec<Service>>,

/// Apple build targets.
pub apple_build_targets: Option<Vec<AppleTarget>>,
/// Apple resources directory path relatively to project path.
Expand Down
1 change: 1 addition & 0 deletions crossbundle/cli/src/commands/build/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ impl AndroidBuildCommand {
config.status("Build finished successfully")?;
Ok((android_manifest, sdk, aligned_apk_path))
}

/// Builds AAB with aapt2 tool and signs it with jarsigner
pub fn execute_aab(
&self,
Expand Down
88 changes: 46 additions & 42 deletions crossbundle/cli/src/commands/build/build_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,28 @@ use crate::{
cargo_manifest::Metadata,
error::{Error, Result},
};
use cargo::core::Manifest;
use crossbundle_tools::{
commands::{
android, apple, find_package_cargo_manifest_path, find_workspace_cargo_manifest_path,
parse_manifest,
},
tools::AndroidSdk,
commands::{android::GenAndroidManifest, *},
tools::*,
types::{
android_manifest::AndroidManifest, apple_bundle::prelude::InfoPlist, AndroidTarget,
AppleTarget,
},
utils::Config,
utils::*,
};
use std::path::PathBuf;

pub struct BuildContext {
pub workspace_manifest_path: PathBuf,
pub package_manifest_path: PathBuf,
pub project_path: PathBuf,
pub manifest: Manifest,
pub manifest: cargo::core::Manifest,
pub metadata: Metadata,
pub target_dir: PathBuf,
}

impl BuildContext {
/// Create new instance of build context
pub fn new(config: &Config, target_dir: Option<PathBuf>) -> Result<Self> {
let workspace_manifest_path = find_workspace_cargo_manifest_path(config.current_dir())?;
let package_manifest_path = find_package_cargo_manifest_path(config.current_dir())?;
Expand All @@ -52,24 +49,28 @@ impl BuildContext {
})
}

/// Get package name from cargo manifest
pub fn package_name(&self) -> String {
if let Some(package_name) = self.metadata.android_package_name.clone() {
return package_name;
};
self.manifest.summary().name().to_string()
}

/// Get package version from cargo manifest
pub fn package_version(&self) -> String {
self.manifest.summary().version().to_string()
}

/// Get target sdk version from cargo manifest
pub fn target_sdk_version(&self, sdk: &AndroidSdk) -> u32 {
if let Some(target_sdk_version) = self.metadata.target_sdk_version {
return target_sdk_version;
};
sdk.default_platform()
}

/// Get android build targets from cargo manifest
pub fn android_build_targets(&self, build_targets: &Vec<AndroidTarget>) -> Vec<AndroidTarget> {
if !build_targets.is_empty() {
return build_targets.clone();
Expand All @@ -84,20 +85,46 @@ impl BuildContext {
vec![AndroidTarget::Aarch64LinuxAndroid]
}

/// Get android resources from cargo manifest
pub fn android_res(&self) -> Option<PathBuf> {
self.metadata.android_res.clone()
}

/// Get android assets from cargo manifest
pub fn android_assets(&self) -> Option<PathBuf> {
self.metadata.android_assets.clone()
}

/// Get android manifest from the path in cargo manifest or generate it with the given configuration
pub fn gen_android_manifest(
&self,
sdk: &AndroidSdk,
package_name: &str,
debuggable: bool,
) -> Result<AndroidManifest> {
let android_manifest = GenAndroidManifest {
app_id: Some(package_name.to_string()),
package_name: package_name.to_string(),
app_name: self.metadata.app_name.clone(),
version_name: self
.metadata
.version_name
.clone()
.unwrap_or(self.package_version()),
version_code: self.metadata.version_code.clone().unwrap_or(1),
min_sdk_version: self.metadata.min_sdk_version,
target_sdk_version: self
.metadata
.target_sdk_version
.unwrap_or_else(|| sdk.default_platform()),
max_sdk_version: self.metadata.max_sdk_version,
icon: self.metadata.icon.clone(),
debuggable,
permissions_sdk_23: self.metadata.android_permissions_sdk_23.clone(),
permissions: self.metadata.android_permissions.clone(),
features: self.metadata.android_features.clone(),
service: self.metadata.android_service.clone(),
};
if self.metadata.use_android_manifest {
let path = self
.metadata
Expand All @@ -106,47 +133,21 @@ impl BuildContext {
.unwrap_or_else(|| self.project_path.join("AndroidManifest.xml"));
Ok(android::read_android_manifest(&path)?)
} else if !self.metadata.use_android_manifest {
let manifest = android::gen_minimal_android_manifest(
self.metadata.android_package_name.clone(),
package_name,
self.metadata.app_name.clone(),
self.metadata
.version_name
.clone()
.unwrap_or(self.package_version()),
self.metadata.version_code.clone(),
self.metadata.min_sdk_version,
self.metadata
.target_sdk_version
.unwrap_or_else(|| sdk.default_platform()),
self.metadata.max_sdk_version,
self.metadata.icon.clone(),
debuggable,
self.metadata.android_permissions_sdk_23.clone(),
self.metadata.android_permissions.clone(),
self.metadata.android_features.clone(),
);
let manifest = GenAndroidManifest::gen_android_manifest(&android_manifest);
Ok(manifest)
} else {
let target_sdk_version = sdk.default_platform();
Ok(android::gen_minimal_android_manifest(
None,
package_name,
None,
self.package_version(),
None,
None,
let minimal_android_manifest = GenAndroidManifest {
target_sdk_version,
None,
None,
debuggable,
None,
None,
None,
))
version_name: self.package_version(),
package_name: package_name.to_string(),
..Default::default()
};
Ok(minimal_android_manifest.gen_min_android_manifest())
}
}

/// Get info plist from the path in cargo manifest or generate it with the given configuration
pub fn gen_info_plist(&self, package_name: &String) -> Result<InfoPlist> {
if self.metadata.use_info_plist {
let path = self
Expand All @@ -173,6 +174,7 @@ impl BuildContext {
}
}

/// Get apple build targets from cargo manifest
pub fn apple_build_targets(&self, build_targets: &Vec<AppleTarget>) -> Vec<AppleTarget> {
if !build_targets.is_empty() {
return build_targets.clone();
Expand All @@ -187,10 +189,12 @@ impl BuildContext {
vec![AppleTarget::X86_64AppleIos]
}

/// Get apple resources from cargo manifest
pub fn apple_res(&self) -> Option<PathBuf> {
self.metadata.apple_res.clone()
}

/// Get apple assets from cargo manifest
pub fn apple_assets(&self) -> Option<PathBuf> {
self.metadata.apple_assets.clone()
}
Expand Down
169 changes: 106 additions & 63 deletions crossbundle/tools/src/commands/android/gen_manifest.rs
Original file line number Diff line number Diff line change
@@ -1,75 +1,118 @@
use android_manifest::*;

/// Generates minimal [`AndroidManifest`](android_manifest::AndroidManifest) with given
/// changes
pub fn gen_minimal_android_manifest(
app_id: Option<String>,
package_name: &str,
app_name: Option<String>,
version_name: String,
version_code: Option<u32>,
min_sdk_version: Option<u32>,
target_sdk_version: u32,
max_sdk_version: Option<u32>,
icon: Option<String>,
debuggable: bool,
permissions_sdk_23: Option<Vec<UsesPermissionSdk23>>,
permissions: Option<Vec<UsesPermission>>,
features: Option<Vec<UsesFeature>>,
) -> AndroidManifest {
AndroidManifest {
package: app_id.unwrap_or(format!("com.rust.{}", package_name.replace('-', "_"))),
version_name: Some(version_name),
version_code,
uses_sdk: Some(UsesSdk {
min_sdk_version: Some(min_sdk_version.unwrap_or(9)),
target_sdk_version: Some(target_sdk_version),
max_sdk_version,
}),
uses_permission_sdk_23: permissions_sdk_23.unwrap_or_default(),
uses_permission: permissions.unwrap_or_default(),
uses_feature: features.unwrap_or_default(),
application: Application {
has_code: Some(false),
label: Some(StringResourceOrString::string(
app_name.as_ref().unwrap_or(&package_name.to_owned()),
)),
debuggable: Some(debuggable),
icon: icon.map(|i| MipmapOrDrawableResource::mipmap(&i, None)),
theme: Some(Resource::new_with_package(
"Theme.DeviceDefault.NoActionBar.Fullscreen",
Some("android".to_string()),
)),
activity: vec![Activity {
name: "android.app.NativeActivity".to_string(),
resizeable_activity: Some(true),
#[derive(Default)]
pub struct GenAndroidManifest {
pub app_id: Option<String>,
pub package_name: String,
pub app_name: Option<String>,
pub version_name: String,
pub version_code: u32,
pub min_sdk_version: Option<u32>,
pub target_sdk_version: u32,
pub max_sdk_version: Option<u32>,
pub icon: Option<String>,
pub debuggable: bool,
pub permissions_sdk_23: Option<Vec<UsesPermissionSdk23>>,
pub permissions: Option<Vec<UsesPermission>>,
pub features: Option<Vec<UsesFeature>>,
pub service: Option<Vec<Service>>,
}

impl GenAndroidManifest {
/// Generates [`AndroidManifest`](android_manifest::AndroidManifest) with
/// given changes
pub fn gen_android_manifest(&self) -> AndroidManifest {
AndroidManifest {
package: self
.app_id
.clone()
.unwrap_or(format!("com.rust.{}", self.package_name.replace('-', "_"))),
version_name: Some(self.version_name.clone()),
version_code: Some(self.version_code),
uses_sdk: Some(UsesSdk {
min_sdk_version: Some(self.min_sdk_version.unwrap_or(9)),
target_sdk_version: Some(self.target_sdk_version),
max_sdk_version: self.max_sdk_version,
}),
uses_permission_sdk_23: self.permissions_sdk_23.clone().unwrap_or_default(),
uses_permission: self.permissions.clone().unwrap_or_default(),
uses_feature: self.features.clone().unwrap_or_default(),
application: Application {
has_code: Some(false),
label: Some(StringResourceOrString::string(
app_name.as_ref().unwrap_or(&package_name.to_owned()),
self.app_name
.as_ref()
.unwrap_or(&self.package_name.to_owned()),
)),
config_changes: vec![
ConfigChanges::Orientation,
ConfigChanges::KeyboardHidden,
ConfigChanges::ScreenSize,
]
.into(),
meta_data: vec![MetaData {
name: Some("android.app.lib_name".to_string()),
value: Some(package_name.replace('-', "_")),
..Default::default()
}],
intent_filter: vec![IntentFilter {
action: vec![Action {
name: Some("android.intent.action.MAIN".to_string()),
debuggable: Some(self.debuggable),
icon: self
.icon
.clone()
.map(|i| MipmapOrDrawableResource::mipmap(&i, None)),
theme: Some(Resource::new_with_package(
"Theme.DeviceDefault.NoActionBar.Fullscreen",
Some("android".to_string()),
)),
service: self.service.clone().unwrap_or_default(),
activity: vec![Activity {
name: "android.app.NativeActivity".to_string(),
resizeable_activity: Some(true),
label: Some(StringResourceOrString::string(
self.app_name
.as_ref()
.unwrap_or(&self.package_name.to_owned()),
)),
config_changes: vec![
ConfigChanges::Orientation,
ConfigChanges::KeyboardHidden,
ConfigChanges::ScreenSize,
]
.into(),
meta_data: vec![MetaData {
name: Some("android.app.lib_name".to_string()),
value: Some(self.package_name.replace('-', "_")),
..Default::default()
}],
category: vec![Category {
name: Some("android.intent.category.LAUNCHER".to_string()),
intent_filter: vec![IntentFilter {
action: vec![Action {
name: Some("android.intent.action.MAIN".to_string()),
}],
category: vec![Category {
name: Some("android.intent.category.LAUNCHER".to_string()),
}],
..Default::default()
}],
..Default::default()
}],
..Default::default()
}],
},
..Default::default()
}
}

/// Generate android manifest with minimal required tags.
pub fn gen_min_android_manifest(&self) -> AndroidManifest {
AndroidManifest {
package: self
.app_id
.clone()
.unwrap_or(format!("com.rust.{}", self.package_name.replace('-', "_"))),
version_name: Some(self.version_name.clone()),
version_code: Some(self.version_code),
application: Application {
has_code: Some(false),
label: Some(StringResourceOrString::string(
self.app_name
.as_ref()
.unwrap_or(&self.package_name.to_owned()),
)),
activity: vec![Activity {
name: "android.app.NativeActivity".to_string(),
..Default::default()
}],
..Default::default()
},
..Default::default()
},
..Default::default()
}
}
}
Loading

0 comments on commit 60727e7

Please sign in to comment.