30
30
import com .facebook .FacebookDialogException ;
31
31
import com .facebook .FacebookException ;
32
32
import com .facebook .FacebookOperationCanceledException ;
33
+ import com .facebook .FacebookRequestError ;
34
+ import com .facebook .FacebookServiceException ;
33
35
import com .facebook .Request ;
34
36
import com .facebook .Response ;
35
37
import com .facebook .Session ;
36
38
import com .facebook .SessionState ;
39
+ import com .facebook .UiLifecycleHelper ;
37
40
import com .facebook .model .GraphObject ;
38
41
import com .facebook .model .GraphUser ;
42
+ import com .facebook .widget .FacebookDialog ;
39
43
import com .facebook .widget .WebDialog ;
40
44
import com .facebook .widget .WebDialog .OnCompleteListener ;
41
45
@@ -62,9 +66,13 @@ public class ConnectPlugin extends CordovaPlugin {
62
66
private String method ;
63
67
private String graphPath ;
64
68
private String userID ;
69
+ private UiLifecycleHelper uiHelper ;
70
+ private boolean trackingPendingCall = false ;
65
71
66
72
@ Override
67
73
public void initialize (CordovaInterface cordova , CordovaWebView webView ) {
74
+ //Initialize UiLifecycleHelper
75
+ uiHelper = new UiLifecycleHelper (cordova .getActivity (), null );
68
76
69
77
// Init logger
70
78
logger = AppEventsLogger .newLogger (cordova .getActivity ());
@@ -102,15 +110,51 @@ public void call(Session session, SessionState state, Exception exception) {
102
110
@ Override
103
111
public void onResume (boolean multitasking ) {
104
112
super .onResume (multitasking );
113
+ uiHelper .onResume ();
105
114
// Developers can observe how frequently users activate their app by logging an app activation event.
106
115
AppEventsLogger .activateApp (cordova .getActivity ());
107
116
}
108
117
118
+ protected void onSaveInstanceState (Bundle outState ) {
119
+ uiHelper .onSaveInstanceState (outState );
120
+ }
121
+
122
+ public void onPause () {
123
+ uiHelper .onPause ();
124
+ }
125
+
126
+ @ Override
127
+ public void onDestroy () {
128
+ super .onDestroy ();
129
+ uiHelper .onDestroy ();
130
+ }
131
+
109
132
@ Override
110
133
public void onActivityResult (int requestCode , int resultCode , Intent intent ) {
111
134
super .onActivityResult (requestCode , resultCode , intent );
112
135
Log .d (TAG , "activity result in plugin" );
113
- Session .getActiveSession ().onActivityResult (cordova .getActivity (), requestCode , resultCode , intent );
136
+ if (trackingPendingCall ) {
137
+ uiHelper .onActivityResult (requestCode , resultCode , intent , new FacebookDialog .Callback () {
138
+ @ Override
139
+ public void onError (FacebookDialog .PendingCall pendingCall , Exception error , Bundle data ) {
140
+ Log .e ("Activity" , String .format ("Error: %s" , error .toString ()));
141
+ handleError (error );
142
+ }
143
+
144
+ @ Override
145
+ public void onComplete (FacebookDialog .PendingCall pendingCall , Bundle data ) {
146
+ Log .i ("Activity" , "Success!" );
147
+ handleSuccess (data );
148
+ }
149
+ });
150
+ } else {
151
+ Session session = Session .getActiveSession ();
152
+
153
+ if (session != null && (loginContext != null || session .isOpened ())) {
154
+ session .onActivityResult (cordova .getActivity (), requestCode , resultCode , intent );
155
+ }
156
+ }
157
+ trackingPendingCall = false ;
114
158
}
115
159
116
160
@ Override
@@ -248,7 +292,7 @@ public void call(Session session, SessionState state, Exception exception) {
248
292
Bundle parameters = new Bundle ();
249
293
250
294
Iterator <?> iterator = params .keys ();
251
- while (iterator .hasNext () ) {
295
+ while (iterator .hasNext ()) {
252
296
try {
253
297
// Try get a String
254
298
String value = params .getString ((String ) iterator .next ());
@@ -330,46 +374,10 @@ public void call(Session session, SessionState state, Exception exception) {
330
374
331
375
@ Override
332
376
public void onComplete (Bundle values , FacebookException exception ) {
333
- String errMsg ;
334
377
if (exception != null ) {
335
- // User clicked "x"
336
- if (exception instanceof FacebookOperationCanceledException ) {
337
- errMsg = "User cancelled dialog" ;
338
- Log .e (TAG , errMsg );
339
- showDialogContext .error (errMsg );
340
- } else if (exception instanceof FacebookDialogException ) {
341
- // Dialog error
342
- errMsg = "Dialog error: " + exception .getMessage ();
343
- Log .e (TAG , errMsg );
344
- showDialogContext .error (errMsg );
345
- } else {
346
- // Facebook error
347
- errMsg = "Facebook error: " + exception .getMessage ();
348
- Log .e (TAG , errMsg );
349
- showDialogContext .error (errMsg );
350
- }
378
+ handleError (exception );
351
379
} else {
352
- // Handle a successful dialog:
353
- // Send the URL parameters back, for a requests dialog, the "request" parameter
354
- // will include the resulting request id. For a feed dialog, the "post_id"
355
- // parameter will include the resulting post id.
356
- // Note: If the user clicks on the Cancel button, the parameter will be empty
357
- if (values .size () > 0 ) {
358
- JSONObject response = new JSONObject ();
359
- try {
360
- Set <String > keys = values .keySet ();
361
- for (String key : keys ) {
362
- response .put (key , values .get (key ));
363
- }
364
- } catch (JSONException e ) {
365
- e .printStackTrace ();
366
- }
367
- showDialogContext .success (response );
368
- } else {
369
- errMsg = "User cancelled dialog" ;
370
- Log .e (TAG , errMsg );
371
- showDialogContext .error (errMsg );
372
- }
380
+ handleSuccess (values );
373
381
}
374
382
}
375
383
};
@@ -379,21 +387,45 @@ public void onComplete(Bundle values, FacebookException exception) {
379
387
public void run () {
380
388
WebDialog feedDialog = (new WebDialog .FeedDialogBuilder (me .cordova .getActivity (), Session .getActiveSession (), paramBundle )).setOnCompleteListener (dialogCallback ).build ();
381
389
feedDialog .show ();
382
- };
383
-
390
+ }
384
391
};
385
392
cordova .getActivity ().runOnUiThread (runnable );
386
393
} else if (this .method .equalsIgnoreCase ("apprequests" )) {
387
394
Runnable runnable = new Runnable () {
388
395
public void run () {
389
396
WebDialog requestsDialog = (new WebDialog .RequestsDialogBuilder (me .cordova .getActivity (), Session .getActiveSession (), paramBundle )).setOnCompleteListener (dialogCallback )
390
- .build ();
397
+ .build ();
391
398
requestsDialog .show ();
392
- };
399
+ }
393
400
};
394
401
cordova .getActivity ().runOnUiThread (runnable );
395
402
} else if (this .method .equalsIgnoreCase ("share" ) || this .method .equalsIgnoreCase ("share_open_graph" )) {
396
- cordova .getActivity ().runOnUiThread (new WebDialogBuilderRunnable (me .cordova .getActivity (), Session .getActiveSession (), this .method , paramBundle , dialogCallback ));
403
+ if (FacebookDialog .canPresentShareDialog (me .cordova .getActivity (), FacebookDialog .ShareDialogFeature .SHARE_DIALOG )) {
404
+ Runnable runnable = new Runnable () {
405
+ public void run () {
406
+ // Publish the post using the Share Dialog
407
+ FacebookDialog shareDialog = new FacebookDialog .ShareDialogBuilder (me .cordova .getActivity ())
408
+ .setName (paramBundle .getString ("name" ))
409
+ .setCaption (paramBundle .getString ("caption" ))
410
+ .setDescription (paramBundle .getString ("description" ))
411
+ .setLink (paramBundle .getString ("link" ))
412
+ .setPicture (paramBundle .getString ("picture" ))
413
+ .build ();
414
+ uiHelper .trackPendingDialogCall (shareDialog .present ());
415
+ }
416
+ };
417
+ this .trackingPendingCall = true ;
418
+ cordova .getActivity ().runOnUiThread (runnable );
419
+ } else {
420
+ // Fallback. For example, publish the post using the Feed Dialog
421
+ Runnable runnable = new Runnable () {
422
+ public void run () {
423
+ WebDialog feedDialog = (new WebDialog .FeedDialogBuilder (me .cordova .getActivity (), Session .getActiveSession (), paramBundle )).setOnCompleteListener (dialogCallback ).build ();
424
+ feedDialog .show ();
425
+ }
426
+ };
427
+ cordova .getActivity ().runOnUiThread (runnable );
428
+ }
397
429
} else {
398
430
callbackContext .error ("Unsupported dialog method." );
399
431
}
@@ -407,7 +439,7 @@ public void run() {
407
439
graphPath = args .getString (0 );
408
440
409
441
JSONArray arr = args .getJSONArray (1 );
410
-
442
+
411
443
final List <String > permissionsList = new ArrayList <String >();
412
444
for (int i = 0 ; i < arr .length (); i ++) {
413
445
permissionsList .add (arr .getString (i ));
@@ -458,6 +490,51 @@ public void run() {
458
490
return false ;
459
491
}
460
492
493
+ private void handleError (Exception exception ) {
494
+ String errMsg = "Facebook error: " + exception .getMessage ();
495
+ // User clicked "x"
496
+ if (exception instanceof FacebookOperationCanceledException ) {
497
+ errMsg = "User cancelled dialog" ;
498
+ } else if (exception instanceof FacebookDialogException ) {
499
+ // Dialog error
500
+ errMsg = "Dialog error: " + exception .getMessage ();
501
+ } else if (exception instanceof FacebookServiceException ) {
502
+ FacebookRequestError error = ((FacebookServiceException ) exception ).getRequestError ();
503
+ if (error .getErrorCode () == 4201 ) {
504
+ // User hit the cancel button in the WebView
505
+ // Tried error.getErrorMessage() but it returns null
506
+ // if though the URL says:
507
+ // Redirect URL: fbconnect://success?error_code=4201&error_message=User+canceled+the+Dialog+flow
508
+ errMsg = "User cancelled dialog" ;
509
+ }
510
+ }
511
+ Log .e (TAG , errMsg );
512
+ showDialogContext .error (errMsg );
513
+ }
514
+
515
+ private void handleSuccess (Bundle values ) {
516
+ // Handle a successful dialog:
517
+ // Send the URL parameters back, for a requests dialog, the "request" parameter
518
+ // will include the resulting request id. For a feed dialog, the "post_id"
519
+ // parameter will include the resulting post id.
520
+ // Note: If the user clicks on the Cancel button, the parameter will be empty
521
+ if (values .size () > 0 ) {
522
+ JSONObject response = new JSONObject ();
523
+ try {
524
+ Set <String > keys = values .keySet ();
525
+ for (String key : keys ) {
526
+ response .put (key , values .get (key ));
527
+ }
528
+ } catch (JSONException e ) {
529
+ e .printStackTrace ();
530
+ }
531
+ showDialogContext .success (response );
532
+ } else {
533
+ Log .e (TAG , "User cancelled dialog" );
534
+ showDialogContext .error ("User cancelled dialog" );
535
+ }
536
+ }
537
+
461
538
private void getUserInfo (final Session session ) {
462
539
if (cordova != null ) {
463
540
Request .newMeRequest (session , new Request .GraphUserCallback () {
@@ -496,7 +573,7 @@ public void onCompleted(Response response) {
496
573
}
497
574
}
498
575
};
499
-
576
+
500
577
//If you're using the paging URLs they will be URLEncoded, let's decode them.
501
578
try {
502
579
graphPath = URLDecoder .decode (graphPath , "UTF-8" );
@@ -550,50 +627,50 @@ private void onSessionStateChange(SessionState state, Exception exception) {
550
627
private boolean isPublishPermission (String permission ) {
551
628
return permission != null && (permission .startsWith (PUBLISH_PERMISSION_PREFIX ) || permission .startsWith (MANAGE_PERMISSION_PREFIX ) || OTHER_PUBLISH_PERMISSIONS .contains (permission ));
552
629
}
553
-
630
+
554
631
/**
555
632
* Create a Facebook Response object that matches the one for the Javascript SDK
556
633
* @return JSONObject - the response object
557
634
*/
558
635
public JSONObject getResponse () {
559
- String response ;
560
- Session session = Session .getActiveSession ();
561
- if (session != null && session .isOpened ()) {
562
- Date today = new Date ();
563
- long expiresTimeInterval = (session .getExpirationDate ().getTime () - today .getTime ()) / 1000L ;
564
- long expiresIn = (expiresTimeInterval > 0 ) ? expiresTimeInterval : 0 ;
565
- response = "{" +
566
- "\" status\" : \" connected\" ," +
567
- "\" authResponse\" : {" +
568
- "\" accessToken\" : \" " + session .getAccessToken ()+ "\" ," +
569
- "\" expiresIn\" : \" " + expiresIn + "\" ," +
570
- "\" session_key\" : true," +
571
- "\" sig\" : \" ...\" ," +
572
- "\" userID\" : \" " + this .userID + "\" " +
573
- "}" +
574
- "}" ;
575
- } else {
576
- response = "{" +
577
- "\" status\" : \" unknown\" " +
578
- "}" ;
579
- }
580
-
581
- try {
582
- return new JSONObject (response );
583
- } catch (JSONException e ) {
584
-
585
- e .printStackTrace ();
586
- }
587
- return new JSONObject ();
588
- }
589
-
636
+ String response ;
637
+ Session session = Session .getActiveSession ();
638
+ if (session != null && session .isOpened ()) {
639
+ Date today = new Date ();
640
+ long expiresTimeInterval = (session .getExpirationDate ().getTime () - today .getTime ()) / 1000L ;
641
+ long expiresIn = (expiresTimeInterval > 0 ) ? expiresTimeInterval : 0 ;
642
+ response = "{"
643
+ + "\" status\" : \" connected\" ,"
644
+ + "\" authResponse\" : {"
645
+ + "\" accessToken\" : \" " + session .getAccessToken () + "\" ,"
646
+ + "\" expiresIn\" : \" " + expiresIn + "\" ,"
647
+ + "\" session_key\" : true,"
648
+ + "\" sig\" : \" ...\" ,"
649
+ + "\" userID\" : \" " + this .userID + "\" "
650
+ + "}"
651
+ + "}" ;
652
+ } else {
653
+ response = "{"
654
+ + "\" status\" : \" unknown\" "
655
+ + "}" ;
656
+ }
657
+
658
+ try {
659
+ return new JSONObject (response );
660
+ } catch (JSONException e ) {
661
+
662
+ e .printStackTrace ();
663
+ }
664
+ return new JSONObject ();
665
+ }
666
+
590
667
private class WebDialogBuilderRunnable implements Runnable {
591
668
private Context context ;
592
669
private Session session ;
593
670
private String method ;
594
671
private Bundle paramBundle ;
595
672
private OnCompleteListener dialogCallback ;
596
-
673
+
597
674
public WebDialogBuilderRunnable (Context context , Session session , String method , Bundle paramBundle , OnCompleteListener dialogCallback ) {
598
675
this .context = context ;
599
676
this .session = session ;
0 commit comments