I'm follow this tutorial to make a small app to login and say hello + user name.
The issue is: I can only login using my account, but can't log in with other account.
This issue is happen with some sample code require login like HelloFacebookSample or Scrumptious.
The Logcat is not show any error.
So please help me to make it login with other account. Thanks in advance!
EDIT (SOLVED):
I just found the cause: My app is in Sandbox mode, just disable Sandbox mode solved problem. Thanks anyone for helps.
My code:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// start Facebook Login
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
// make request to the /me API
Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null) {
TextView welcome = (TextView) findViewById(R.id.welcome);
welcome.setText("Hello " + user.getName() + "!");
}
}
});
}
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}
}
Screenshot when login with my account: Show hello + my name (Nguyễn Việt Anh)
Screenshot when login with other account: White screen
You can login with different Facebook user id, after that:
Go to developers.facebook.com
choose Apps from Top
select wanted App from left side
select Edit App
disable sandbox mode
This is expected behavior. Essentially the login for facebook is SSO (single sign on) so there is a strong expectation that the user has only one account on their device.
I myself have tried to find a way to get the Facebook SDK to allow the user to sign on to a different account but it doesn't work.
It might be possible fudge it by clearing the caches perhaps but this wouldn't help users who are using the genuine facebook app on their phone.
What I did in the end was went to the web workflow as opposed to native app. I can recommend scribe for this task.
https://github.com/fernandezpablo85/scribe-java
If you do choose to use Scribe, this is my activity for loggin in.
public class FacebookScribeLogin extends FragmentActivity{
private static final String TAG = FacebookScribeLogin.class.getSimpleName();
private final static String CALLBACK = "http://localhost:3000/";
private WebView mWebView;
private ProgressDialog mProgressDialog;
private OAuthService mAuthService;
private SyncStatusUpdaterFragment mSyncStatusUpdaterFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
mWebView = (WebView) findViewById(R.id.webview);
new GetLoginPage().execute();
}
private class GetLoginPage extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... voids) {
//set up service and get request token as seen on scribe website
//https://github.com/fernandezpablo85/scribe-java/wiki/Getting-Started
mAuthService = new ServiceBuilder()
.provider(FacebookApi.class)
.apiKey(getString(R.string.facebook_api_key))
.apiSecret(getString(R.string.facebook_api_secret))
.scope("read_stream, publish_stream, manage_notifications, publish_actions, manage_pages")
.callback(CALLBACK)
.build();
return mAuthService.getAuthorizationUrl(null);
}
#Override
protected void onPostExecute(String authURL) {
//send user to authorization page
android.webkit.CookieManager.getInstance().removeAllCookie();
mWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//check for our custom callback protocol otherwise use default behavior
if (url.startsWith(CALLBACK)) {
GetAccessToken getAccessToken = new GetAccessToken(url);
getAccessToken.execute();
return true;
}
if(mProgressDialog == null){
mProgressDialog = ProgressDialog.show(FacebookScribeLogin.this, null,
String.format(getString(R.string.talking_to_x), getString(R.string.facebook)), true, false);
}
return super.shouldOverrideUrlLoading(view, url);
}
#Override
public void onPageFinished(WebView view, String url) {
if(mProgressDialog != null){
mProgressDialog.hide();
mProgressDialog = null;
}
}
});
mWebView.loadUrl(authURL);
}
}
private class GetAccessToken extends AsyncTask<Void, Void, Void>{
private String mUrl, mToken, mSecret;
private GetAccessToken(String url) {
mUrl = url;
}
#Override
protected Void doInBackground(Void... voids) {
Uri uri = Uri.parse(mUrl);
String verifierStr = uri.getQueryParameter("code");
Verifier verifier = new Verifier(verifierStr);
//save this token for practical use.
Token accessToken = mAuthService.getAccessToken(null, verifier);
mToken = accessToken.getToken();
mSecret = accessToken.getSecret();
return null;
}
#Override
protected void onPostExecute(Void s) {
//mToken - save your mToken somehwere and perhaps use a graph API call for user details
}
}
}
Related
I'm working on an Android application that allows users to share an article via Facebook and/or Twitter. Facebook share works well using ShareDialog, which opens up Facebook share dialog in my application.
The problem I'm having is with posting to Twitter. If the user has a Twitter app installed, share works perfectly. When there is no Twitter app installed on the device, then the Twitter share page is opened in the default browser and user never gets returned to my application after tweeting, which is kind of a bad user experience.
My code for tweet posting is:
Intent intent = new TweetComposer.Builder(context).text("Tweet text.").createIntent();
startActivityForResult(intent, SHARE_ACTION_TWITTER);
I have also tried this:
TweetComposer.Builder builder = new TweetComposer.Builder(this).text("Tweet text.");
builder.show();
Is there a way to get a dialog in my application (similar to Facebook share behavior) when the user does not have the Twitter app installed?
Additionally, for statistics, I would like to know if the user has successfully posted a tweet. How can this be achieved with Fabric Twitter API if user does not have Twitter app installed? Should I use a different API?
The solution was to create a custom webview for tweeting. It doesn't even require the Fabric Twitter API.
Most important part is to create a webview activity:
public class TweetCustomWebView extends AppCompatActivity {
android.webkit.WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview_activity);
Bundle extras = getIntent().getExtras();
if (extras != null) {
final String stringToShow = extras.getString("tweettext");
webView = (android.webkit.WebView) findViewById(R.id.wv);
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(android.webkit.WebView view, String url) {
if (url.contains("latest_status_id=")) {
// Twitted
setResult(Activity.RESULT_OK, new Intent());
TweetCustomWebView.this.finish();
}
view.loadUrl(url);
return true;
}
public void onPageFinished(android.webkit.WebView view, String url) {
// Finished loading url
}
public void onReceivedError(android.webkit.WebView view, int errorCode, String description, String failingUrl) {
Log.e("", "Error: " + description);
setResult(Activity.RESULT_CANCELED, new Intent());
}
});
webView.loadUrl("https://twitter.com/intent/tweet?text=" + stringToShow);
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
setResult(Activity.RESULT_CANCELED, new Intent());
}
}
And a layout like this:
<WebView android:layout_width="match_parent" android:layout_height="match_parent" android:id="#+id/wv"/>
In the AndroidManifest.xml we must add the activity for our webview inside the <application> tag:
<activity android:name=".TweetCustomWebView" />
Last step is to call our vebview when user taps Share on Twitter button:
Intent intent = new Intent(MainActivity.this, TweetCustomWebView.class);
intent.putExtra("tweettext", "Text to tweet");
startActivityForResult(intent, 100);
That should be it. I hope this will help someone.
use below code to post status to twitter.it use's twitter's rest api calls:
i am sharing successfully from my app. it doesn't require twitter app to be installed.
TwitterAuthClient mTwitterAuthClient = new TwitterAuthClient();
mTwitterAuthClient.authorize(this, new Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> result) {
TwitterSession session = result.data;
twitterApiClient = TwitterCore.getInstance().getApiClient(session);
statusesService = twitterApiClient.getStatusesService();
postToTwitter("here goes your share message to post status");
}
}
public void postToTwitter(String Message) {
String message;
StatusesService statusesService = twitterApiClient.getStatusesService();
statusesService.update(message, null, null, null, null, null, null, null, mediaId, new Callback<Tweet>() {
#Override
public void success(Result<Tweet> result) {
//handle success case
}
#Override
public void failure(TwitterException exception) {
//handle failure case
}
});
}
I guess the correct answer is using Update Status API call.
I'm using the latest Twitter SDK version: com.twitter.sdk.android:twitter:3.1.1
public void publishTwitter(final String message) {
final TwitterApiClient apiClient = TwitterCore.getInstance().getApiClient();
final StatusesService statusesService = apiClient.getStatusesService();
final Call<Tweet> update = statusesService.update(message, null, null, null, null, null, null, null, null);
update.enqueue(new com.twitter.sdk.android.core.Callback<Tweet>() {
#Override
public void success(Result<Tweet> result) {
Log.d("TweetTest", "Tweet generated");
}
#Override
public void failure(TwitterException exception) {
Log.e("TweetTest", exception.getLocalizedMessage());
}
});
}
NOTE
The user must be authenticated before calling this API call.
For further details, check this post on Twitter Dev Forum.
Best regards
I'm using this for my Facebook log-in and sharing. I'm wondering if instead of opening a WebView that displays the log-in with Facebookis there a way when a User have already installed a Facebook app instead of opening the WebView it will opens the Facebook app? And when the User is already log-in in the Facebook App it will gets its credentials and log-in automatically in my app? I can't seem to find how to do this. Thank you in advantage.
Edit
I found out that my activityCode always return -1 instead of >= 0 that's why it always open the WebView instead of the app. And also found out that I need to enabled the Single Sign-On, I enabled the Single Sign-On but it still doesn't open the facebook app. Maybe it is because of FORCE_DIALOG_AUTH that always returns -1. I'm wondering if there is a default value instead of using FORCE_DIALOG_AUTH.
In solution on the FORCE_DIALOG_AUTH I used code below:
Instead of using
facebook.authorize(this, Constants.FACEBOOK_PERMISSIONS,
Facebook.FORCE_DIALOG_AUTH, new LoginDialogListener());
I used
facebook.authorize(this, Constants.FACEBOOK_PERMISSIONS, new LoginDialogListener());
where in my Facebook.java
public void authorize(Activity activity, String[] permissions,
final DialogListener listener) {
authorize(activity, permissions, DEFAULT_AUTH_ACTIVITY_CODE, listener);
}
Also it detects now if there is an Facebook app installed or not, but when there is an Facebook app installed it still doesn't display/open in Facebook app, it just load and goes back to my Activity nothing happens.
Update
I tried to log in without a user log-in in the Facebook app and that user is still not authorized to use my app, it opens the Facebook app log-in screen but after authorizing it, it doesn't get my log-in informations.
Here's my code in Facebook.java it same as it is
private boolean startSingleSignOn(Activity activity, String applicationId,
String[] permissions, int activityCode) {
boolean didSucceed = true;
Intent intent = new Intent();
intent.setClassName("com.facebook.katana",
"com.facebook.katana.ProxyAuth");
intent.putExtra("client_id", applicationId);
if (permissions.length > 0) {
intent.putExtra("scope", TextUtils.join(",", permissions));
}
// Verify that the application whose package name is
// com.facebook.katana.ProxyAuth
// has the expected FB app signature.
if (!validateActivityIntent(activity, intent)) {
return false;
}
mAuthActivity = activity;
mAuthPermissions = permissions;
mAuthActivityCode = activityCode;
try {
activity.startActivityForResult(intent, activityCode);
} catch (ActivityNotFoundException e) {
didSucceed = false;
}
return didSucceed;
}
In my activity that calls the authorizing and handles what to do after authorizing here's my code
private void setFacebookConnection() {
// progressBar.setVisibility(View.VISIBLE);
facebook = new Facebook(Constants.FACEBOOK_APP_ID);
facebookAsyncRunner = new AsyncFacebookRunner(facebook);
// facebook.authorize(MerchantDetailsActivity.this, Constants.FACEBOOK_PERMISSIONS,
// Facebook.FORCE_DIALOG_AUTH, new LoginDialogListener());
facebook.authorize(MerchantDetailsActivity.this, Constants.FACEBOOK_PERMISSIONS, new LoginDialogListener());
}
private class LoginDialogListener implements Facebook.DialogListener {
public void onComplete(Bundle values) {
String token = facebook.getAccessToken();
long token_expires = facebook.getAccessExpires();
Log.d(TAG, "AccessToken: " + token);
Log.d(TAG, "AccessExpires: " + token_expires);
facebookSharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
facebookSharedPreferences.edit()
.putLong(Constants.FACEBOOK_ACCESS_EXPIRES, token_expires)
.commit();
facebookSharedPreferences.edit()
.putString(Constants.FACEBOOK_ACCESS_TOKEN, token).commit();
facebookAsyncRunner.request("me", new IDRequestListener());
shareFBPost();
}
It seems that when the user is already authorized it doesn't go inside my LoginDialogListener
If you will use this guide you will be able to open Facebook app for login
After implementing Facebook auth, initialize Facebook SDK in your Application class or in activity which uses Facebook login
// initialize facebook sdk and app events logger
FacebookSdk.sdkInitialize(getApplicationContext());
Then you can use the class below to login
public class FacebookAuth {
private static FacebookAuth instance;
private OnLoginDataReadyListener mResponseListener;
public static synchronized FacebookAuth getInstance() {
if (instance == null) {
instance = new FacebookAuth();
}
return instance;
}
/**
* Call if you want the user to login with his facebook account
* #param activity needed to initialize the Facebook LoginManager
* #param listener used to set the login listener
*/
public void facebookLogin(Activity activity, OnLoginDataReadyListener listener, CallbackManager callbackManager) {
mResponseListener = listener;
LoginManager.getInstance().logInWithReadPermissions(activity, Arrays.asList("public_profile", "user_friends", "email"));
LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
getUserData();
}
#Override
public void onCancel() {
if (mResponseListener != null) {
mResponseListener.onCanceled();
}
}
#Override
public void onError(FacebookException error) {
if (mResponseListener != null) {
mResponseListener.onCanceled();
}
}
});
}
/**
* Creates an Facebook Graph request witch will grab the user data
* such as name id and picture for now
*/
public void getUserData() {
GraphRequest request = GraphRequest.newMeRequest( AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
if (mResponseListener != null) {
mResponseListener.onLoginDataReady(object);
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "picture.height(200).width(200),cover,location,birthday,first_name,last_name,email,gender,name");
request.setParameters(parameters);
request.executeAsync();
}
public interface OnLoginDataReadyListener {
void onLoginDataReady(JSONObject facebookData);
void onCanceled();
}
}
Once you've implemented the above solution, în your activity create a CallbackManager
CallbackManager mCallbackManager = CallbackManager.Factory.create();
Then in button click listener you can login your user as following
FacebookAuth.getInstance().facebookLogin(activity, dataReadyListener, mCallbackManager);
And finally in onActivityResult()
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mCallbackManager.onActivityResult(requestCode, resultCode, data);
}
Hope this will help you ))
I use the latest Facebook SDK instead and follow these steps. It is important to add onActivityResult for Facebook login callbackManager.
Issue
After successful login verification from the server, unable to open New activity. Activity stays at Login Activity
Background
What I am trying to achieve here is open "Welcome" activity after successful User login. The server correctly validates the user login and displays the Toast, but not opening the activity
Code
private static final String LOGIN_URL = "<myURL>/login.php";
public static final String KEY_LOGUSERNAME = "loUname";
public static final String KEY_LOGPASSWORD = "loPass";
EditText LogUser, LogPass;
Button btnsLogin;
String loUser, loPassword;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initalizevars();
btnsLogin.setOnClickListener(this);
}
public void initalizevars() {
LogUser = (EditText) findViewById(R.id.etLogUser);
LogPass = (EditText) findViewById(R.id.etLogPass);
btnsLogin = (Button) findViewById(R.id.btnLogin);
}
private void login() {
loUser = LogUser.getText().toString().trim();
loPassword = LogPass.getText().toString().trim();
StringRequest stringRequest1 = new StringRequest(Request.Method.POST, LOGIN_URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if(response.trim().equals("Success"))
{
Toast.makeText(Login.this,response,Toast.LENGTH_LONG).show();
openProfile();
}else
{
Toast.makeText(Login.this,response,Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(Login.this,error.toString(),Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<String, String>();
map.put(KEY_LOGUSERNAME, loUser);
map.put(KEY_LOGPASSWORD, loPassword);
return map;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest1);
}
private void openProfile() {
Intent i = new Intent(this,Welcome.class);
startActivity(i);
}
#Override
public void onClick(View v) {
if (v == btnsLogin) {
login();
}
}
The Toast is being displayed from the server response on successful verification
What i tried
I tried changing the Intent to below
Intent i = new Intent(Login.this,Welcome.class);
startActivity(i);
But no luck. Am stuck and unable to figure out where and what went wrong.
Requesting your help in putting me in the right direction.
Thanks
EDIT
i modified the if condition to be more meaningful and to debug as well
if (response.trim().equals("Success")) {
Toast.makeText(Login.this, response + " Right", Toast.LENGTH_LONG).show();
openProfile();
} else {
Toast.makeText(Login.this, response + " Wrong", Toast.LENGTH_LONG).show();
openProfile();
}
As suggested by user #user1232726, the else part is being considered and the activity is opened which should not be the case.
My login.php outputs
Success
<!-- Hosting24 Analytics Code -->
<script type="text/javascript" src="http://stats.hosting24.com/count.php"></script>
<!-- End Of Analytics Code -->
Basically the issue was with the server response as it did return some javascript along with the success message. Guidance from #cricket_007, #IshitaSinha actually help me fix the issue.
Solution : Additional javascript/ or messages can be added When using free hosting sites. Check the entire response before comparing it with the actual response
I'm creating a library to implement a Facebook login without having to compile FacebookSDK directly in the project using the library, meaning, the library (i.e. FacebookLogingUtils) compiles the Facebook SDK and uses its methods to create simpler methods for a programmer to implement Facebook login. The programmer won't ever have to compile Facebook SDK since everything dealing with it is managed within the library.
The issue is the following one: I want to provide the user with a button which they can call in their layout file instead of FacebookLogginButton, so once the button is received by the library, it will be converted into a Facebook.LoginButton and can be used as such. How can I do this? How can I change a button I receive as a parameter into a different kind of button and return it?
You don't have use the LoginButton class to perform a login. You can just use the LoginManager, and trigger a login anytime by using .loginWith(). To see an example of it can be done, check this answer: https://stackoverflow.com/a/30230718/1395437
Now FB gives provision in their 4.x SDK to do like this without using the FB Login Button.
Please try following:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(this.getApplicationContext());
callbackManager = CallbackManager.Factory.create();
}
protected void doFBLoginForProfile() {
LoginManager loginManager = LoginManager.getInstance();
loginManager.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
fetchUserInfo();
}
#Override
public void onCancel() {
}
#Override
public void onError(FacebookException error) {
}
});
loginManager.logInWithReadPermissions(this, getReadPermissions());
}
private ArrayList<String> getReadPermissions() {
ArrayList<String> fbPermissions = new ArrayList<String>();
fbPermissions.add("public_profile");
fbPermissions.add("email");
fbPermissions.add("user_location");
fbPermissions.add("user_friends");
return fbPermissions;
}
public void fetchUserInfo() {
GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
Utils.displayLogs("FB", "response: " + object);
onFBUserInfoFetched(new FBProfile().parse(object));
}
}).executeAsync();
}
public class FBProfile {
public String id = "";
public String email = "";
public String firstName = "";
public String lastName = "";
public String location = "";
public FBProfile parse(JSONObject object) {
id = object.optString("id");
email = object.optString("email");
firstName = object.optString("first_name");
lastName = object.optString("last_name");
if (object.has("location")) {
location = object.optJSONObject("location").optString("name");
}
return this;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
I have followed some Facebook API 3.0 tutorials, including the Login/Logout and the Publish To Feed examples. So the login works this way:
App opens, shows a fragment which displays a login button
User clicks login, the authentication is done via the referenced FacebookSDK library (com.facebook.widget.LoginActivity) and the provided code using sessions.
User is redirected to next screen
I don't want to make the user to login this way. I want them to use my app without any login/registration, then if they click on a facebook specific feature e.g. share a note on Facebook, then the app should ask them whether they let Facebook use their app or something, you know the usual stuff. Without this I get a nullpointer in the publishFeedDialog() function as session is null, because no login has been made.
So my question is, how can I ignore the SplashFragment with the Login button, so when the user clicks on a Facebook feature in my app, no new screen is displayed with a login button, but only the default Facebook authentication window that users are used to?
#erdomester, #sromku
Facebook launch new sdk version 4.x where Session is deprecated,
There new concept of login as from facebook
LoginManager and AccessToken - These new classes perform Facebook
Login
So, Now you can access Facebook authentication without login button as
layout.xml
<Button
android:id="#+id/btn_fb_login"
.../>
MainActivity.java
private CallbackManager mCallbackManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(this.getApplicationContext());
mCallbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(mCallbackManager,
new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
Log.d("Success", "Login");
}
#Override
public void onCancel() {
Toast.makeText(MainActivity.this, "Login Cancel", Toast.LENGTH_LONG).show();
}
#Override
public void onError(FacebookException exception) {
Toast.makeText(MainActivity.this, exception.getMessage(), Toast.LENGTH_LONG).show();
}
});
setContentView(R.layout.activity_main);
Button btn_fb_login = (Button)findViewById(R.id.btn_fb_login);
btn_fb_login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile", "user_friends"));
}
});
}
Edit
If you don't add the following, it won't work (rightly pointed out by #Daniel Zolnai in comment below):
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(mCallbackManager.onActivityResult(requestCode, resultCode, data)) {
return;
}
}
Something like this
private void performFacebookLogin()
{
Log.d("FACEBOOK", "performFacebookLogin");
final Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(this, Arrays.asList("email"));
Session openActiveSession = Session.openActiveSession(this, true, new Session.StatusCallback()
{
#Override
public void call(Session session, SessionState state, Exception exception)
{
Log.d("FACEBOOK", "call");
if (session.isOpened() && !isFetching)
{
Log.d("FACEBOOK", "if (session.isOpened() && !isFetching)");
isFetching = true;
session.requestNewReadPermissions(newPermissionsRequest);
Request getMe = Request.newMeRequest(session, new GraphUserCallback()
{
#Override
public void onCompleted(GraphUser user, Response response)
{
Log.d("FACEBOOK", "onCompleted");
if (user != null)
{
Log.d("FACEBOOK", "user != null");
org.json.JSONObject graphResponse = response.getGraphObject().getInnerJSONObject();
String email = graphResponse.optString("email");
String id = graphResponse.optString("id");
String facebookName = user.getUsername();
if (email == null || email.length() < 0)
{
Logic.showAlert(
ActivityLogin.this,
"Facebook Login",
"An email address is required for your account, we could not find an email associated with this Facebook account. Please associate a email with this account or login the oldskool way.");
return;
}
}
}
});
getMe.executeAsync();
}
else
{
if (!session.isOpened())
Log.d("FACEBOOK", "!session.isOpened()");
else
Log.d("FACEBOOK", "isFetching");
}
}
});
Actually exactly like that. It works perfectly fine for me.
This worked for me
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.widget.TextView;
import com.facebook.*;
import com.facebook.model.*;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// start Facebook Login
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
// make request to the /me API
Request.newMeRequest(session, new Request.GraphUserCallback() {
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null) {
TextView welcome = (TextView) findViewById(R.id.welcome);
welcome.setText("Hello " + user.getName() + "!");
}
}
}).executeAsync();
}
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}
}
if you need to get authorizations after verify that session is open ,add this way:
List<String> permissions = session.getPermissions();
Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(getActivity(), Arrays.asList("read_mailbox"));
session.requestNewReadPermissions(newPermissionsRequest);
This simple library can help you: https://github.com/sromku/android-simple-facebook
Just add this library to your project and make the reference from this library to Facebook SDK 3.0.x and add reference from your app to this library.
Then you can login without the LoginButton and do simple actions like publish feeds, get profile/friends, send invite and more.
This is how the login look like:
OnLoginOutListener onLoginOutListener = new SimpleFacebook.OnLoginOutListener()
{
#Override
public void onFail()
{
Log.w(TAG, "Failed to login");
}
#Override
public void onException(Throwable throwable)
{
Log.e(TAG, "Bad thing happened", throwable);
}
#Override
public void onThinking()
{
// show progress bar or something to the user while login is happening
Log.i(TAG, "In progress");
}
#Override
public void onLogout()
{
// change the state of the button or do whatever you want
Log.i(TAG, "Logged out");
}
#Override
public void onLogin()
{
// change the state of the button or do whatever you want
Log.i(TAG, "Logged in");
}
};
// set login/logut listener
mSimpleFacebook.setLogInOutListener(onLoginOutListener);
// do the login action
mSimpleFacebook.login(MainActivity.this);
Then, in onLogin() callback method you can publish feed like this:
// build feed
Feed feed = new Feed.Builder()
.setMessage("Clone it out...")
.setName("Simple Facebook for Android")
.setCaption("Code less, do the same.")
.setDescription("The Simple Facebook library project makes the life much easier by coding less code for being able to login, publish feeds and open graph stories, invite friends and more.")
.setPicture("https://raw.github.com/sromku/android-simple-facebook/master/Refs/android_facebook_sdk_logo.png")
.setLink("https://github.com/sromku/android-simple-facebook")
.build();
// publish the feed
mSimpleFacebook.publish(feed);
Hope it can help you.
A Turnaroubd to access FB details withot using LoginButton is
1)Hide Your LoginButton UI
2)Add your Custom Button
Button signup = (Button) view.findViewById(R.id.btn_signup);
signup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loginButton.performClick();//Where loginButton is Facebook UI
}
});
But I suggest to use LoginManager
You can bypass the login dialog using the Node powered facebook-proxy module. Create your own instance on Heroku using the one-click-deployment button.
What it basicly does:
Requests an access_token from Facebook
Opens a proxy server using express-http-proxy
Let's you request all endpoints of the API
You can change put the Facebook button and change the visibility. For example :
<FrameLayout
android:id="#+id/frameLayout_facebook"
android:layout_width="0dp"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="#+id/button_continue_facebook"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/continue_with_facebook" />
<com.facebook.login.widget.LoginButton
android:id="#+id/loginButton_facebook"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
After, in your code (in Kotlin here), you can call the onClick() method of the Facebook SDK when someone click on your Button :
button_continue_facebook.setOnClickListener {
binding.loginButton_facebook.callOnClick()
}