Querying friends' birthdays using updated facebook sdk - android

I am trying to access my friends' birthdays using the latest facebook sdk. Due to latest updates, I am forced to call the api multiple times to accomplish this. Once to fetch my friends and then use their user-id to query their birthdays.
The second query, the inner query to get birthdays, is being skipped altogether.
And I am not sure if I am even doing this right.
Here is my background AsyncTask class which contains the calls :
/**
* Background Async Task to Load all friends by making calls the Graph API
* */
class LoadAllFriends extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
...
}
/**
* getting All friends and birthdays from api
* */
protected String doInBackground(String... args) {
try
{
final AccessToken accessToken = AccessToken.getCurrentAccessToken();
GraphRequestAsyncTask graphRequestAsyncTask = new GraphRequest(
accessToken,
"/me/friends",
null,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
try
{
friends = response.getJSONObject().getJSONArray("data");
Log.d("Friends length",String.valueOf(friends.length()));
for (int l=0; l < friends.length(); l++)
{
final HashMap hm = new HashMap<String, Date>();
hm.put("uid", friends.getJSONObject(l).getString("id"));
hm.put("name",friends.getJSONObject(l).getString("name"));
GraphRequestAsyncTask graphRequestAsyncTask = new GraphRequest(
accessToken,
"/"+hm.get("uid"),
null,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
try
{
JSONArray birthday = response.getJSONObject().getJSONArray("data");
Log.d("birthday",(String) birthday.getJSONObject(0).get("birthday"));
hm.put("date", (Date) birthday.getJSONObject(0).get("birthday"));
} catch (Exception e) {
e.printStackTrace();
}
}}).executeAsync();
friendsList.add(hm);
}
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yy");
Calendar cal = Calendar.getInstance();
Date date1 = dateFormat.parse(dateFormat.format(cal.getTime()));
cal.add(Calendar.DATE, 30);
Date date2 = dateFormat.parse(dateFormat.format(cal.getTime()));
Iterator<HashMap<String, Object>> iter = friendsList.iterator();
while (iter.hasNext())
{
HashMap<String, Object> map = iter.next();
Log.d("uid", (String) map.get("uid"));
Log.d("name", (String) map.get("name"));
Log.d("date", (String) map.get("date"));
/*if (date1.compareTo((Date) map.get("date")) < 0 ||
date2.compareTo((Date) map.get("date")) > 0)
{
friendsList.remove(map);
}*/
}
}
catch (JSONException e)
{
e.printStackTrace();
}
catch (ParseException e)
{
e.printStackTrace();
}
}
}
).executeAsync();
if (friendsList.size() > 0)
{
friendsFound = true;
}
else
{
friendsFound = false;
}
}
catch(NullPointerException e){
e.printStackTrace();
}
catch(RuntimeException e){
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url)
{
// dismiss the dialog after getting all events
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable()
{
public void run()
{
...
}
});
}
}
Here :
Log.d("birthday",(String) birthday.getJSONObject(0).get("birthday"));
in the inner api call is not displayed in the terminal. Log output is being displayed for friends.length() and from the iterator and only for uid and name. Log for date throws the following error :
AndroidRuntime: FATAL EXCEPTION: main
Process: com.supre.www.surprise, PID: 18142
java.lang.NullPointerException: println needs a message
at android.util.Log.println_native_inner(Native Method)
at android.util.Log.println_native(Log.java:290)
at android.util.Log.d(Log.java:323)
at com.supre.www.surprise.HomeActivity$LoadAllFriends$1.onCompleted(HomeActivity.java:237)
at com.facebook.GraphRequest$5.run(GraphRequest.java:1368)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
Please Help!

You can´t get the birthdays of friends who did not authorize your App, for privacy reasons. All friend permissions have been removed with v2.0 of the Graph API: https://developers.facebook.com/docs/apps/changelog#v2_0
You can only get birthdays of friends who authorized your App with user_friends and user_birthday, with the following API call: me/friends?fields=name,birthday

You can not access friends detail unless they have your app installed and made a login/signup inside your app with Facebook. Only
"summary": {
"total_count": 2
}
Only friends who installed this app are returned in API v2.0 and
higher. total_count in summary represents the total number of friends,
including those who haven't installed the app.
If any friends having your app installed, here is the code that will give access to their data:
GraphRequest request = GraphRequest.newMeRequest(
accessToken,
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
// Insert your code here
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "email,birthday,friends{birthday}");
request.setParameters(parameters);
request.executeAsync();
Let me know if anyone having issues!

Related

Get Facebook name with Parse on an Android app

When a user logs into Facebook, I'd like to get their name and profile picture. For the name, I was looking at this link with this code:
private void makeMeRequest(final Session session) {
Request request = Request.newMeRequest(session,
new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
// If the response is successful
if (session == Session.getActiveSession()) {
if (user != null) {
String facebookId = user.getId();
}
}
if (response.getError() != null) {
// Handle error
}
}
});
request.executeAsync();
}
But I was unable to import the Request class and it looks like the class is no longer available. Is there another class that could get the same job done?
The Session class has been removed from the the SDK at the version 4.0 - at March 25, 2015. You can find information about this in this link
Call newMeRequest using accressToken
GraphRequest request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
try {
String name = object.
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Why are you using Parse? Instead, go directly to Facebook and use Graph API. Here's the link:
https://developers.facebook.com/docs/android/graph

Cannot get the facebook's user's timeline with api 2.5

I'm trying to get the facebook's user's timeline in my Android app.
Here my code :
mLoginButton.setReadPermissions(Arrays.asList("user_about_me", "user_friends", "user_likes",
"user_photos", "user_relationships", "user_posts",
"user_status"));
// If using in a fragment
mLoginButton.setFragment(this);
// Other app specific specialization
// Callback registration
mLoginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
mAccessToken = loginResult.getAccessToken();
for (String permission : loginResult.getRecentlyGrantedPermissions()) {
Log.d(LOG_TAG, "Granted Permission:" + permission);
}
getUserFeed();
}
#Override
public void onCancel() {
// App code
}
#Override
public void onError(FacebookException exception) {
// App code
}
});
And after the login, I launch this :
private void getUserFeed() {
Bundle params = new Bundle();
params.putInt("limit", 25);
params.putString("fields", "id,name,link,full_picture,message,story,picture,type,place,from,to");
params.putBoolean("summary", true);
/* make the API call */
new GraphRequest(
AccessToken.getCurrentAccessToken(),
"/me/home",
params,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
try {
final JSONArray data = response.getJSONObject().getJSONArray("data");
//currentJson = response.getJSONObject();
} catch (JSONException e) {
Log.e("Error: ", e.toString());
}
}
}
).executeAsync();
}
I have this respond code from Facebook :
Requires extended permission: read_stream
I know this permission is depreceted, I'm using the latest API 2.5.
Do you know if we can continue to get the user's timeline now, if I replace the "/me/home" by "/me/feed" it's ok, but I just get my posts, not my entire timeline.
Thanks :)
Do you know if we can continue to get the user's timeline now,
No, you can’t.
if I replace the "/me/home" by "/me/feed" it's ok, but I just get my posts, not my entire timeline.
/me/home was deprecated together with the permission.
/me/feed is what you can get now, and that’s it.
Which posts you can expect to see is listed here: https://developers.facebook.com/docs/graph-api/reference/v2.5/user/feed#readperms

Facebook SDK for android: getFirstName() and getLastName() return null strings

I'm developing an android native app using Facebook SDK 3.5.
I'm trying to have an autocompletetextview where I can pick some facebook friends, for this I'm using an newMyFriendsRequest as below:
private void fbFriendsRequest(final Session session) {
Request request = Request.newMyFriendsRequest(session, new Request.GraphUserListCallback() {
#Override
public void onCompleted(List<GraphUser> listFacebookFriends, Response response) {
// If the response is successful
if (session == Session.getActiveSession()) {
if (listFacebookFriends != null) {
mAdapter = new GraphUserAdapter(FriendPicker.this, listFacebookFriends);
mAutoComplete.setAdapter(mAdapter);
Toast.makeText(FriendPicker.this,"Friends Loaded",Toast.LENGTH_SHORT).show();
}
}
if (response.getError() != null) {
// Handle errors, will do so later.
}
}
});
request.executeAsync();
}
Then each time the user pick a row from the autocompletetextview I add this row to another list, and when a I press OK button I have:
public void onOkClick(View v) {
if(mGraphUsersList.size()==0) {
setResult(RESULT_CANCELED,null);
} else {
Intent returnIntent = new Intent();
Iterator<GraphUser> itr = mGraphUsersList.iterator();
int n = mGraphUsersList.size();
String[] idfb = new String[n];
String[] names = new String[n];
String[] lastnames = new String[n];
int i = 0;
while(itr.hasNext()) {
GraphUser User = (GraphUser) itr.next();
idfb[i]=User.getId();
names[i]=User.getFirstName(); // problem
lastnames[i]=User.getLastName(); // problem
i++;
}
returnIntent.putExtra("idfb",idfb);
returnIntent.putExtra("names",names);
returnIntent.putExtra("lastnames",lastnames);
setResult(RESULT_OK,returnIntent);
}
finish();
}
When I use the getFirstName() and getLastName() functions I have null strings, but if I use getName() function it's return the name+lastname. It's like if in the list given by newMyFriendsRequest something has been lost.
Anyone knows a workaround for this?
To get other fields than id and name of friends, you need to specify them explicitly in your request.
For this add them to the Bundle of your request like:
Request request = Request.newMyFriendsRequest(session, new Request.GraphUserListCallback() {
#Override
public void onCompleted(List<GraphUser> listFacebookFriends, Response response) {
// your code like you did
}
}
// here add fields explicitly
Bundle bundle = request.getParameters();
mBundle.putString("fields", "id,first_name,last_name");
// execute like you did
request.executeAsync();
This is one solution for you, or another one is to use this super simple library: android-simple-facebook
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
Profile profile = Profile.getCurrentProfile();
Log.d("fbEmail_id", profile.getFirstName());
String first_name=profile.getFirstName();
String last_name=profile.getLastName();
}

Android Integrating Facebook - Getting FQL response in changed order

I am developing an android application which includes the facebook integration. If I execute multiple fql queries, I am getting the response in changed order.
I am using the following code:
public static ArrayList<String> photoAlbumIdArr = null;
#Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.main);
photoAlbumIdArr = new ArrayList<String>();
photoAlbumIdArr.add("111114545_25133454545");
photoAlbumIdArr.add("111114590_25133434768");
photoAlbumIdArr.add("111114232_2513345487");
photoAlbumIdArr.add("111114512_25133454456");
startProgress();
}
public void startProgress() {
// Do something long
PhotoGalleryActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
String fqlQuery = "";
for(int k=0;k<photoAlbumIdArr.size();k++)
{
fqlQuery = "SELECT pid, src FROM photo WHERE aid = '"+photoAlbumIdArr.get(k)+"'";
Bundle params = new Bundle();
params.putString("q", fqlQuery);
session = Session.getActiveSession();
Request request = new Request(session, "/fql", params,
HttpMethod.GET, new Request.Callback() {
public void onCompleted(Response response) {
String jsonResponse = response.toString();
Log.i(LOG_TAG, jsonResponse);
}
});
Request.executeBatchAsync(request);
}
}
});
}
Here the callback response is called after the for loop completed. In that I am getting the unorder response(i.e) getting first album photos as last or middle response likewise. What may be the problem. Why I get the unordered response.
This may be due to the fact that you do not have an ORDER BY clause in your FQL query.
Try using something like:
SELECT pid, src FROM photo WHERE aid = '{album id}' ORDER BY modified
This will ensure that the order that is returned is always the same (assuming no images are modified in-between queries).

Android: get facebook friends list

I am using the Facebook SDK to post messages on walls.
Now I need to fetch the Facebook friends list. Can anybody help me with this?
-- Edit --
try {
Facebook mFacebook = new Facebook(Constants.FB_APP_ID);
AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(mFacebook);
Bundle bundle = new Bundle();
bundle.putString("fields", "birthday");
mFacebook.request("me/friends", bundle);
} catch(Exception e){
Log.e(Constants.LOGTAG, " " + CLASSTAG + " Exception = "+e.getMessage());
}
When I execute my activity, I'm not seeing anything, but in LogCat there is a debug message like:
06-04 17:43:13.863: DEBUG/Facebook-Util(409): GET URL: https://graph.facebook.com/me/friends?format=json&fields=birthday
And when I tried to access this url directly from the browser, I'm getting the following error response:
{
error: {
type: "OAuthException"
message: "An active access token must be used to query information about the current user."
}
}
You are about half way there. You've sent the request, but you haven't defined anything to receive the response with your results. You can extend BaseRequestListener class and implement its onComplete method to do that. Something like this:
public class FriendListRequestListener extends BaseRequestListener {
public void onComplete(final String response) {
_error = null;
try {
JSONObject json = Util.parseJson(response);
final JSONArray friends = json.getJSONArray("data");
FacebookActivity.this.runOnUiThread(new Runnable() {
public void run() {
// Do stuff here with your friends array,
// which is an array of JSONObjects.
}
});
} catch (JSONException e) {
_error = "JSON Error in response";
} catch (FacebookError e) {
_error = "Facebook Error: " + e.getMessage();
}
if (_error != null)
{
FacebookActivity.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Error occurred: " +
_error, Toast.LENGTH_LONG).show();
}
});
}
}
}
Then in your request you can specify the request listener to use for receiving the response from the request, like this:
mFacebook.request("me/friends", bundle, new FriendListRequestListener());
Using FQL Query
String fqlQuery = "SELECT uid, name, pic_square FROM user WHERE uid IN " +
"(SELECT uid2 FROM friend WHERE uid1 = me() LIMIT 25)";
Bundle params = new Bundle();
params.putString("q", fqlQuery);
Session session = Session.getActiveSession();
Request request = new Request(session,"/fql", params,HttpMethod.GET, new Request.Callback(){
public void onCompleted(Response response) {
Log.i(TAG, "Result: " + response.toString());
try{
GraphObject graphObject = response.getGraphObject();
JSONObject jsonObject = graphObject.getInnerJSONObject();
Log.d("data", jsonObject.toString(0));
JSONArray array = jsonObject.getJSONArray("data");
for(int i=0;i<array.length();i++)
{
JSONObject friend = array.getJSONObject(i);
Log.d("uid",friend.getString("uid"));
Log.d("name", friend.getString("name"));
Log.d("pic_square",friend.getString("pic_square"));
}
}catch(JSONException e){
e.printStackTrace();
}
}
});
Request.executeBatchAsync(request);
I was dealing with that and I found the answer.
The problem is that you want to access to your data without previous registration with your facebook token.
First, you must to define your Facebook variable:
Facebook mFacebook = new Facebook(getString(R.string.fb_id));
Later, define your AsyncFacebookRunner:
final AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(mFacebook);
Ok, now you must to authorize your request, with autorize method. Note that you must implement callback methods on DialogListener(), put attention on onComplete() method. On that method you must to run the friend fetch request. Now your request will pass because now you are authenticated.
Now the code:
mFacebook.authorize(this, fb_perms, new DialogListener(){
/**
* Triggered on a successful Facebook registration.
*/
public void onComplete(Bundle values) {
mAsyncRunner.request("me/friends", new FriendListRequestListener());
}
/**
* Triggered on a FacebookError.
*/
public void onFacebookError(FacebookError e) {
}
/**
* Triggered on a DialogError.
*/
public void onError(DialogError e) {
}
/**
* Triggered when the User cancels the Facebook Login.
*/
public void onCancel() {
}
});
You can use the FriendListRequestListener class that was post by #Kon
I hope this helps.
Cheers!
Hi Please check below link
Facebook API for Android: how to get extended info regarding user`s friends?
Post on user's friends facebook wall through android application
I faced the same problem yesterday.
I wondering if you have overriden the onActivityResult() function?
private Facebook mFacebook=null;
...
...
...
#Override
protected void onActivityResult(int requestCode,
int resultCode,
Intent data) {
mFacebook.authorizeCallback(requestCode, resultCode, data);
}
Check this answer in order to know how to get Facebook friend list and who of these friends have installed your app using new Facebook SDK 3.0 for Android.
I'm doing something like this is working good....
jsonObj = Util.parseJson(facebook.request("me/friends"));
JSONArray jArray = jsonObj.getJSONArray("data");
for(int i=0;i<jArray.length();i++){
JSONObject json_data = jArray.getJSONObject(i);
Log.v("THIS IS DATA", i+" : "+jArray.getJSONObject(i));
}
Hope it is helpful...
If somebody is reading this in late 2015, the answer and code is quite simple. Take a look at official documentation here (in the code window click on Android SDK).
Keep in mind that you need to have user_friends permission.
Bro tip for android-rx users - get your friends synchronously, then process message and return Observable:
public Observable<List<Friend>> execute() {
return Observable.defer(new Func0<Observable<List<Friend>>>() {
#Override
public Observable<List<Friend>> call() {
AccessToken a = AccessToken.getCurrentAccessToken();
if (Utils.isValid(a)) {
try {
GraphResponse res = new GraphRequest(AccessToken.getCurrentAccessToken(), "me/friends").executeAndWait();
// process result
return Observable.just(your friend list);
} catch (Exception e) {
// notify user or load again
}
}
// invalid access token -> notify user
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}

Categories

Resources