Skip to content

Commit a948725

Browse files
author
aogilvie
committed
Merge branch 'master' of github.com:wizcorp/phonegap-facebook-plugin
2 parents 26c2755 + 0ccdfb3 commit a948725

File tree

6 files changed

+183
-96
lines changed

6 files changed

+183
-96
lines changed

README.md

+9-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ The Facebook plugin for [Apache Cordova](http://incubator.apache.org/cordova/) a
88
* This plugin is built for
99
* iOS FacebookSDK 3.16.1
1010
* Android FacebookSDK 3.16.0
11+
* GitHub URL : [https://github.com/Wizcorp/phonegap-facebook-plugin/](https://github.com/Wizcorp/phonegap-facebook-plugin/)
12+
13+
## << --- Cordova Registry Warning [iOS]
14+
15+
****Installing this plugin directly from Cordova Registry results in Xcode using a broken `Facebook.framework`, this is because the current publish procedure to NPM breaks symlinks [CB-6092](https://issues.apache.org/jira/browse/CB-6092). Please re-add facebook.framework to Xcode.****
16+
17+
## ------------------------------------------ >>
18+
19+
------------------------------------------
1120

1221
## Facebook Requirements and Set-Up
1322

@@ -25,11 +34,6 @@ To use this plugin you will need to make sure you've registered your Facebook ap
2534

2635
`platforms/android` and `platforms/ios` contain example projects and all the native code for the plugin for both Android and iOS platforms. They also include versions of the Android and iOS Facebook SDKs. These are used during automatic installation.
2736

28-
#### Adobe PhoneGap Build
29-
30-
If using this plugin on Adobe PhoneGap Build you can ignore the instructions below and go straight to the
31-
PhoneGap Build documentation available [here] (https://build.phonegap.com/plugins/257).
32-
3337
## API
3438

3539
### Login

platforms/android/AndroidManifest.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="0.0.1" android:windowSoftInputMode="adjustPan" package="io.cordova.hellocordova" xmlns:android="http://schemas.android.com/apk/res/android">
33
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
44
<uses-permission android:name="android.permission.INTERNET" />
5-
<application android:debuggable="true" android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name">
5+
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" />
6+
<application android:allowBackup="false" android:icon="@drawable/icon" android:label="@string/app_name">
67
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/app_name" android:name="HelloCordova" android:theme="@android:style/Theme.Black.NoTitleBar">
78
<intent-filter>
89
<action android:name="android.intent.action.MAIN" />
910
<category android:name="android.intent.category.LAUNCHER" />
1011
</intent-filter>
1112
</activity>
1213
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/fb_app_id" />
13-
<activity android:label="@string/fb_app_name" android:name="com.facebook.LoginActivity" />
14+
<activity android:label="@string/fb_app_name" android:name="com.facebook.LoginActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
1415
</application>
15-
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" />
1616
</manifest>

platforms/android/src/org/apache/cordova/facebook/ConnectPlugin.java

+157-80
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@
3030
import com.facebook.FacebookDialogException;
3131
import com.facebook.FacebookException;
3232
import com.facebook.FacebookOperationCanceledException;
33+
import com.facebook.FacebookRequestError;
34+
import com.facebook.FacebookServiceException;
3335
import com.facebook.Request;
3436
import com.facebook.Response;
3537
import com.facebook.Session;
3638
import com.facebook.SessionState;
39+
import com.facebook.UiLifecycleHelper;
3740
import com.facebook.model.GraphObject;
3841
import com.facebook.model.GraphUser;
42+
import com.facebook.widget.FacebookDialog;
3943
import com.facebook.widget.WebDialog;
4044
import com.facebook.widget.WebDialog.OnCompleteListener;
4145

@@ -62,9 +66,13 @@ public class ConnectPlugin extends CordovaPlugin {
6266
private String method;
6367
private String graphPath;
6468
private String userID;
69+
private UiLifecycleHelper uiHelper;
70+
private boolean trackingPendingCall = false;
6571

6672
@Override
6773
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
74+
//Initialize UiLifecycleHelper
75+
uiHelper = new UiLifecycleHelper(cordova.getActivity(), null);
6876

6977
// Init logger
7078
logger = AppEventsLogger.newLogger(cordova.getActivity());
@@ -102,15 +110,51 @@ public void call(Session session, SessionState state, Exception exception) {
102110
@Override
103111
public void onResume(boolean multitasking) {
104112
super.onResume(multitasking);
113+
uiHelper.onResume();
105114
// Developers can observe how frequently users activate their app by logging an app activation event.
106115
AppEventsLogger.activateApp(cordova.getActivity());
107116
}
108117

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+
109132
@Override
110133
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
111134
super.onActivityResult(requestCode, resultCode, intent);
112135
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;
114158
}
115159

116160
@Override
@@ -248,7 +292,7 @@ public void call(Session session, SessionState state, Exception exception) {
248292
Bundle parameters = new Bundle();
249293

250294
Iterator<?> iterator = params.keys();
251-
while (iterator.hasNext() ) {
295+
while (iterator.hasNext()) {
252296
try {
253297
// Try get a String
254298
String value = params.getString((String) iterator.next());
@@ -330,46 +374,10 @@ public void call(Session session, SessionState state, Exception exception) {
330374

331375
@Override
332376
public void onComplete(Bundle values, FacebookException exception) {
333-
String errMsg;
334377
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);
351379
} 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);
373381
}
374382
}
375383
};
@@ -379,21 +387,45 @@ public void onComplete(Bundle values, FacebookException exception) {
379387
public void run() {
380388
WebDialog feedDialog = (new WebDialog.FeedDialogBuilder(me.cordova.getActivity(), Session.getActiveSession(), paramBundle)).setOnCompleteListener(dialogCallback).build();
381389
feedDialog.show();
382-
};
383-
390+
}
384391
};
385392
cordova.getActivity().runOnUiThread(runnable);
386393
} else if (this.method.equalsIgnoreCase("apprequests")) {
387394
Runnable runnable = new Runnable() {
388395
public void run() {
389396
WebDialog requestsDialog = (new WebDialog.RequestsDialogBuilder(me.cordova.getActivity(), Session.getActiveSession(), paramBundle)).setOnCompleteListener(dialogCallback)
390-
.build();
397+
.build();
391398
requestsDialog.show();
392-
};
399+
}
393400
};
394401
cordova.getActivity().runOnUiThread(runnable);
395402
} 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+
}
397429
} else {
398430
callbackContext.error("Unsupported dialog method.");
399431
}
@@ -407,7 +439,7 @@ public void run() {
407439
graphPath = args.getString(0);
408440

409441
JSONArray arr = args.getJSONArray(1);
410-
442+
411443
final List<String> permissionsList = new ArrayList<String>();
412444
for (int i = 0; i < arr.length(); i++) {
413445
permissionsList.add(arr.getString(i));
@@ -458,6 +490,51 @@ public void run() {
458490
return false;
459491
}
460492

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+
461538
private void getUserInfo(final Session session) {
462539
if (cordova != null) {
463540
Request.newMeRequest(session, new Request.GraphUserCallback() {
@@ -496,7 +573,7 @@ public void onCompleted(Response response) {
496573
}
497574
}
498575
};
499-
576+
500577
//If you're using the paging URLs they will be URLEncoded, let's decode them.
501578
try {
502579
graphPath = URLDecoder.decode(graphPath, "UTF-8");
@@ -550,50 +627,50 @@ private void onSessionStateChange(SessionState state, Exception exception) {
550627
private boolean isPublishPermission(String permission) {
551628
return permission != null && (permission.startsWith(PUBLISH_PERMISSION_PREFIX) || permission.startsWith(MANAGE_PERMISSION_PREFIX) || OTHER_PUBLISH_PERMISSIONS.contains(permission));
552629
}
553-
630+
554631
/**
555632
* Create a Facebook Response object that matches the one for the Javascript SDK
556633
* @return JSONObject - the response object
557634
*/
558635
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+
590667
private class WebDialogBuilderRunnable implements Runnable {
591668
private Context context;
592669
private Session session;
593670
private String method;
594671
private Bundle paramBundle;
595672
private OnCompleteListener dialogCallback;
596-
673+
597674
public WebDialogBuilderRunnable(Context context, Session session, String method, Bundle paramBundle, OnCompleteListener dialogCallback) {
598675
this.context = context;
599676
this.session = session;

0 commit comments

Comments
 (0)