Skip to content

Commit

Permalink
android: address failure on termux in absence of vm context
Browse files Browse the repository at this point in the history
  • Loading branch information
amodm committed Nov 8, 2022
1 parent 0bbeab4 commit d2a8ce6
Showing 1 changed file with 48 additions and 4 deletions.
52 changes: 48 additions & 4 deletions src/android.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{Browser, BrowserOptions, Error, ErrorKind, Result};
use jni::objects::JValue;
pub use std::os::unix::process::ExitStatusExt;
use std::process::{Command, Stdio};

/// Deal with opening of browsers on Android. Only [Browser::Default] is supported, and
/// in options, only [BrowserOptions::dry_run] is honoured.
Expand All @@ -17,17 +17,28 @@ pub fn open_browser_internal(browser: Browser, url: &str, options: &BrowserOptio

/// Open the default browser
#[inline]
pub fn open_browser_default(url: &str, options: &BrowserOptions) -> Result<()> {
fn open_browser_default(url: &str, options: &BrowserOptions) -> Result<()> {
// always return true for a dry run
if options.dry_run {
return Ok(());
}

// Create a VM for executing Java calls
let ctx = ndk_context::android_context();
let vm = unsafe {
jni::JavaVM::from_raw(ctx.vm() as _).expect("Expected to find JVM via ndk_context crate")
let vm = match unsafe { jni::JavaVM::from_raw(ctx.vm() as _) } {
Ok(x) => x,
Err(_) => {
// if we didn't get the vm instance, maybe we're running
// inside a termux, so try with that
return try_for_termux(url, options).map_err(|_| -> Error {
Error::new(
ErrorKind::NotFound,
"Expected to find JVM via ndk_context crate",
)
});
}
};

let activity = unsafe { jni::objects::JObject::from_raw(ctx.context() as _) };
let env = vm.attach_current_thread().map_err(|_| -> Error {
Error::new(ErrorKind::Other, "Failed to attach current thread")
Expand Down Expand Up @@ -82,3 +93,36 @@ pub fn open_browser_default(url: &str, options: &BrowserOptions) -> Result<()> {

Ok(())
}

/// Attemps to open a browser assuming a termux environment
///
/// See [issue #53](https://github.com/amodm/webbrowser-rs/issues/53)
#[inline]
fn try_for_termux(url: &str, options: &BrowserOptions) -> Result<()> {
use std::env;
if env::var("TERMUX_VERSION").is_ok() {
// return true on dry-run given that termux-open command is guaranteed to be present
if options.dry_run {
return Ok(());
}
let mut cmd = Command::new("termux-open");
cmd.arg(url);
if options.suppress_output {
cmd.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null());
}
cmd.status().and_then(|status| {
if status.success() {
Ok(())
} else {
Err(Error::new(
ErrorKind::Other,
"command present but exited unsuccessfully",
))
}
})
} else {
Err(Error::new(ErrorKind::Other, "Not a termux environment"))
}
}

0 comments on commit d2a8ce6

Please sign in to comment.