31
31
import com .facebook .login .LoginManager ;
32
32
import com .facebook .login .LoginResult ;
33
33
import com .firebase .ui .auth .AuthUI ;
34
- import com .firebase .ui .auth .BuildConfig ;
35
34
import com .firebase .ui .auth .IdpResponse ;
36
35
import com .firebase .ui .auth .R ;
37
36
import com .google .firebase .auth .AuthCredential ;
45
44
46
45
public class FacebookProvider implements IdpProvider , FacebookCallback <LoginResult > {
47
46
private static final String TAG = "FacebookProvider" ;
48
- protected static final String ERROR = "err" ;
49
- protected static final String ERROR_MSG = "err_msg" ;
50
47
private static final String EMAIL = "email" ;
51
48
private static final String PUBLIC_PROFILE = "public_profile" ;
52
- private static final CallbackManager CALLBACK_MANAGER = CallbackManager .Factory .create ();
49
+ private static final String ERROR = "err" ;
50
+ private static final String ERROR_MSG = "err_msg" ;
51
+
52
+ private static CallbackManager sCallbackManager ;
53
53
54
54
private final List <String > mScopes ;
55
+ // DO NOT USE DIRECTLY: see onSuccess(String, LoginResult) and onFailure(Bundle) below
55
56
private IdpCallback mCallbackObject ;
56
57
57
58
public FacebookProvider (Context appContext , AuthUI .IdpConfig idpConfig , @ StyleRes int theme ) {
@@ -86,8 +87,9 @@ public String getProviderId() {
86
87
87
88
@ Override
88
89
public void startLogin (Activity activity ) {
90
+ sCallbackManager = CallbackManager .Factory .create ();
89
91
LoginManager loginManager = LoginManager .getInstance ();
90
- loginManager .registerCallback (CALLBACK_MANAGER , this );
92
+ loginManager .registerCallback (sCallbackManager , this );
91
93
92
94
List <String > permissionsList = new ArrayList <>(mScopes );
93
95
@@ -111,18 +113,11 @@ public void setAuthenticationCallback(IdpCallback callback) {
111
113
112
114
@ Override
113
115
public void onActivityResult (int requestCode , int resultCode , Intent data ) {
114
- CALLBACK_MANAGER .onActivityResult (requestCode , resultCode , data );
116
+ sCallbackManager .onActivityResult (requestCode , resultCode , data );
115
117
}
116
118
117
119
@ Override
118
120
public void onSuccess (final LoginResult loginResult ) {
119
- if (BuildConfig .DEBUG ) {
120
- Log .d (TAG , "Login to facebook successful with Application Id: "
121
- + loginResult .getAccessToken ().getApplicationId ()
122
- + " with Token: "
123
- + loginResult .getAccessToken ().getToken ());
124
- }
125
-
126
121
GraphRequest request = GraphRequest .newMeRequest (
127
122
loginResult .getAccessToken (),
128
123
new GraphRequest .GraphJSONObjectCallback () {
@@ -131,19 +126,19 @@ public void onCompleted(JSONObject object, GraphResponse response) {
131
126
FacebookRequestError requestError = response .getError ();
132
127
if (requestError != null ) {
133
128
Log .e (TAG , "Received Facebook error: " + requestError .getErrorMessage ());
134
- mCallbackObject . onFailure (new Bundle ());
129
+ onFailure (new Bundle ());
135
130
return ;
136
131
}
137
132
if (object == null ) {
138
133
Log .w (TAG , "Received null response from Facebook GraphRequest" );
139
- mCallbackObject . onFailure (new Bundle ());
134
+ onFailure (new Bundle ());
140
135
} else {
141
136
try {
142
137
String email = object .getString ("email" );
143
- mCallbackObject . onSuccess (createIDPResponse ( loginResult , email ) );
138
+ onSuccess (email , loginResult );
144
139
} catch (JSONException e ) {
145
140
Log .e (TAG , "JSON Exception reading from Facebook GraphRequest" , e );
146
- mCallbackObject . onFailure (new Bundle ());
141
+ onFailure (new Bundle ());
147
142
}
148
143
}
149
144
}
@@ -155,27 +150,11 @@ public void onCompleted(JSONObject object, GraphResponse response) {
155
150
request .executeAsync ();
156
151
}
157
152
158
- private IdpResponse createIDPResponse (LoginResult loginResult , String email ) {
159
- return new IdpResponse (
160
- FacebookAuthProvider .PROVIDER_ID ,
161
- email ,
162
- loginResult .getAccessToken ().getToken ());
163
- }
164
-
165
- public static AuthCredential createAuthCredential (IdpResponse response ) {
166
- if (!response .getProviderType ().equals (FacebookAuthProvider .PROVIDER_ID )) {
167
- return null ;
168
- }
169
- return FacebookAuthProvider
170
- .getCredential (response .getIdpToken ());
171
- }
172
-
173
153
@ Override
174
154
public void onCancel () {
175
155
Bundle extra = new Bundle ();
176
156
extra .putString (ERROR , "cancelled" );
177
- mCallbackObject .onFailure (extra );
178
-
157
+ onFailure (extra );
179
158
}
180
159
181
160
@ Override
@@ -184,6 +163,44 @@ public void onError(FacebookException error) {
184
163
Bundle extra = new Bundle ();
185
164
extra .putString (ERROR , "error" );
186
165
extra .putString (ERROR_MSG , error .getMessage ());
187
- mCallbackObject .onFailure (extra );
166
+ onFailure (extra );
167
+ }
168
+
169
+ private IdpResponse createIdpResponse (String email , LoginResult loginResult ) {
170
+ return new IdpResponse (
171
+ FacebookAuthProvider .PROVIDER_ID ,
172
+ email ,
173
+ loginResult .getAccessToken ().getToken ());
174
+ }
175
+
176
+ private void onSuccess (String email , LoginResult loginResult ) {
177
+ gcCallbackManager ();
178
+ mCallbackObject .onSuccess (createIdpResponse (email , loginResult ));
179
+ }
180
+
181
+ private void onFailure (Bundle bundle ) {
182
+ gcCallbackManager ();
183
+ mCallbackObject .onFailure (bundle );
184
+ }
185
+
186
+ private void gcCallbackManager () {
187
+ // sCallbackManager must be static to prevent it from being destroyed if the activity
188
+ // containing FacebookProvider dies.
189
+ // In startLogin(Activity), LoginManager#registerCallback(CallbackManager, FacebookCallback)
190
+ // stores the FacebookCallback parameter--in this case a FacebookProvider instance--into
191
+ // a HashMap in the CallbackManager instance, sCallbackManager.
192
+ // Because FacebookProvider which contains an instance of an activity, mCallbackObject,
193
+ // is contained in sCallbackManager, that activity will not be garbage collected.
194
+ // Thus, we have leaked an Activity.
195
+ sCallbackManager = null ;
196
+ }
197
+
198
+
199
+ public static AuthCredential createAuthCredential (IdpResponse response ) {
200
+ if (!response .getProviderType ().equals (FacebookAuthProvider .PROVIDER_ID )) {
201
+ return null ;
202
+ }
203
+ return FacebookAuthProvider
204
+ .getCredential (response .getIdpToken ());
188
205
}
189
206
}
0 commit comments