Skip to main content

android/
android.rs

1// File: examples\android.rs
2// Author: Hadi Cahyadi <cumulus13@gmail.com>
3// Date: 2026-05-13
4// Description:
5// License: MIT
6
7// examples/android.rs
8// Example: Send notifications to Growl for Android with retry
9//
10// Run with: cargo run --example android
11
12use gntp::{GntpClient, IconMode, NotificationType, NotifyOptions, Resource};
13use std::env;
14
15fn main() -> Result<(), Box<dyn std::error::Error>> {
16    println!("=== Growl for Android Example ===\n");
17
18    // Get Android device IP from environment
19    let android_host = env::var("ANDROID_HOST").unwrap_or_else(|_| {
20        println!("⚠ ANDROID_HOST not set, using default");
21        println!("  Set with: set ANDROID_HOST=192.168.1.100\n");
22        "192.168.1.100".to_string()
23    });
24
25    println!("Target Android device: {}", android_host);
26
27    // Create client optimized for Android
28    let mut client = GntpClient::new("Android Example")
29        .with_host(&android_host)
30        .with_port(23053)
31        .with_icon_mode(IconMode::DataUrl) // Best for Android
32        .with_debug(false);
33
34    // Try to load icon (optional)
35    let icon = match Resource::from_file("icon.png") {
36        Ok(icon) => {
37            println!("✓ Icon loaded: icon.png");
38            Some(icon)
39        }
40        Err(_) => {
41            println!("ℹ No icon found (optional)");
42            None
43        }
44    };
45
46    // Define notification type with icon
47    let mut notification =
48        NotificationType::new("android").with_display_name("Android Notification");
49
50    if let Some(icon) = icon {
51        notification = notification.with_icon(icon);
52        println!("✓ Icon attached to notification");
53    }
54
55    println!();
56
57    // Register with retry (Android may need retry due to network)
58    println!("Registering with Growl for Android...");
59    let mut register_ok = false;
60
61    for attempt in 1..=3 {
62        match client.register(vec![notification.clone()]) {
63            Ok(_) => {
64                println!(
65                    "✓ Registered successfully{}\n",
66                    if attempt > 1 {
67                        format!(" (attempt {})", attempt)
68                    } else {
69                        String::new()
70                    }
71                );
72                register_ok = true;
73                break;
74            }
75            Err(e) => {
76                if attempt < 3 {
77                    println!("⚠ Attempt {} failed, retrying... ({})", attempt, e);
78                    std::thread::sleep(std::time::Duration::from_secs(2));
79                } else {
80                    eprintln!("❌ Registration failed after 3 attempts: {}", e);
81                    eprintln!("\nTroubleshooting:");
82                    eprintln!("  1. Is Growl for Android running?");
83                    eprintln!("  2. Is {} the correct IP address?", android_host);
84                    eprintln!("  3. Are both devices on the same network?");
85                    eprintln!("  4. Check Android firewall settings");
86                    return Err(e.into());
87                }
88            }
89        }
90    }
91
92    if !register_ok {
93        return Err("Registration failed".into());
94    }
95
96    // Send notification with options
97    println!("Sending notification...");
98    let options = NotifyOptions::new()
99        .with_sticky(false) // Don't make it sticky on mobile
100        .with_priority(1); // High priority
101
102    match client.notify_with_options(
103        "android",
104        "Hello Android!",
105        "This notification was sent from Rust",
106        options,
107    ) {
108        Ok(_) => {
109            println!("✓ Notification sent\n");
110            println!("✅ Check your Android device for the notification!");
111        }
112        Err(e) => {
113            eprintln!("❌ Failed to send: {}", e);
114            return Err(e.into());
115        }
116    }
117
118    Ok(())
119}