Files
Ferrous-Solitaire/solitaire_engine/src/android_clipboard.rs
T
funman300 6e407a3ea7
Build and Deploy / build-and-push (push) Successful in 3m54s
fix(engine,server): safe area clamp, analytics batch, achievement save order, daily rollover, replay validation, leaderboard opt-in (#56, #60, #61, #62, #66, #68)
- #66: Clamp safe-area insets to 25% of window height with warn!() on excess
- #68: Move fire_flush outside per-event loop in analytics (batch flush once)
- #56: Persist progress before marking reward_granted to prevent XP loss on crash
- #60: Add DateRolloverTimer + check_date_rollover system for midnight seed refresh
- #62: Add validate_header() in replay upload with mode/draw_mode allowlists
- #61: Restore two-query leaderboard opt-in check (SELECT then UPDATE); original
       queries already in .sqlx cache; EXISTS variant would require sqlx prepare

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-28 13:07:22 -07:00

66 lines
2.3 KiB
Rust

/// Android clipboard bridge via JNI.
///
/// Writes text to the system clipboard by calling into `ClipboardManager`
/// through the JNI. Only compiled and linked on `target_os = "android"`.
#[cfg(target_os = "android")]
pub fn set_text(text: &str) -> Result<(), String> {
use bevy::android::ANDROID_APP;
use jni::{
JavaVM,
objects::{JObject, JValueOwned},
};
let app = ANDROID_APP
.get()
.ok_or_else(|| "ANDROID_APP not initialized".to_string())?;
// SAFETY: vm_as_ptr() returns the raw JavaVM* set up by the Android runtime.
let vm = unsafe { JavaVM::from_raw(app.vm_as_ptr().cast()) }
.map_err(|e| format!("JavaVM::from_raw: {e}"))?;
let mut env = vm
.attach_current_thread_permanently()
.map_err(|e| format!("attach_current_thread: {e}"))?;
// SAFETY: activity_as_ptr() is the NativeActivity jobject pointer —
// valid for the lifetime of the process.
let activity = unsafe { JObject::from_raw(app.activity_as_ptr() as _) };
(|| -> jni::errors::Result<()> {
// ClipboardManager cm = activity.getSystemService("clipboard")
let svc_name = JValueOwned::from(env.new_string("clipboard")?);
let cm = env
.call_method(
&activity,
"getSystemService",
"(Ljava/lang/String;)Ljava/lang/Object;",
&[svc_name.borrow()],
)?
.l()?;
// ClipData clip = ClipData.newPlainText("link", text)
let label = JValueOwned::from(env.new_string("link")?);
let java_text = JValueOwned::from(env.new_string(text)?);
let clip_class = env.find_class("android/content/ClipData")?;
let clip = env
.call_static_method(
&clip_class,
"newPlainText",
"(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Landroid/content/ClipData;",
&[label.borrow(), java_text.borrow()],
)?
.l()?;
// cm.setPrimaryClip(clip)
let clip_val = JValueOwned::Object(clip);
env.call_method(
&cm,
"setPrimaryClip",
"(Landroid/content/ClipData;)V",
&[clip_val.borrow()],
)?
.v()
})()
.map_err(|e| format!("clipboard JNI: {e}"))
}