I want to share some text as well as one picture from my app to facebook wall programatically.
I already registered my android app on facebook developer site.
I am using following code for posting the text but it is not working.It is also not giving me any error so I am totally confused what is happening inside.
public class FacebookManager {
private Activity activity;
private Session.StatusCallback statusCallback;
public UiLifecycleHelper uiHelper;
public FacebookManager(final Activity activity) {
this.activity = activity;
statusCallback = new ShareStatusCallback();
uiHelper = new UiLifecycleHelper(activity, null);
}
public void share() {
Session session = Session.getActiveSession();
if (!session.isOpened() && !session.isClosed()) {
session.openForPublish(new Session.OpenRequest(activity).setCallback(statusCallback).setPermissions("publish_actions"));
} else {
Session.openActiveSession(activity, true, statusCallback);
}
}
public void initFbSession(Bundle savedInstanceState) {
Session session = Session.getActiveSession();
if (session == null) {
if (savedInstanceState != null) {
session = Session.restoreSession(activity, null, null, savedInstanceState);
}
if (session == null) {
session = new Session(activity);
}
Session.setActiveSession(session);
}
}
private class ShareStatusCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState state, Exception exception) {
if (!session.isOpened()) {
return;
}
if (FacebookDialog.canPresentShareDialog(activity, FacebookDialog.ShareDialogFeature.SHARE_DIALOG)) {
FacebookDialog shareDialog = new FacebookDialog.ShareDialogBuilder(activity)
.setDescription("Test Message ")
//.setPicture("")
.build();
uiHelper.trackPendingDialogCall(shareDialog.present());
} else {
Bundle params = new Bundle();
params.putString("description", "Test Message");
// params.putString("picture", "");
WebDialog feedDialog = (
new WebDialog.FeedDialogBuilder(activity,
Session.getActiveSession(),
params)).build();
feedDialog.show();
}
}
}
}
Does it required any configuration for android app on facebook developer site to use share functionality ?
Please help me out for this.
setDescription only applies if you have a link (via setLink).
You cannot prefill the actual message itself, that's against Facebook's platform policies (the user must type in the message themselves).
We will update the javadocs so that it's more clear.
Related
I am trying to integrate Facebook SDK for android in my application.
Below is code I am using to use FB Integration.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bundle = savedInstanceState;
permissions = new ArrayList<String>();
readpermissions = new ArrayList<String>();
permissions.add("publish_actions");
readpermissions.add("email");
executeFacebookLogin();
}
private void executeFacebookLogin() {
Session session = Session.getActiveSession();
Log.i("FB Login "," Session Status "+session);
if(session == null) {
if(session == null) {
Log.i("TEST","CREATE NEW SESSION");
session = new Session(this);
}
Session.setActiveSession(session);
session.addCallback(statusCallback);
if(session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback).setPermissions(readpermissions));
}
}
Log.i("TEST","Session State "+session.isOpened()+ " for close "+session.isClosed());
if(session.isClosed()) {
session.closeAndClearTokenInformation();
Session.setActiveSession(null);
}
if(!session.isOpened()) {
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback).setPermissions(readpermissions));
Log.i("FB Login ","Open for Publish");
} else {
Session.openActiveSession(this, true, statusCallback);
}
}
private class SessionStatusCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState state, Exception exception) {
//Check if Session is Opened or not
processSessionStatus(session, state, exception);
}
}
#SuppressWarnings("deprecation")
public void processSessionStatus(Session session, SessionState state, Exception exception) {
Log.i("TEST","Session in process session "+session);
if(session != null && session.isOpened()) {
if(session.getPermissions().contains("publish_actions")) {
//Show Progress Dialog
dialog = new ProgressDialog(this);
dialog.setMessage("Loggin in..");
dialog.show();
Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
if (dialog!=null && dialog.isShowing()) {
dialog.dismiss();
}
if(user != null) {
Map<String, Object> responseMap = new HashMap<String, Object>();
GraphObject graphObject = response.getGraphObject();
responseMap = graphObject.asMap();
Log.i("FbLogin", "Response Map KeySet - " + responseMap.keySet());
// TODO : Get Email responseMap.get("email");
fb_id = user.getId();
fb_email = null;
user.getBirthday();
fb_userName = user.getUsername();
fb_fullname = user.getFirstName() +" "+user.getLastName();
String name = (String) responseMap.get("name");
if (responseMap.get("email")!=null) {
fb_email = responseMap.get("email").toString();
Log.i("TEST", "FB_ID="+fb_id +"email="+fb_email+"name="+name+"user_name="+user.getUsername()+"birthday="+user.getBirthday());
Session session = Session.getActiveSession();
tokenKey = session.getAccessToken();
SharedPreferenceStoring myPrefsClass = new SharedPreferenceStoring();
myPrefsClass.storingFBToken(FBActivity.this, tokenKey);
Log.i("TEST", "TOKEN kEY fourth = "+tokenKey);
}
else {
//Clear all session info & ask user to login again
Session session = Session.getActiveSession();
if(session != null) {
session.closeAndClearTokenInformation();
}
}
}
}
});
} else {
session.requestNewPublishPermissions(new Session.NewPermissionsRequest(FBActivity.this, permissions));
}
}
}
This code works perfectly if NATIVE FB app is installed.
In case where Native FB app is not installed it shows FB login Web view ( which is correct ).
But if I login into Web view its again showing me that I already authorize application and when I click on Ok button I am getting the same Login FB View and not returning control back to my application.
I am not getting why this is happening.
Can anyone please tell me how to resolve this issue ?
**EDIT**
I am getting this in my logcat when I press Ok button on "You already authorize this app" screen
{Session state:OPENED, token:{AccessToken token:ACCESS_TOKEN_REMOVED permissions:[email]}, appId:xxxxxxxxxxxxx}
and
{act=SSO_WITH_FALLBACK cmp=com.myapp/com.facebook.LoginActivity (has extras)}
Comment this lines any check
if(!session.isOpened()) {
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback).setPermissions(readpermissions));
Log.i("FB Login ","Open for Publish");
} else {
Session.openActiveSession(this, true, statusCallback);
}
EDIT: this code work ing for me Both Native And Webview once try this..
And See this FACEBOOK LOGIN
if (fb_session != null && fb_session.isOpened()) {
makeMeRequest(fb_session);
Log.i("Facebook Login State == >", "Facebook Login State");
} else {
if (fb_session == null) {
fb_session = new Session(mCurrContext);
}
Session.setActiveSession(fb_session);
ConnectToFacebook();
Log.i("Facebook not Login State == >", "Facebook Not login State");
}
}
I can login to my app then share something. This needs an OPENED session state. However, when I am not logged in, then I want to share something, I need to open the session. I am using a ViewPager so e.g. when I go from one page to another and this code
Session.openActiveSession(getActivity(), true, new StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
}
});
is in the beginning of the code, then the session becomes active, and I get automatically logged in, which is wrong! That's why I put this code block into an onClickListener, so I only want to open the session if I click the share button in my app:
if (session != null && session.isOpened()) {
publishFeedDialog();
}
else {
Session.openActiveSession(getActivity(), true, new StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
}
});
publishFeedDialog();
}
private void publishFeedDialog() {
session = Session.getActiveSession();
Log.i("TAG", session.getState() + ""); //OPENING
WebDialog feedDialog = (
new WebDialog.FeedDialogBuilder(getActivity(),
Session.getActiveSession(),
params))
.setOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(Bundle values,
FacebookException error) {
if (error == null) {
final String postId = values.getString("post_id");
if (postId != null) {
} else {
// User clicked the Cancel button
}
} else if (error instanceof FacebookOperationCanceledException) {
} else {
// Generic, ex: network error
}
}
})
.build();
feedDialog.show();
}
The error:
Attempted to use a session that was not open.
So I open the session in vain, because it is still OPENING when the WebDialog should appear.
Please help.
For me it works like this:
if (Session.getActiveSession() != null && Session.getActiveSession().isOpened()) {
publishFeedDialog();
}
else {
Session session = Session.getActiveSession();
if (!session.isOpened() && !session.isClosed()) {
// List<String> permissions = new ArrayList<String>();
// permissions.add("email");
session.openForRead(new Session.OpenRequest(this)
// .setPermissions(permissions)
.setCallback(mFacebookCallback));
} else {
Session.openActiveSession(getActivity(), true, mFacebookCallback);
}
}`
where callback is
private Session.StatusCallback mFacebookCallback = new Session.StatusCallback() {
#Override
public void
call(final Session session, final SessionState state, final Exception exception) {
if (state.isOpened()) {
String facebookToken = session.getAccessToken();
Log.i("MainActivityFaceBook", facebookToken);
Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user,
com.facebook.Response response) {
publishFeedDialog();
}
}).executeAsync();
Prefs.setStringProperty(getActivity(), R.string.key_prefs_facebook_token, facebookToken);
}
}
};
Try to call publishFeedDialog() in CallBack onCompleted
Try calling publishFeedDialog() from inside call() after you check for the status of the session (do not use session.isOpened(), use state.isOpened() instead). Checking the state ensures that your Session is in an open state and that it can also be used to execute requests. The StatusCallback can be called multiple times until the Session is actually open, that is why you should check the status before sending any request.
If you are opening a session from a fragment use the next openActiveSession method implementation.
openActiveSession(Context context, Fragment fragment, boolean allowLoginUI, Session.StatusCallback callback)
This works for me.
I am working on facebook integration in an android app. I did a lot of search about error handling of facebook inn android but nothing foung. Can anyone tell me how handle these situation in android :
1.The user changes her password which invalidates the access token.
2.The user de-authorizes your app.
3.The user logs out of Facebook.
My code of facebook integration is here :
private UiLifecycleHelper uiHelper;
private Session.StatusCallback callback = new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if ( exception instanceof FacebookOperationCanceledException ||
exception instanceof FacebookAuthorizationException)
{
new AlertDialog.Builder(MainWindow.this)
.setTitle("cancel")
.setMessage("your permission has expired.")
.setPositiveButton("ok", null)
.show();
}
}
private void onClickFacebookRequest()
{
if (session.isOpened())
{
sendRequests();
} else {
StatusCallback callback = new StatusCallback() {
public void call(Session session, SessionState state, Exception exception) {
if (exception != null) {
new AlertDialog.Builder(MainWindow.this)
.setTitle(R.string.login_failed_dialog_title)
.setMessage(exception.getMessage())
.setPositiveButton(R.string.ok_button, null)
.show();
session = createSession();
}
}
};
pendingRequest = true;
session.openForRead(new Session.OpenRequest(this).setCallback(callback));
}
}
private static final List<String> PERMISSIONS = Arrays.asList("publish_actions");
private static final String PENDING_PUBLISH_KEY = "pendingPublishReauthorization";
private void sendRequests()
{
List<String> permissions = quytechApps.getSession().getPermissions();
if (!isSubsetOf(PERMISSIONS, permissions)) {
pendingRequest = true;
Session.NewPermissionsRequest newPermissionsRequest = new Session
.NewPermissionsRequest(this, PERMISSIONS);
session.requestNewPublishPermissions(newPermissionsRequest);
return;
}
showValidationDialog("Please Wait.posting Data on Facebook");
Bitmap image = BitmapFactory.decodeResource(this.getResources(), R.drawable.splash_screen_final4);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Bundle postParams=new Bundle();
postParams.putByteArray("photo",byteArray);
postParams.putString("message", "Hi Friends I am using Twinqli Chat App.");
Request request = new Request(Session.getActiveSession(), "me/photos", postParams, HttpMethod.POST, new Request.Callback()
{
#Override
public void onCompleted(Response response) {
// TODO Auto-generated method stub
// showPublishResult(getString(R.string.photo_post), response.getGraphObject(), response.getError());
if(response.getError() == null)
{
Log.d("GraphApiSample.java Sucesses","sucess");
dismissValidatingDialog();
}
else
{
dismissValidatingDialog();
session.closeAndClearTokenInformation();
//quytechApps.getSession().
//quytechApps.setSession(null);
// Log.d("GraphApiSample.java",""+response.getError().getErrorMessage());
}
}
});
request.executeAsync();
}
private boolean isSubsetOf(Collection<String> subset, Collection<String> superset) {
for (String string : subset) {
if (!superset.contains(string)) {
return false;
}
}
return true;
}
static final String applicationId = "390611174384274";
boolean pendingRequest;
static final String PENDING_REQUEST_BUNDLE_KEY = "com.facebook.samples.graphapi:PendingRequest";
private Session createSession()
{
Session activeSession = Session.getActiveSession();
if (activeSession == null || activeSession.getState().isClosed())
{
activeSession = new Session.Builder(this).setApplicationId(applicationId).build();
Session.setActiveSession(activeSession);
}
return activeSession;
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (qsession.onActivityResult(this, requestCode, resultCode, data) &&
pendingRequest &&
session.getState().isOpened()) {
sendRequests();
}
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
pendingRequest = savedInstanceState.getBoolean(PENDING_REQUEST_BUNDLE_KEY, pendingRequest);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(PENDING_REQUEST_BUNDLE_KEY, pendingRequest);
}
can anyone help me . Thanks in advance.
The handleError() method noted by Ming Li is relevant to request errors. It does not handle login errors. I have not seen any examples in the Facebook docs, nor samples, as to how to handle login errors, beyond differentiating between a cancellation and an error. My suggestion is to generate erroneous conditions prior to login attempts (e.g. change the password, deauthorize the app, etc), then in the login callback look at the different values you get for error.getMessage(), and build your own mechanisms accordingly (e.g. if the word "session" appears in the message, tell the user to login to the Facebook app). Also note that getLocalizedMessage() seems not to work (as of SDK 3.5.2). You can differentiate between cancels and errors by if (exception instanceof FacebookOperationCanceledException) and if (exception instanceof FacebookAuthorizationException), but that's pretty much it.
This question is related to face book error handling and is very complex to handle .
However, when i was using the face book API, i got a list of error codes that might be returned and as a result i was able to gracefully solve this scenario . I guess what you are asking for , is graceful error handling.
First of all if it is so, a search in google reveals this url.
Now off to the fun part :
Invalidation of access token : Here the error description is : Invalid OAuth 2.0 Access Token and the error number returned is : 190
User De authorirization : This is a permission issue, so error desc is : Permissions error and error no is : 200
User logs out : When user logs out, it will lead to user data error . The error desc is : User data failure and error no is : 310.
But, there are other scenarios as well, which you need to consider. For this you can get a list of all these error codes here in this LINK .
The error handling document is here - https://developers.facebook.com/docs/reference/api/errors/
You should also look at the Scrumptious sample app, specifically the handleError() method in SelectionFragment.java, it breaks down the different cases you should handle.
I'm working on Facebookintegration for my Android app and to reduce the hassle, I'm trying to create a singleton class to seperate the facebook logic from the main logic of my application.
I'd like to be able to call this class from different parts of my application (entrypoint, asynctasks, ...). At this moment, I call the initialize function first with the applicationcontext as context. After this initialization I'd like to be able to call eg. FacebookSession.getInstance().login() and FacebookSession.getInstance().requestWithQuery(examplestring).
The problem is that I just can't find decent documentation. Even the facebook official samples uses the old Facebook object, which is deprecated. I threw this class together with different parts of code I could find and I came up with this:
package be.ugent.zeus.hydra.util.facebook;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import com.facebook.HttpMethod;
import com.facebook.Request;
import com.facebook.Session;
import com.facebook.SessionState;
public class FacebookSession {
private static final String APP_ID = "hidden";
private static final String ACCESS_TOKEN = "hidden";
private static FacebookSession fbSession;
public static final String TAG = "FACEBOOK";
private Activity activity;
private static Session.StatusCallback statusCallback = new SessionStatusCallback();
protected FacebookSession() {
}
public static void initialize(Context context) {
Session session = Session.getActiveSession();
if (session == null) {
session = new Session.Builder(context)
.setApplicationId(APP_ID)
.build();
}
Session.setActiveSession(session);
}
public static FacebookSession getInstance() {
if (fbSession == null) {
fbSession = new FacebookSession();
}
return fbSession;
}
public Session getSession() {
return Session.getActiveSession();
}
public void tryOpenSession(Activity activity) {
Session session = Session.openActiveSession(activity, false, statusCallback);
Session.setActiveSession(session);
}
public void login(Activity activity) {
Session session = Session.getActiveSession();
if (!session.isOpened() && !session.isClosed()) {
Session.openActiveSession(activity, true, statusCallback);
}
}
public void logout() {
Session session = Session.getActiveSession();
if (!session.isClosed()) {
session.closeAndClearTokenInformation();
}
}
public boolean isOpen() {
Session session = Session.getActiveSession();
return session.isOpened();
}
public Request requestWithQuery(String query) {
Bundle bundle = new Bundle();
bundle.putString("q", query);
return requestWithGraphPath("/fql", bundle, "GET");
}
private Request requestWithGraphPath(String path, Bundle bundle, String method) {
// Get the session
Session session = Session.getActiveSession();
// No session? Try to open one without user interaction
if (session == null) {
session = Session.openActiveSession(activity, false, statusCallback);
Session.setActiveSession(session);
}
// Still no session? Use the default key
if (session == null) {
bundle.putString("access_token", ACCESS_TOKEN);
}
return new Request(session, path, bundle, HttpMethod.valueOf(method));
}
private static class SessionStatusCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState state, Exception exception) {
Log.i(TAG, state.toString());
switch (state) {
case CLOSED:
case CLOSED_LOGIN_FAILED:
session.closeAndClearTokenInformation();
break;
default:
break;
}
}
}
}
The queryingpart works pretty neat, but the sessions don't. For example, if I call the login function, the active session is null, however I did initialize the Session with the applicationcontext in the entry point of my application.
Concrete, I have this question:
Is this the 'good' way of (trying) to keep track of the Session state? Can it be done this way? If so, what I'm doing wrong that it just doesn't work?
And as a follow-up question:
If not, then what is the correct way to keep track of a Session during either the application life time and otherwise between application sessions?
Thanks in advance.
I'm not 100% certain I understand the problem, but FWIW, the following works for me:
In an Activity somewhere:
Session.openActiveSession(MyActivity.this, true, new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
if(session.isOpened()) {
Log.d(TAG, "FB session opened successfully");
} else {
Log.d(TAG, "FB session not opened ... " + exception.toString());
}
}
});
And then, somewhere else (different Activity, AsyncTask, whatever) access the session with Session.getActiveSession():
Session session = Session.getActiveSession();
if(session!=null && session.isOpened()) {
Request.executeMyFriendsRequestAsync(session, new Request.GraphUserListCallback() {
#Override
public void onCompleted(List<GraphUser> users, Response response) {
for(GraphUser u : users) {
Log.d(TAG, ""+u.getId()+ ": " + u.getName());
}
}
});
}
So it seems to me that the Session class from Facebook gives you what you want (access to the active session "singleton-style")
HTH
I would like to get the friendlist of the facebook using intent.
Please let me know if there is any way to get the friends list of the facebook by using built in application of the device.
Thanks.
You need to integrate the Android SDK into your app, here is the link to download the latest SDK. You then will have to have the user authenticate your app to access their information.
Here is sample code to do this
private SessionTracker mSessionTracker;
private Session mCurrentSession;
private void signInWithFacebook() {
mSessionTracker = new SessionTracker(getBaseContext(), new StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
}
}, null, false);
String applicationId = Utility.getMetadataApplicationId(getBaseContext());
mCurrentSession = mSessionTracker.getSession();
if (mCurrentSession == null || mCurrentSession.getState().isClosed()) {
mSessionTracker.setSession(null);
Session session = new Session.Builder(getBaseContext()).setApplicationId(applicationId).build();
Session.setActiveSession(session);
mCurrentSession = session;
}
if (!mCurrentSession.isOpened()) {
Session.OpenRequest openRequest = null;
openRequest = new Session.OpenRequest(SignUpChoices.this);
if (openRequest != null) {
openRequest.setDefaultAudience(SessionDefaultAudience.FRIENDS);
openRequest.setPermissions(Arrays.asList("user_birthday", "email", "user_location"));
openRequest.setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK);
mCurrentSession.openForRead(openRequest);
Request.executeMeRequestAsync(mCurrentSession, new Request.GraphUserCallback() {
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response) {
Log.w("myConsultant", user.getId() + " " + user.getName() + " " + user.getInnerJSONObject());
}
});
}
}
}
One you have a user that has approved your app you can perform other Request about their information. friends info example
Finally i found a way to get the friendlist of the Facebook using Intent.
Intent m_fb=getOpenFacebookIntent(m_context);
startActivity(m_fb);
public static Intent getOpenFacebookIntent(Context context) {
try {
context.getPackageManager().getPackageInfo("com.facebook.katana", 0);
return new Intent(Intent.ACTION_VIEW,Uri.parse("fb://profile/<user_id>/fans"));
} catch (Exception e) {
return new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.facebook.com/abc.xyz"));
}
}
You can use Official Facebook App with Intent listed HERE.