@@ -164,7 +164,7 @@ impl AndroidSigner {
164
164
fn launch_get_public_key_intent (
165
165
& self ,
166
166
permissions : Option < Vec < Permission > > ,
167
- ) -> Result < ( ) , Error > {
167
+ ) -> Result < usize , Error > {
168
168
let mut env: JNIEnv = self . ctx . get_env ( ) ?;
169
169
170
170
let context: & JObject = self . ctx . get_context ( ) ?;
@@ -194,56 +194,74 @@ impl AndroidSigner {
194
194
add_intent_flags ( & mut env, & intent, FLAG_ACTIVITY_NEW_TASK ) ?;
195
195
196
196
// 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 ) ?;
200
200
201
- Ok ( ( ) )
201
+ Ok ( request_code )
202
202
}
203
203
204
204
/// Get public key from signer using Content Resolver
205
205
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) ?;
207
210
208
211
//let (tx, rx) = mpsc::channel();
209
212
210
- self . launch_get_public_key_intent ( permissions) ?;
213
+ let request_code = self . launch_get_public_key_intent ( permissions) ?;
211
214
212
215
// // Wait for response
213
216
// match rx.recv_timeout(Duration::from_secs(60)) {
214
217
// Ok(res) => println!("Got response: {:?}", res),
215
218
// Err(e) => panic!("Error: {:?}", e),
216
219
// }
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);
222
222
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
228
224
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 ( ( ) ) ;
241
232
}
242
-
243
- // Wait before next poll
233
+
234
+ // Wait a bit before checking again
244
235
std:: thread:: sleep ( POLLING_INTERVAL ) ;
245
236
}
237
+
238
+ Err ( Error :: Timeout )
246
239
}
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
+ // }
247
265
}
248
266
249
267
/// Get JVM
@@ -492,6 +510,99 @@ fn start_activity_for_result(
492
510
Ok ( ( ) )
493
511
}
494
512
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
+
495
606
/// Create a string array for JNI
496
607
fn create_string_array < ' a > ( env : & mut JNIEnv < ' a > , strings : & [ & str ] ) -> Result < JObject < ' a > , Error > {
497
608
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
505
616
Ok ( array. into ( ) )
506
617
}
507
618
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 > {
509
624
let obj = string_to_jobject ( env, column) ?;
510
625
Ok ( env. call_method (
511
626
cursor,
0 commit comments