Facebook authentication without login button
AndroidFacebookFacebook Android-SdkAndroid Problem Overview
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?
Android Solutions
Solution 1 - Android
@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;
}
}
Solution 2 - Android
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.
Solution 3 - Android
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);
Solution 4 - Android
This simple library can help you: https://github.com/sromku/android-simple-facebook<br><br> 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.
Solution 5 - Android
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
Solution 6 - Android
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
Solution 7 - Android
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()
}