Skip to content

Commit 46e5fe4

Browse files
committed
Take 4
Signed-off-by: Yuki Kishimoto <yukikishimoto@protonmail.com>
1 parent aa43f9f commit 46e5fe4

File tree

1 file changed

+147
-32
lines changed
  • signer/nostr-android-signer/src

1 file changed

+147
-32
lines changed

signer/nostr-android-signer/src/lib.rs

Lines changed: 147 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl AndroidSigner {
164164
fn launch_get_public_key_intent(
165165
&self,
166166
permissions: Option<Vec<Permission>>,
167-
) -> Result<(), Error> {
167+
) -> Result<usize, Error> {
168168
let mut env: JNIEnv = self.ctx.get_env()?;
169169

170170
let context: &JObject = self.ctx.get_context()?;
@@ -194,56 +194,74 @@ impl AndroidSigner {
194194
add_intent_flags(&mut env, &intent, FLAG_ACTIVITY_NEW_TASK)?;
195195

196196
// Start activity
197-
start_activity(&mut env, context, &intent)?;
198-
//let request_code = self.next_request_code();
199-
//start_activity_for_result(&mut env, context, &intent, request_code as i32)?;
197+
//start_activity(&mut env, context, &intent)?;
198+
let request_code = self.next_request_code();
199+
start_activity_for_result(&mut env, context, &intent, request_code as i32)?;
200200

201-
Ok(())
201+
Ok(request_code)
202202
}
203203

204204
/// Get public key from signer using Content Resolver
205205
pub fn public_key(&self, permissions: Option<Vec<Permission>>) -> Result<(), Error> {
206-
let package_name = self.package_name.get().ok_or(Error::PackageNameNotSet)?;
206+
let mut env = self.ctx.get_env()?;
207+
208+
// Get the current activity
209+
let activity = get_current_activity_context(&mut env)?;
207210

208211
//let (tx, rx) = mpsc::channel();
209212

210-
self.launch_get_public_key_intent(permissions)?;
213+
let request_code = self.launch_get_public_key_intent(permissions)?;
211214

212215
// // Wait for response
213216
// match rx.recv_timeout(Duration::from_secs(60)) {
214217
// Ok(res) => println!("Got response: {:?}", res),
215218
// Err(e) => panic!("Error: {:?}", e),
216219
// }
217-
let res = self.wait_for_response(package_name, Request::GetPublicKey)?;
218-
println!("Got response: {:?}", res);
219-
220-
Ok(())
221-
}
220+
// let res = self.wait_for_response(package_name, Request::GetPublicKey)?;
221+
// println!("Got response: {:?}", res);
222222

223-
/// Wait for response from signer using Content Resolver
224-
fn wait_for_response(&self, package_name: &str, req: Request) -> Result<String, Error> {
225-
let mut env: JNIEnv = self.ctx.get_env()?;
226-
let context: &JObject = self.ctx.get_context()?;
227-
223+
// Poll for the result
228224
let start_time = Instant::now();
229-
230-
loop {
231-
// Check if timeout exceeded
232-
if start_time.elapsed() > CONTENT_RESOLVER_TIMEOUT {
233-
return Err(Error::Timeout);
234-
}
235-
236-
// Try to get response from content resolver
237-
if let Ok(response) = query_content_resolver(&mut env, context, package_name, req) {
238-
if !response.is_empty() {
239-
return Ok(response);
240-
}
225+
let timeout = Duration::from_secs(30);
226+
227+
while start_time.elapsed() < timeout {
228+
// Check if we have a result
229+
if let Some(result) = check_activity_result(&mut env, &activity, request_code as i32)? {
230+
println!("Got result: {:?}", result);
231+
return Ok(());
241232
}
242-
243-
// Wait before next poll
233+
234+
// Wait a bit before checking again
244235
std::thread::sleep(POLLING_INTERVAL);
245236
}
237+
238+
Err(Error::Timeout)
246239
}
240+
241+
// /// Wait for response from signer using Content Resolver
242+
// fn wait_for_response(&self, package_name: &str, req: Request) -> Result<String, Error> {
243+
// let mut env: JNIEnv = self.ctx.get_env()?;
244+
// let context: &JObject = self.ctx.get_context()?;
245+
//
246+
// let start_time = Instant::now();
247+
//
248+
// loop {
249+
// // Check if timeout exceeded
250+
// if start_time.elapsed() > CONTENT_RESOLVER_TIMEOUT {
251+
// return Err(Error::Timeout);
252+
// }
253+
//
254+
// // Try to get response from content resolver
255+
// if let Ok(response) = query_content_resolver(&mut env, context, package_name, req) {
256+
// if !response.is_empty() {
257+
// return Ok(response);
258+
// }
259+
// }
260+
//
261+
// // Wait before next poll
262+
// std::thread::sleep(POLLING_INTERVAL);
263+
// }
264+
// }
247265
}
248266

249267
/// Get JVM
@@ -492,6 +510,99 @@ fn start_activity_for_result(
492510
Ok(())
493511
}
494512

513+
fn check_activity_result<'a>(
514+
env: &mut JNIEnv<'a>,
515+
activity: &JObject,
516+
request_code: i32,
517+
) -> Result<Option<JObject<'a>>, Error> {
518+
// Get the Activity class
519+
let activity_class = env.get_object_class(&activity)?;
520+
521+
// Try to access mActivityResult field (this is internal Android implementation)
522+
// Note: This might not work on all Android versions due to internal changes
523+
let activity_result_field = match env.get_field_id(
524+
activity_class,
525+
"mActivityResult",
526+
"Landroid/app/ActivityResult;",
527+
) {
528+
Ok(field) => field,
529+
Err(_) => return Ok(None), // Field doesn't exist or isn't accessible
530+
};
531+
532+
let activity_result =
533+
env.get_field_unchecked(&activity, activity_result_field, ReturnType::Object)?;
534+
let result_obj = activity_result.l()?;
535+
536+
if !result_obj.is_null() {
537+
// Get the result code and request code from ActivityResult
538+
let result_code = get_activity_result_code(env, &result_obj)?;
539+
let result_request_code = get_activity_result_request_code(env, &result_obj)?;
540+
541+
if result_request_code == request_code {
542+
// We found the result
543+
let result_data = get_activity_result_data(env, &result_obj)?;
544+
545+
// Clear the result so we don't process it again
546+
clear_activity_result(env, &activity)?;
547+
548+
return Ok(Some(result_data));
549+
}
550+
}
551+
552+
Ok(None)
553+
}
554+
555+
fn get_activity_result_code(
556+
env: &mut JNIEnv,
557+
result_obj: &JObject,
558+
) -> Result<i32, jni::errors::Error> {
559+
let result_class = env.get_object_class(result_obj)?;
560+
let field_id = env.get_field_id(result_class, "mResultCode", "I")?;
561+
env.get_field_unchecked(result_obj, field_id, ReturnType::Primitive(Primitive::Int))?
562+
.i()
563+
}
564+
565+
fn get_activity_result_request_code(
566+
env: &mut JNIEnv,
567+
result_obj: &JObject,
568+
) -> Result<i32, jni::errors::Error> {
569+
let result_class = env.get_object_class(result_obj)?;
570+
let field_id = env.get_field_id(result_class, "mRequestCode", "I")?;
571+
env.get_field_unchecked(result_obj, field_id, ReturnType::Primitive(Primitive::Int))?
572+
.i()
573+
}
574+
575+
fn get_activity_result_data<'a>(
576+
env: &mut JNIEnv<'a>,
577+
result_obj: &JObject,
578+
) -> Result<JObject<'a>, jni::errors::Error> {
579+
let result_class = env.get_object_class(result_obj)?;
580+
let field_id = env.get_field_id(result_class, "mData", "Landroid/content/Intent;")?;
581+
env.get_field_unchecked(result_obj, field_id, ReturnType::Object)?
582+
.l()
583+
}
584+
585+
fn clear_activity_result(env: &mut JNIEnv, activity: &JObject) -> Result<(), jni::errors::Error> {
586+
let activity_class = env.get_object_class(activity)?;
587+
588+
// Try to clear the mActivityResult field by setting it to null
589+
match env.get_field_id(
590+
activity_class,
591+
"mActivityResult",
592+
"Landroid/app/ActivityResult;",
593+
) {
594+
Ok(field_id) => {
595+
// Set the field to null to clear the result
596+
env.set_field_unchecked(activity, field_id, JValue::Object(&JObject::null()))?;
597+
Ok(())
598+
}
599+
Err(_) => {
600+
// Field doesn't exist or isn't accessible, that's okay
601+
Ok(())
602+
}
603+
}
604+
}
605+
495606
/// Create a string array for JNI
496607
fn create_string_array<'a>(env: &mut JNIEnv<'a>, strings: &[&str]) -> Result<JObject<'a>, Error> {
497608
let string_class = env.find_class("java/lang/String")?;
@@ -505,7 +616,11 @@ fn create_string_array<'a>(env: &mut JNIEnv<'a>, strings: &[&str]) -> Result<JOb
505616
Ok(array.into())
506617
}
507618

508-
fn get_column_index<'a>(env: &mut JNIEnv<'a>, cursor: &JObject, column: &str) -> Result<JValueOwned<'a>, Error> {
619+
fn get_column_index<'a>(
620+
env: &mut JNIEnv<'a>,
621+
cursor: &JObject,
622+
column: &str,
623+
) -> Result<JValueOwned<'a>, Error> {
509624
let obj = string_to_jobject(env, column)?;
510625
Ok(env.call_method(
511626
cursor,

0 commit comments

Comments
 (0)