android.rs (4638B)
1 //#[cfg(target_os = "android")] 2 //use egui_android::run_android; 3 4 use egui_winit::winit::platform::android::activity::AndroidApp; 5 use notedeck_columns::Damus; 6 7 use crate::setup::setup_chrome; 8 use notedeck::Notedeck; 9 use serde_json::Value; 10 use std::fs; 11 use std::path::PathBuf; 12 13 #[no_mangle] 14 #[tokio::main] 15 pub async fn android_main(app: AndroidApp) { 16 use tracing_logcat::{LogcatMakeWriter, LogcatTag}; 17 use tracing_subscriber::{prelude::*, EnvFilter}; 18 19 std::env::set_var("RUST_BACKTRACE", "full"); 20 std::env::set_var("RUST_LOG", "egui=trace,notedeck=debug,notedeck_columns=debug,notedeck_chrome=debug,enostr=debug,android_activity=debug"); 21 22 //std::env::set_var( 23 // "RUST_LOG", 24 // "enostr=debug,notedeck_columns=debug,notedeck_chrome=debug", 25 //); 26 27 let writer = 28 LogcatMakeWriter::new(LogcatTag::Target).expect("Failed to initialize logcat writer"); 29 30 let fmt_layer = tracing_subscriber::fmt::layer() 31 .with_level(false) 32 .with_target(false) 33 .without_time(); 34 35 let filter_layer = EnvFilter::try_from_default_env() 36 .or_else(|_| EnvFilter::try_new("info")) 37 .unwrap(); 38 39 tracing_subscriber::registry() 40 .with(filter_layer) 41 .with(fmt_layer) 42 .init(); 43 44 let path = app.internal_data_path().expect("data path"); 45 let mut options = eframe::NativeOptions::default(); 46 options.renderer = eframe::Renderer::Wgpu; 47 // Clone `app` to use it both in the closure and later in the function 48 //let app_clone_for_event_loop = app.clone(); 49 //options.event_loop_builder = Some(Box::new(move |builder| { 50 // builder.with_android_app(app_clone_for_event_loop); 51 //})); 52 53 options.android_app = Some(app.clone()); 54 55 let app_args = get_app_args(app); 56 57 let _res = eframe::run_native( 58 "Damus Notedeck", 59 options, 60 Box::new(move |cc| { 61 let ctx = &cc.egui_ctx; 62 let mut notedeck = Notedeck::new(ctx, path, &app_args); 63 setup_chrome(ctx, ¬edeck.args(), notedeck.theme()); 64 65 let damus = Damus::new(&mut notedeck.app_context(), &app_args); 66 67 // ensure we recognized all the arguments 68 let completely_unrecognized: Vec<String> = notedeck 69 .unrecognized_args() 70 .intersection(damus.unrecognized_args()) 71 .cloned() 72 .collect(); 73 assert!( 74 completely_unrecognized.is_empty(), 75 "unrecognized args: {:?}", 76 completely_unrecognized 77 ); 78 79 notedeck.set_app(damus); 80 81 Ok(Box::new(notedeck)) 82 }), 83 ); 84 } 85 /* 86 Read args from a config file: 87 - allows use of more interesting args w/o risk of checking them in by mistake 88 - allows use of different args w/o rebuilding the app 89 - uses compiled in defaults if config file missing or broken 90 91 Example android-config.json: 92 ``` 93 { 94 "args": [ 95 "argv0-placeholder", 96 "--npub", 97 "npub1h50pnxqw9jg7dhr906fvy4mze2yzawf895jhnc3p7qmljdugm6gsrurqev", 98 "-c", 99 "contacts", 100 "-c", 101 "notifications" 102 ] 103 } 104 ``` 105 106 Install/update android-config.json with: 107 ``` 108 adb push android-config.json /sdcard/Android/data/com.damus.notedeck/files/android-config.json 109 ``` 110 111 Using internal storage would be better but it seems hard to get the config file onto 112 the device ... 113 */ 114 115 fn get_app_args(app: AndroidApp) -> Vec<String> { 116 let external_data_path: PathBuf = app 117 .external_data_path() 118 .expect("external data path") 119 .to_path_buf(); 120 let config_file = external_data_path.join("android-config.json"); 121 122 let default_args = vec![ 123 "argv0-placeholder", 124 "--pub", 125 "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245", 126 "-c", 127 "contacts", 128 "-c", 129 "notifications", 130 "-c", 131 "notifications:3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681", 132 ] 133 .into_iter() 134 .map(|s| s.to_string()) 135 .collect(); 136 137 if config_file.exists() { 138 if let Ok(config_contents) = fs::read_to_string(config_file) { 139 if let Ok(json) = serde_json::from_str::<Value>(&config_contents) { 140 if let Some(args_array) = json.get("args").and_then(|v| v.as_array()) { 141 let config_args = args_array 142 .iter() 143 .filter_map(|v| v.as_str().map(String::from)) 144 .collect(); 145 146 return config_args; 147 } 148 } 149 } 150 } 151 152 default_args // Return the default args if config is missing or invalid 153 }