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).
Related
I have a loop that calls the getComments method for each Facebook object as shown, the getComments method is not called from anywhere else in the program.
JSONArray feedArr = response.getGraphObject().getInnerJSONObject().getJSONArray("data");
for (int i=0;i<feedArr.length();i++) {
JSONObject obj = feedArr.getJSONObject(i);
getComments(obj.getString("id"));
}
From what I see, I am making a new Request object each time, but I still get the error "java.lang.IllegalStateException: Cannot execute task: the task is already running." each time.
private void getComments(final String post) {
String fqlQuery = "{" +
"'comments':'SELECT fromid, text, id, likes, time, user_likes FROM comment WHERE post_id=\""
+ post + "\" LIMIT 2000'," +
"'users':'SELECT uid, name, pic_square FROM user WHERE uid IN (SELECT fromid FROM #comments)'" +
"}";
Bundle params = new Bundle();
params.putString("q", fqlQuery);
Session session = Session.getActiveSession();
new Request(session,
"/fql",
params,
HttpMethod.GET,
new Request.Callback(){
public void onCompleted(Response response) {
//..parsing data
}
}).executeAsync();
}
}
Is there a reason why this happens and how can I fix it?
new Request(session,
"/fql",
params,
HttpMethod.GET,
new Request.Callback(){
public void onCompleted(Response response) {
//INVOKE NEXT FROM HERE
}
}).executeAsync();
Only one instance of this can run at a time. The second instance can run only after the first has terminated. You were trying to invoke 10 parallel intances, which was causing the error.
If you wish to run this for multiple instances, you can do it from onCompleted(Response response) call back.
//First CALL
//PUBLIC DATA MAMBER : feedArr & mCount
int mCount = 0;
JSONArray feedArr = response.getGraphObject().getInnerJSONObject().getJSONArray("data");
JSONObject obj = feedArr.getJSONObject(mCount);
getComments(obj.getString("id"));
//RECURSIVE CALL
private void getComments(final String post) {
String fqlQuery = "{" +
"'comments':'SELECT fromid, text, id, likes, time, user_likes FROM comment WHERE post_id=\""
+ post + "\" LIMIT 2000'," +
"'users':'SELECT uid, name, pic_square FROM user WHERE uid IN (SELECT fromid FROM #comments)'" +
"}";
Bundle params = new Bundle();
params.putString("q", fqlQuery);
Session session = Session.getActiveSession();
new Request(session,
"/fql",
params,
HttpMethod.GET,
new Request.Callback(){
public void onCompleted(Response response)
{
mCount++;
if(mCount< feedArr .size())// or feedArr.length()
{
JSONObject obj = feedArr.getJSONObject(mCount);
getComments(obj.getString("id"));
}
}
}).executeAsync();
}
}
I had a similar problem, and the exception is been thrown because you're executing .executeAsync(); several times. That happens because recursive calls will execute the same method again.
A simple solution is to execute your method getComments(final String post) inside an AsyncTask and then change .executeAsync() by .executeAndWait(), so the application will wait for the results for each call to getComments(...).
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();
}
Having trouble using facebook graph API library for android when sending a batch of requests.
Not getting a callback when running this code:
RequestBatch requestBatch = new RequestBatch(requests);
requestBatch.addCallback(new com.facebook.RequestBatch.Callback() {
#Override
public void onBatchCompleted(RequestBatch batch) {
Log.e(LOG_TAG, "onBatchCompleted()");
}
});
requestBatch.executeAsync();
Found the answer.
You need to set the callback for each individual request to get the batch-related callback, because onBatchCompleted callback will be called after all per-Request callbacks are called..
for (String friend : friends) {
MyLog.d(LOG_TAG, "Adding request for " + friend.getInterestFbId());
String graphPath = friend + "/feed";
Request request = new Request(session, graphPath, null, HttpMethod.GET);
Bundle params = new Bundle();
params.putString("fields",
"id,"+
"name,"+
"username,"+
"feed,");
request.setParameters(params);
// THIS IS VITAL OR THE BATCH CALLBACK WILL NEVER ARRIVE
request.setCallback(new com.facebook.Request.Callback() {
#Override
public void onCompleted(Response response) {}
});
requests.add(request);
}
I have this snippet
AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(mFacebook);
Bundle bundle = new Bundle();
bundle.putString("fields", "birthday");
mAsyncRunner.request("me/friends", bundle, new FriendListRequestListener());
and it works somehow, I mean I can read the ids from all my friends.
But in I want to read everything how can I do that ?
String _error = null;
JSONObject json = Util.parseJson(response);
final JSONArray friends = json.getJSONArray("data");
for (int i = 0; i < friends.length(); i++) {
Log.v("id:", "id= "+friends.get(i).toString());
}
What should I do to get info about my friends and to read that info
I guess this is the key, this is from the example I found and it works fine
bundle.putString("fields", "birthday");
but when I put for example, doesn't works
bundle.putString("fields", "friends_relationships");
-----------------EDIT 1-------------------------
code for permissions
mFacebook.authorize(Example.this, new String[] {"offline_access", "user_interests", "friends_interests","friends_relationships","friends_relationship_details"},new DialogListener() {
#Override
public void onComplete(Bundle values) {}
#Override
public void onFacebookError(FacebookError error) {}
#Override
public void onError(DialogError e) {}
#Override
public void onCancel() {}
});
-------------- EDIT 2 --------------
{"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthException","code":2500}}
Graph API is the smart choice in most cases. To retrieve your friend information you need to collect some extended permissions from the user first. Then you can retrieve a lot more information other than the basic ones.
Following is a list of extended permissions related to friends different kind of information
friends_about_me
friends_activities
friends_birthday
friends_checkins
friends_education_history
friends_events
friends_games_activity
friends_groups
friends_hometown
friends_interests
friends_likes
friends_location
friends_notes
friends_online_presence
friends_photo_video_tags
friends_photos
friends_relationship_details
friends_relationships
friends_religion_politics
friends_status
friends_subscriptions
friends_videos
friends_website
friends_work_history
facebook.authorize(this, new String[] {"offline_access", "user_interests", "friends_interests"},
Edit :-
If your app needs more than this basic information to function, you
must request specific permissions from the user. This is accomplished
by passing String[] of permissions to the authorize method. The
following example shows how to ask for access to user's email address,
get extended access token and check-in user at a place:
facebook.authorize(this, new String[] { "email", "publish_checkins" },
new DialogListener() {
#Override
public void onComplete(Bundle values) {}
#Override
public void onFacebookError(FacebookError error) {}
#Override
public void onError(DialogError e) {}
#Override
public void onCancel() {}
}
);
Look at here for more details.
Edit :-
mAsyncRunner.request("me/friends?fields=id,name,birthday,relationship_status", new FriendListRequestListener());
JSONObject json = Util.parseJson(response);
final JSONArray friends = json.getJSONArray("data");
for(int i=0;i<friends.length();i++)
{
JSONObject object = friends.getJSONObject(i);
Log.i("------------------ Id",object.getString("id"));
Log.i("------------------ Name",object.getString("name"));
Log.i("------------------ RelationShip",object.getString("relationship_status"));
}
There are separate permissions for your friends relationships. Check out the permissions documentation.
You'll want to request -
friends_relationships
friends_relationship_details
This is now longer possible as of May 2015 when the v1.0 facebook Graph API got deprecated.
try this :
Bundle params = new Bundle();
params.putString("fields", "name, picture, location");
mAsyncFacebook.request("me/friends",params, new RequestListener(){
#Override
public void onComplete(String response, Object object) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(response);
} catch (JSONException e) {
Log.d(TAG,"Exception :"+e);
}
}
}
to know about the keys see this link : https://developers.facebook.com/docs/authentication/permissions/
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());
}