Android Facebook Log In with AWS Cognito - android

I'm having trouble authenticating users with Facebook and creating a single new identity with AWS Cognito. Then if that user deletes the app and re-downloads it I want Cognito to return the same identity.
Facebook login works but credentialsProvider.setLogins(logins); creates 4 NEW unauthenticated identities every time.
final CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(getApplicationContext(), "xxxxxxxx", Regions.US_EAST_1);
loginButton = (LoginButton) findViewById(R.id.login_button);
loginButton.setReadPermissions(Arrays.asList("email", "user_friends"));
callbackManager = CallbackManager.Factory.create();
accessTokenTracker = new AccessTokenTracker() {
#Override
protected void onCurrentAccessTokenChanged(
AccessToken oldAccessToken,
AccessToken currentAccessToken) {
updateWithToken(currentAccessToken);
}
};
loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
Map<String, String> logins = new HashMap<String, String>();
logins.put("graph.facebook.com", AccessToken.getCurrentAccessToken().getToken());
credentialsProvider.setLogins(logins);
Log.d("LogTag", "my ID is " + logins);
}
#Override
public void onCancel() {
Toast.makeText(getBaseContext(), "Login Cancelled", Toast.LENGTH_SHORT).show();
Log.v("LoginActivity", "cancel");
}
#Override
public void onError(FacebookException exception) {
Toast.makeText(getBaseContext(), "Problem connecting to Facebook", Toast.LENGTH_SHORT).show();
Log.v("LoginActivity", exception.getCause().toString());
}
});
}
private void updateWithToken(AccessToken token) {
if (token != null) {
Intent intent = new Intent(LogIn.this, NavDrawer.class);
LogIn.this.startActivity(intent);
}
;
}
#Override
public void onDestroy() {
super.onDestroy();
accessTokenTracker.stopTracking();
}
#Override
protected void onResumeFragments() {
super.onResumeFragments();
updateWithToken(AccessToken.getCurrentAccessToken());
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
Intent intent = new Intent(LogIn.this, Buffer.class);
LogIn.this.startActivity(intent);
}
}
Any help would be amazing, thanks you!

I can see you are starting a new activity every time your access token from Facebook is updated. That mean you are creating different instances of CognitoCachingCredentialsProvider every time, which is not right.
Ideally you should have CognitoCachingCredentialsProvider as a singleton in your application and use is in all you activities and app logic. You can use the Cognito sample application as an example to model the flow.

Related

How do I use SharedPreferences with Facebook SDK?

Currently this is how my FB login looks like:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
TAG = "Login.Activity";
//Callback manager manages callbacks into the FB SDK from an Activity's onActivityResult() Method.
callbackManager = CallbackManager.Factory.create();
loginButton = (LoginButton) findViewById(R.id.login_button);
loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
//If login in successful,
#Override
public void onSuccess(LoginResult loginResult) {
Profile profile = Profile.getCurrentProfile();
goMainScreen(profile);
}
#Override
public void onCancel() {
Toast.makeText(getApplicationContext(),R.string.cancel_login, Toast.LENGTH_LONG).show();
}
#Override
public void onError(FacebookException error) {
Toast.makeText(getApplicationContext(), R.string.error_login, Toast.LENGTH_LONG).show();
}
});
}
private void goMainScreen(Profile profile) {
if(profile != null){
//Passing in the name,id and photo from the profile.
Intent intent = new Intent(this, MainActivity.class);
// intent.putExtra("name",profile.getName());
intent.putExtra("id",profile.getId());
intent.putExtra("photo",profile.getProfilePictureUri(200,200));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
#Override
//All Request Code, Result Code, and data are recieved by the activity
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode,resultCode,data);
callbackManager.onActivityResult(requestCode,resultCode,data);
}
}
I would like to keep track of the user session throughout other activities and know if they have logged in before.Would I use sharedpreferences for this? If so will I be doing this at the beginning of the loginActivity?
Well you could use what provide the SDK and create a method like this one :
public boolean isLoggedIn() {
AccessToken accessToken = AccessToken.getCurrentAccessToken();
return accessToken != null;
}

Dismiss facebook login dialog android

I've integrated facebook sdk v-4 with my android app. Here I've worked facebook login in 2 activities.
1) In one activity fb login is done via LoginButton. Where after successful login the fb login dialog is dismissed by facebook sdk automatically.
code:
fbLoginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
ProfileTracker profileTracker;
#Override
public void onSuccess(LoginResult loginResult) {
Logger.d("FBLOGIN", "login successful. User ID: "
+ loginResult.getAccessToken().getUserId()
+ "\n" +
"Auth Token: "
+ loginResult.getAccessToken().getToken());
com.facebook.Profile fbProfile = com.facebook.Profile.getCurrentProfile();
if (fbProfile == null) {
profileTracker = new ProfileTracker() {
#Override
protected void onCurrentProfileChanged(com.facebook.Profile oldProfile, com.facebook.Profile currentProfile) {
profileTracker.stopTracking();
doTaskWithFbProfile(currentProfile);
}
};
profileTracker.startTracking();
} else {
doTaskWithFbProfile(fbProfile);
}
}
#Override
public void onCancel() {
Logger.d(TAG, "fb Login attempt canceled.");
}
#Override
public void onError(FacebookException e) {
Logger.e(TAG, "fb Login attempt failed." + e);
Toast.makeText(LoginActivity.this,R.string.str_please_check_your_internet_connection,Toast.LENGTH_LONG).show();
}
});
private void doTaskWithFbProfile(com.facebook.Profile fbProfile) {
Logger.d("FBLOGIN", "id - " + fbProfile.getId());
Logger.d("FBLOGIN", "name - " + fbProfile.getName());
Logger.d("FBLOGIN", "pic - " + fbProfile.getProfilePictureUri(150, 150));
com.android.circlecare.models.common.Profile profile = new com.android.circlecare.models.common.Profile();
profile.setFBID(fbProfile.getId());
profile.setName(fbProfile.getName());
profile.setProfilePhoto(fbProfile.getProfilePictureUri(150, 150).toString());
Intent intent = new Intent(this, LoginWithFacebookActivity.class);
intent.putExtra(LoginWithFacebookActivity.EXTRA_PROFILE, profile);
startActivity(intent);
finish();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
}
2)On the other hand I used LoginManager to log in to fb. Where after successful login the login dialog does not get dismissed, instead it stays in front and again after login the dialog doesn't go.
code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(this.getApplicationContext());
mFacebookCallback = new FacebookCallback<LoginResult>() {
ProfileTracker profileTracker;
#Override
public void onSuccess(LoginResult loginResult) {
Profile fbProfile = Profile.getCurrentProfile();
if (fbProfile == null) {
profileTracker = new ProfileTracker() {
#Override
protected void onCurrentProfileChanged(Profile oldProfile, Profile currentProfile) {
profileTracker.stopTracking();
getAllFriends();
}
};
profileTracker.startTracking();
} else {
getAllFriends();
}
}
#Override
public void onCancel() {
Logger.d(TAG, "fb Login attempt canceled.");
}
#Override
public void onError(FacebookException error) {
Logger.d(TAG, "Error : " + error.getMessage());
finish();
}
};
callbackManager = CallbackManager.Factory.create();
if (hasAccess)
getAllFriends();
else
loginWorks();
}
private void loginWorks() {
loginManager = LoginManager.getInstance();
loginManager.registerCallback(callbackManager, mFacebookCallback);
ArrayList<String> publishPermission = new ArrayList<>();
publishPermission.add("publish_pages");
publishPermission.add("publish_actions");
loginManager.logInWithPublishPermissions(this, publishPermission);
ArrayList<String> readPermission = new ArrayList<>();
readPermission.add("user_friends");
readPermission.add("public_profile");
readPermission.add("user_about_me");
loginManager.logInWithReadPermissions(this, readPermission);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
I've used almost same codes in both the cases, but I wonder why login dialog isn't get dismissed when working with LoginManager.
Can any one point out the problem or is there any api to dismiss fb login dialog(web view).
In your loginWorks() method, you're literally calling login twice, which is probably actually showing 2 different login screens, and why it looks like the dialog is not dismissing after you finish one of them. Try removing the loginWithPublishPermissions call, and put it in the callback from the read permissions call if you really need it.

Android Facebook - get null profile

First time with Facebook SDK. I can't get users profile. Its always null. What's wrong?
btnFbWidget = (LoginButton) findViewById(R.id.btnFbWidget);
btnFbWidget.setReadPermissions("public_profile");
// Callback registration
btnFbWidget.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
Profile profile = Profile.getCurrentProfile();
if (profile != null)
Toast.makeText(getApplicationContext(), "LogIN as " + profile.getName(), Toast.LENGTH_SHORT).show();
else
Toast.makeText(getApplicationContext(), "nulll", Toast.LENGTH_SHORT).show();
}
/*...*/
});
use this method also,.....
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
Try with this method.
Initialize facebook SDK firstly.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//init facebook sdk and
FacebookSdk.sdkInitialize(getApplicationContext());
setContentView(R.layout.activity_main);
//instantiate callbacks manager
mCallbackManager = CallbackManager.Factory.create();
btnFbWidget=(LoginButton)findViewById(R.id.login_button);
btnFbWidget.registerCallback(mCallbackManager, this);
btnFbWidget.setReadPermissions(Arrays.asList("user_status","email"));
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//manage login result
mCallbackManager.onActivityResult(requestCode, resultCode, data);
}
public void onSuccess(LoginResult loginResults) {
Toast.makeText(getApplicationContext(), "Success ",
Toast.LENGTH_LONG).show();
}
public void onCancel() {
}
public void onError(FacebookException e) {
}
And then to get the User Profile use this method.
private static String uid,email;
public void getUserProfile() {
GraphRequest request = GraphRequest.newMeRequest(
AccessToken.getCurrentAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(
JSONObject object,
GraphResponse response) {
// Application code
Log.v("LoginActivity", response.toString());
try {
//and fill them here like so.
uid = object.getString("id");
email = object.getString("email")
} catch (JSONException e) {
e.printStackTrace();
}
getGroups();
}
});
// If you want to pass data to other activity.
Bundle parameters = new Bundle();
parameters.putString("userdata", "email");
request.setParameters(parameters);
request.executeAsync();
}
And do call this method getUserProfile() in your on create.
EDIT 1 :
Change in read permissions.
btnFbWidget.setReadPermissions(Arrays.asList("public_profile", "email", "user_birthday", "user_friends"));
And accordingly you can get further information like.
String email = object.getString("email");
String birthday = object.getString("birthday");

Facebook Login Not Returning User access_token

This is my first post, so please let me know if I'm not abiding by the community rules.
Now to the problem! I've been trying to setup the Facebook login process for an app and I've gotten as far as adding a GUI element (the built-in Facebook login button), and having the button go ahead and ask for a user/pass, granting the app access to the user's account. The problem I'm facing is that when using the following code to get a callback value from the app I receive nothing (no value being printed). Right now I'm printing to LogCat arbitrary values, however as soon as printing works, I look to access the user access_token and other information (which didn't initially work). Any help appreciated!
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_connect_accounts);
Log.i("fromMe", "test1");
FacebookSdk.sdkInitialize(this.getApplicationContext());
callbackManager = CallbackManager.Factory.create();
LoginButton loginButton = (LoginButton)findViewById(R.id.login_button);
loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>(){
public void onSuccess(LoginResult loginResult) {
Log.i("fromMe", "1");
}
public void onCancel() {
Log.i("fromMe", "2");
}
public void onError(FacebookException exception) {
Log.i("fromMe", "3");
}
});
}
if Log.i("fromMe", "1");work so you can call :
AccessToken accessToken = loginResult.getAccessToken();
in your onSuccess().
And in onActivityResult(int requestCode, int resultCode, Intent data)
add :
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
I never used the built-in facebook button ,instead i used the normal button with a click a listener. and i call this method in the onClick().
myButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
//Starting facebook signIN
startFbSignIn();
}
});
startFbSignIn();
private void startFbSignIn() {
List<String> permissions = new ArrayList<>();
permissions.add("email");
Session.openActiveSession(this, true, permissions, new Session.StatusCallback() {
#Override
public void call(final Session session, SessionState sessionState, Exception e) {
Log.d("X", "Call Called");
if (session.isOpened()) {
Log.d("X", "SessionOpened" + session.getAccessToken());
//Showing some loading
Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser graphUser, Response response) {
//FACEBOOOK SIGNIN SUCCESS
Log.i("X", "Facebook Login Success");
//Log
Log.d("X", "GRAPH USER:" + graphUser.toString());
String name = graphUser.getName();
//.....
}
}).executeAsync();
} else {
Log.d("X", "SessioNOTopened");
}
}
});
}
The above method successfully working for me and your onActivityResult() must look something like this
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//Facebook Session Manager
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}
Probably cause of a bug in the facebook SDK you cannot directly get the accessToken. We need to create an accessToken tracker and then get the accessToken
private AccessTokenTracker accessTokenTracker;
accessTokenTracker = new AccessTokenTracker() {
#Override
protected void onCurrentAccessTokenChanged(AccessToken oldAccessToken, AccessToken newAccessToken) {
try {
if (newAccessToken.getToken() != null) {
facebookAccessToken = newAccessToken.getToken();
//this is your accessToken here
}
else if (oldAccessToken.getToken() != null) {
facebookAccessToken = oldAccessToken.getToken();
//this is your accessToken here
}else {
Toast.makeText(getBaseContext(), "Facebook Login Failed", Toast.LENGTH_LONG).show();
}
if(oldAccessToken.getToken()!=null)
Log.e("old", oldAccessToken.getToken());
}catch (Exception e){
e.printStackTrace();
}
}
};
once this is successfully done, overide the onStop method of the activity and make sure you stoptracking the accessToken there.
accessTokenTracker.stopTracking();

How to re-ask declined permissions in Facebook SDK 4.0 (android)

I checked below. It is very similar but it is not same my problem.
How to re-request permissions in Facebook SDK 4.0
I got permissions in this code.
LoginManager.getInstance().logInWithReadPermissions(*fragment*, "user_friends");
If a user reject "user_friends" permission, I can't re-ask "user_friends" permissions above code. Because automatically rejected on next authentication.
What actions should I do to get "user_friends" programmatically?
its simple just use
LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
Log.e(TAG, "LoginManager FacebookCallback onSuccess");
if (loginResult.getAccessToken() != null) {
Set<String> deniedPermissions = loginResult.getRecentlyDeniedPermissions();
if (deniedPermissions.contains("user_friends")) {
LoginManager.getInstance().logInWithReadPermissions(MainActivity.this, Arrays.asList("user_friends"));
}
}
}
#Override
public void onCancel() {
Log.e(TAG, "LoginManager FacebookCallback onCancel");
}
#Override
public void onError(FacebookException e) {
Log.e(TAG, "LoginManager FacebookCallback onError");
}
});
and do not forget to initialize fb SDK before you call setContentView(R.layout.main)
i.e
// Create callback manager to handle login response
FacebookSdk.sdkInitialize(getApplicationContext());
callbackManager = CallbackManager.Factory.create();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fb = (ImageView) findViewById(R.id.authFacebook);
setFacebookData(savedInstanceState);
fb.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
LoginManager.getInstance().logInWithReadPermissions(MainActivity.this, Arrays.asList("public_profile", "email"));
}
});
}
private void setFacebookData(Bundle savedInstanceState) {
FacebookSdk.sdkInitialize(MainActivity.this);
callbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult result) {
Log.i("LoginActivity","onSuccess Facebook Login"+result);
GraphRequest request = GraphRequest.newMeRequest(
AccessToken.getCurrentAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject jsonObject, GraphResponse response) {
Log.d("","onCompleted jsonObject: "+jsonObject);
Log.d("","onCompleted response: "+response);
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,link,cover,email");
request.setParameters(parameters);
request.executeAsync();
}
#Override
public void onCancel() {
// TODO Auto-generated method stub
}
#Override
public void onError(FacebookException e) {
// TODO Auto-generated method stub
Log.e("LoginActivity","ERROR: "+e.getMessage());
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("FbLogin", "Result Code is = " + resultCode +"");
callbackManager.onActivityResult(requestCode, resultCode, data);
}
In Manifest File add these lines
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/app_id" />
<provider
android:name="com.facebook.FacebookContentProvider"
android:authorities="com.facebook.app.FacebookContentProvider355198514515820"
android:exported="true" />
<receiver android:name="laddu.fbexample.HelloFacebookBroadcastReceiver" >
<intent-filter>
<action android:name="com.facebook.platform.AppCallResultBroadcast" />
</intent-filter>
</receiver>
Solution by user2403096 works well, but I've encountered some problem and spent some time to resolve it. If User revoked some permission through console or somehow else and you need it in your app during login (e.g. I need email permission) I use code by user2403096 :
LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
if (loginResult.getRecentlyDeniedPermissions().contains("email")) {
LoginManager.getInstance().logInWithReadPermissions(
this, (Collections.singletonList("email")));
} else {
performGraphRequest();
}
}
#Override
public void onCancel() {
Log.e(TAG, "LoginManager FacebookCallback onCancel");
}
#Override
public void onError(FacebookException e) {
Log.e(TAG, "LoginManager FacebookCallback onError");
}
});
performGraprhRequest() just obtains profile info with GraphRequest.newMeRequest(token, callback). So when you re-requesting permission there will be callback into onActivityResult but onSuccess(), onCancel() or onError() will NOT be called again. My approach is:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
boolean processed = mCallbackManager.onActivityResult(requestCode, resultCode, data);
if (!processed) {
performGraphRequest();
}
}
If you login into facebook and enter your credentials - onActivityResult will be processed by CallbackManager and will return true. CallbackManager under the hood checks whether your current AccessToken null or not and if you already logged in and then you re-ask permission - you will have token and callbackManager.onActivityResult return false. Then you can invoke performGraphRequest and login user into your app.
Just an improvement to #Naveedumar 's answer
You can also do
LoginManager.getInstance()
.logInWithReadPermissions(MainActivity.this,
new ArrayList<String>(AccessToken.getCurrentAccessToken().getDeclinedPermissions()) );

Categories

Resources