I'm having an issue with the Facebook graph API not returning anything for a request to get a user's notifications. I'm doing it through a batch request, using the same syntax to get a user's news feed, and the news feed request works fine. I have the "manage_notifications" permission enabled also. I always get a null pointer exception in my code when I try to parse the result of the graph call to notifications.
Note that when I got to the graph explorer in my internet browser and type "me/notifications?include_read=true" I DO get the appropriate data.
Here's the code for my request.
static Request notificationsRequest = Request.newGraphPathRequest(fbSession, "me/notifications?include_read=true", new Request.Callback() {
#Override
public void onCompleted(Response response) {
GraphObject object = response.getGraphObject();
if(object != null){
notifications = object.getProperty("data").toString();
}
else{
notifications = "Notifications returns null";
}
}
});
Any ideas? Thanks.
EDIT: I updated the code and found out that the GraphObject object is returning null and that's why it can't parse anything from it. It seems like there would be something wrong with the graph request, but I can't figure out what it is. Like I said, the exact same method for getting a user's news feed ("me/home") works perfectly fine.
Instead of passing the parameter in the Graph path, add it as a parameter to the request:
me/notifications?include_read=true
static Request notificationsRequest = Request.newGraphPathRequest(fbSession, "me/notifications", new Request.Callback() {
#Override
public void onCompleted(Response response) {
GraphObject object = response.getGraphObject();
if(object != null){
notifications = object.getProperty("data").toString();
}
else{
notifications = "Notifications returns null";
}
}
});
Bundle params = new Bundle();
params.putString("include_read", "true");
notificationsRequest.setParameters(params);
I found another way. I will post it in case somebody finds it helpful
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
if (state.isOpened()) {
InboxMessage.setVisibility(View.VISIBLE);
new Request(session,"/me/notifications", null,HttpMethod.GET,new Request.Callback() {
public void onCompleted(Response response) {
GraphObject object = response.getGraphObject();
if (object != null) {
InboxMessage.setText(object.getProperty("data").toString());
} else {
InboxMessage.setText("Notifications returns null");
}
}
}
).executeAsync();
} else {
InboxMessage.setVisibility(View.INVISIBLE);
Log.i(TAG, "Logged out...");
}
}
Related
I have a big problem with android-facebook-sdk 3.19.1. No problem to retrieve public information about user but it is not possible getting email address.
I know my post is very near to the following thread ==> facebook android sdk -user email returns null but I have no solution for now.
So here is my code
In my ConnectionActivity.java I have a button R.id.fb_connect
private List<String> permissions = Arrays.asList("email");
#Click(R.id.fb_connect)
protected void fbConnect() {
ensureOpenSession();
}
private boolean ensureOpenSession() {
Session session = Session.getActiveSession();
if (session == null || !session.isOpened()) {
LOGD(TAG, "Call Session.openActiveSession");
Session.openActiveSession(this, true, permissions, new FbCallback());
return false;
}
return true;
}
public class FbCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState sessionState, Exception e) {
// 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) {
// user.asMap().get("email");
Toast.makeText(ConnectionActivity.this, "email : " + user.getProperty("email"), Toast.LENGTH_LONG).show();
}
}
}).executeAsync();
}
}
I've also tried the code in the link above but it doesn't work. One precision, with this code, I can see the facebook activity which says "XXX will receive the following info: your public profile and email address" but the toast displays "email : null"
EDIT
I work with android studio and my gradle file has the following line
compile 'com.facebook.android:facebook-android-sdk:3.19.1'
EDIT2
If I use
LOGD(TAG, "isPermissionGranted : " + session.isPermissionGranted(permissions.get(0)));
before call Request.newMeRequest so true is shown. Permission is correctly granted
Thx
I'm trying to follow scrumptious tutorial, at the part of newMeRequest, the request never returns, the code is as in the example, like below. Am I missing anything? thanks?
private void makeMeRequest(final Session session) {
// Make an API call to get user data and define a
// new callback to handle the response.
Request request = Request.newMeRequest(session,
new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
// If the response is successful
if (BuildConfig.DEBUG){
Log.i(TAG, "GraphUserCallback" + user.getId()+" " + response.toString());
}
if (session == Session.getActiveSession()) {
if (user != null) {
// Set the id for the ProfilePictureView
// view that in turn displays the profile picture.
//profilePictureView.setProfileId(user.getId());
profilePictureView.setId(Integer.parseInt(user.getId()));
// Set the Textview's text to the user's name.
userNameView.setText(user.getName());
}
}
if (response.getError() != null) {
// Handle errors, will do so later.
}
}
});
request.executeAsync();
}
Make sure you add this permission
<uses-permission android:name="android.permission.INTERNET"/>
I am implementing the new Facebook SDK 3.0.1 and I have some doubts about use with Session.
I created a function to query just the user id:
String userID;
public String getUserID(){
final Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
Request request = Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
if (session == Session.getActiveSession()) {
if (user != null) {
userID = user.getId();
System.out.println("User ID " + userID); //OK
}
}
}
});
Request.executeBatchAsync(request);
return userID;
}else{
return null;
}
}
The problem is when I do System.out.println("ID is... "+FB.getUserID()); because only shows: "ID is...".
But the internal println perfectly shows the id (User ID XXXXXXXXX). The problem is the time to receive the information. How I can I control it?
I think you cannot control it.
You are executing an async request that is a request that "permits other processing to continue before the transmission has finished." (see Wikipedia page).
You have to wait until the onCompleted method is called by the request object.
There is actually a way around this. Simply use Request.executeAndWait(). that function does exactly what it sounds like it does, it pauses the thread until the onComplete is finished.
i am new to facebook development on android. My target is to get the list of page names liked by a user. I am using the fallowing code for that.
I want to make sure that i am using the latest facebook sdk and none of the classes or methods i am using are deprecated
ArrayList<String> permissions = new ArrayList<String>();
permissions.add("user_likes");
loginButton.clearPermissions();
loginButton.setReadPermissions(permissions);
loginButton.setUserInfoChangedCallback(new LoginButton.UserInfoChangedCallback() {
#Override
public void onUserInfoFetched(GraphUser user) {
if(user != null)
{
Log.d(TAG,"User login successful:"+user.getProperty("favorite_teams"));
Session session = Session.getActiveSession();
if(session !=null && session.isOpened())
{
if(session.getPermissions().contains("user_likes"))
{
requestForPageLikes = new Request(session, "https://graph.facebook.com/me/likes");
requestForPageLikes.setCallback(new Request.Callback() {
#Override
public void onCompleted(Response response) {
GraphObject go = response.getGraphObject();
JSONObject jso = go.getInnerJSONObject();
Log.d(TAG,"Facebook response:"+jso.toString());
}
});
Request.executeAndWait(requestForPageLikes);
}
}
}
}
}
The above request is working fine and i am getting the response code as 200, which is OK.
but the log message is printing as
Facebook response:{"id":"https://graph.facebook.com/me/likes"}
I am sure that there are pages which the user has liked, and my app is configured well in developers.facebook.com and as we see in the above code i have the permission user_likes which is required to read the like pages.
I am heavily stuck with this issue. Any help would be really appreciated.
I am developing an Android app. With the impending deprecation of Facebook's offline_access permission I am trying to use the Graph API to extend the Facebook token.
https://graph.facebook.com/oauth/access_token?
client_id=APP_ID&
client_secret=APP_SECRET&
grant_type=fb_exchange_token&
fb_exchange_token=EXISTING_ACCESS_TOKEN
Can anyone provide detailed code that demonstrates how to implement the code above into an android app and obtain the refreshed Facebook token?
Thank you for your time.
Update Two:
Progress (I think)!
Using the full URL with the facebook request method results in the base URL being added to the the beginning of the URL
So instead of
String refreshUrl = "https://graph.facebook.com/oauth/access_token?client_id=12345678910&client_secret=abcdefghijklmnopqrstuvwxyz&grant_type=fb_exchange_token&fb_exchange_token="+currentAccessToken;
should use
String refreshUrl = "oauth/access_token?client_id=12345678910&client_secret=abcdefghijklmnopqrstuvwxyz&grant_type=fb_exchange_token&fb_exchange_token="+currentAccessToken;
However I am now getting the response {"error":{"message":"Error validating application. Invalid application ID.","type":"OAuthException","code":190}}
Update One:
Here is what I have I tried. The code completes, that is OnComplete on the listerner is called, BUT the response does not contain a new access token or expiry value.
void refreshWithGraph() {
AsyncFacebookRunner extendingAsyncRunner = new AsyncFacebookRunner(facebook);
Bundle parameters = new Bundle();
//the variable currentAccessToken is obtained after authorisation is complete using currentAccessToken = facebook.getAccessToken();
String refreshUrl = "https://graph.facebook.com/oauth/access_token?client_id=12345678910&client_secret=abcdefghijklmnopqrstuvwxyz&grant_type=fb_exchange_token&fb_exchange_token="+currentAccessToken;
extendingAsyncRunner.request(refreshUrl, parameters, new RefreshListener(), null );
}
Here is my version of RefreshListener...
//REFRESH LISTENER
public class RefreshListener extends BaseRequestListener {
public void onComplete(final String response, Object state) {
try {
final JSONObject json = Util.parseJson(response);
runOnUiThread(new Runnable() {
#Override
public void run() {
tvRefreshResponse.setText("IN REFRESH LISTENER ONCOMPLETE\nResponse is " + response);
tvRefreshToken.setText("IN REFRESH LISTENER ONCOMPLETE\nToken is " + facebook.getAccessToken());
tvRefreshExpiry.setText("IN REFRESH LISTENER ONCOMPLETE\nFacebook expiry is " + millisecToDate(facebook.getAccessExpires()));
}
}); //end runOnUiThread
} catch (JSONException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tvRefreshResponse.setText("IN REFRESH LISTENER ONCOMPLETE CAUGHT JSON EXCEPTION \nResponse is " + response);
}
}); //end runOnUiThread
} catch (FacebookError fe) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tvRefreshResponse.setText("IN REFRESH LISTENER ONCOMPLETE CAUGHT FACEBOOK ERROR \nResponse is " + response);
}
}); //end runOnUiThread
} //end catch Facebook error
} //end onComplete
#Override
public void onIOException(IOException e, Object state) {
tvRefreshResponse.setText("IN REFRESH LISTENER IOEXCEPTION \nException is "+ e.getLocalizedMessage());
}
#Override
public void onFileNotFoundException(FileNotFoundException e, Object state) {
tvRefreshResponse.setText("IN REFRESH LISTENER FILE NOT FOUND EXCEPTION \nException is "+ e.getLocalizedMessage());
}
#Override
public void onMalformedURLException(MalformedURLException e, Object state) {
tvRefreshResponse.setText("IN REFRESH MALFORMED URL \nException is "+ e.getLocalizedMessage());
}
#Override
public void onFacebookError(FacebookError e, Object state) {
tvRefreshResponse.setText("IN REFRESH ONFACEBOOK ERROR \nException is "+ e.getLocalizedMessage());
}
} //end RefreshListener
The code completes, that is OnComplete on the listerner is called, BUT the response does not contain a new access token or expiry value. The response is...
{"id":"https:\/\/graph.facebook.com\/oauth\/access_token","shares":78,"comments":1}
When I put the same URL (with a alphanumeric current token value) into a web browser the response DOES include an access token.
Related Info
Facebook's offline_access permission will be deprecated on 1st of May, 2012
Please don't suggest using the extendAccessTokenIfNeeded function in onResume() instead. I am also having trouble with that and it is the reason why I am looking into the Graph API token refreshing :-)
Related Stack Overflow Questions
Is it possible to extend Facebook tokens with extendAccessTokenIfNeeded in an Android app? (my question)
How would offline_access work after deprecation after May 1st?
Facebook access token can not be extended
Protecting app secret for extendAccessToken usage (Java/Android)
Relevant Facebook links
Facebook Android Tutorial
Facebook offline_access permission deprecation
To be honest, I'm a bit confused - looks like you have everything to get it done - and it's simple. But let me try to answer your question. Here is the code from my C# project where I extend app's token with my comments in case you are not familiar with C# languages and classes:
string currentToken = "token from somewhere";
// WebClient is used to send GET request to the given URL
// and receive the response
using (var req = new System.Net.WebClient())
{
// create URL string and fill it in with data (app Id, secret, and current token)
var extendTokenUrl = string.Format(
"https://graph.facebook.com/oauth/access_token?client_id={0}&client_secret={1}&grant_type=fb_exchange_token&fb_exchange_token={2}",
FB_APP_ID,
FB_APP_SECRET,
currentToken);
// send GET request and download the response
var response = req.DownloadString(extendTokenUrl);
// if all is good, response will be a string which looks like this:
// access_token=<<THE TOKEN GOES HERE>>
var newToken = response.Substring("access_token=".Length);
// now save newToken in your DB INSTEAD of currentToken -
// so all calls will be made with extended token
SaveTokenInDB(newToken);
}
hope that helps, and translating this into Java should be straightforward.