My application is very image centric and would like to allow the user to share images generated by the application on facebook posts. I am of the understanding that "User Generated" can only be used with user/camera taken photos so that is not an option. Correct?
Since I can't specify user generated, I'd like to either:
Set the link on the feed image such that the image in the album is opened, not the default og:url.
This link is by default the og:url specified in the open graph object.
I still need all of the other og:url links in the post except the image to point to the website page.
-OR-
Put an href link in the description (or somewhere else in the feed post) that opens the image in the album.
Unless I am mistaken, It doesn't seem that HTML href tags are allowed in posts/stories. Is there a way to do this in the caption of a custom story?
I am able to upload the image to the app's album and obtain the URL to the image in the album (also using "no story" so that it doesn't create a post).
Is what I'm trying to do possible?
How do I garner more control over the links set in a facebook feed post?
EDIT:
Regarding "User Generated" from facebook docs:
"The User Generated Photos action capability can only be used if the photos are original and taken by a user with an actual camera."
I don't want to generate two stories. Ideally I want ONE story that features an image that can be clicked on that links to the original full size image in the app album. The rest of the story shares some details about the image (desc. etc.). So I guess, in a way, I'm looking for a workaround for the camera/photo requirement.
I don't mind the standard story layout (with a smaller image with title, description/captions) but just want to link that image to one in the users application album.
EDIT:
I'm realizing that an Open Graph Story isn't the way to go here. I have instead gone to simply using the Graph API. (https://developers.facebook.com/docs/graph-api/reference/user/photos/) This allows me to post a link in the user comments along with a photo. For anyone interested:
public static void doImagePost(final Bitmap _sideBySide, String _comments) {
Bundle parameters = new Bundle();
parameters.putParcelable("image", _sideBySide);
String message;
if(_comments != null)
{
if(!_comments.isEmpty())
{
message = _comments + '\n' + '\n' + JSBridge.getURL();
} else {
message = JSBridge.getURL();
}
} else {
message = JSBridge.getURL();
}
//Plain Http://blahblahblah.com/foobar/whatever gets turned into a link in the message field
parameters.putString("message", message);
Bitmap redSideBySide = EHelper.reduceImageSize(_sideBySide, (int)4E6);
Session session = Session.getActiveSession();
if(session == null) {
requestPublish(MODE_PHOTO, redSideBySide, _comments);
return;
} else {
if(!session.isOpened())
{
requestPublish(MODE_PHOTO, redSideBySide, _comments);
return;
}
}
//Here is the Graph API request.
Request imagePostRequest = new Request(Session.getActiveSession(), "me/photos" , parameters, HttpMethod.POST, new Request.Callback() {
#Override
public void onCompleted(Response response) {
if(response.getError() == null)
{
Toast.makeText(m_Context, "Post image success", Toast.LENGTH_SHORT).show();
//m_Images = null;
dismissProgressDlg();
} else {
Toast.makeText(m_Context, "Error posting image to facebook: " + response.getError().getErrorMessage(), Toast.LENGTH_SHORT).show();
Log.e(DEBUG_TAG, "Error posting image to facebook: " + response.getError().getErrorMessage());
dismissProgressDlg();
}
}
});
showProgressDialog("Posting to Facebook...");
imagePostRequest.executeAsync();
}
Related
I am trying to get my friend name and ids with Graph API v2.0, but data returns empty:
{
"data": [
]
}
When I was using v1.0, everything was OK with the following request:
FBRequest* friendsRequest = [FBRequest requestForMyFriends];
[friendsRequest startWithCompletionHandler: ^(FBRequestConnection *connection,
NSDictionary* result,
NSError *error) {
NSArray* friends = [result objectForKey:#"data"];
NSLog(#"Found: %i friends", friends.count);
for (NSDictionary<FBGraphUser>* friend in friends) {
NSLog(#"I have a friend named %# with id %#", friend.name, friend.id);
}
}];
But now I cannot get friends!
In v2.0 of the Graph API, calling /me/friends returns the person's friends who also use the app.
In addition, in v2.0, you must request the user_friends permission from each user. user_friends is no longer included by default in every login. Each user must grant the user_friends permission in order to appear in the response to /me/friends. See the Facebook upgrade guide for more detailed information, or review the summary below.
If you want to access a list of non-app-using friends, there are two options:
If you want to let your people tag their friends in stories that they publish to Facebook using your App, you can use the /me/taggable_friends API. Use of this endpoint requires review by Facebook and should only be used for the case where you're rendering a list of friends in order to let the user tag them in a post.
If your App is a Game AND your Game supports Facebook Canvas, you can use the /me/invitable_friends endpoint in order to render a custom invite dialog, then pass the tokens returned by this API to the standard Requests Dialog.
In other cases, apps are no longer able to retrieve the full list of a user's friends (only those friends who have specifically authorized your app using the user_friends permission). This has been confirmed by Facebook as 'by design'.
For apps wanting allow people to invite friends to use an app, you can still use the Send Dialog on Web or the new Message Dialog on iOS and Android.
UPDATE: Facebook have published an FAQ on these changes here: https://developers.facebook.com/docs/apps/faq which explain all the options available to developers in order to invite friends etc.
Although Simon Cross's answer is accepted and correct, I thought I would beef it up a bit with an example (Android) of what needs to be done. I'll keep it as general as I can and focus on just the question. Personally I wound up storing things in a database so the loading was smooth, but that requires a CursorAdapter and ContentProvider which is a bit out of scope here.
I came here myself and then thought, now what?!
The Issue
Just like user3594351, I was noticing the friend data was blank. I found this out by using the FriendPickerFragment. What worked three months ago, no longer works. Even Facebook's examples broke. So my issue was 'How Do I create FriendPickerFragment by hand?
What Did Not Work
Option #1 from Simon Cross was not strong enough to invite friends to the app. Simon Cross also recommended the Requests Dialog, but that would only allow five requests at a time. The requests dialog also showed the same friends during any given Facebook logged in session. Not useful.
What Worked (Summary)
Option #2 with some hard work. You must make sure you fulfill Facebook's new rules: 1.) You're a game 2.) You have a Canvas app (Web Presence) 3.) Your app is registered with Facebook. It is all done on the Facebook developer website under Settings.
To emulate the friend picker by hand inside my app I did the following:
Create a tab activity that shows two fragments. Each fragment shows a list. One fragment for available friend (/me/friends) and another for invitable friends (/me/invitable_friends). Use the same fragment code to render both tabs.
Create an AsyncTask that will get the friend data from Facebook. Once that data is loaded, toss it to the adapter which will render the values to the screen.
Details
The AsynchTask
private class DownloadFacebookFriendsTask extends AsyncTask<FacebookFriend.Type, Boolean, Boolean> {
private final String TAG = DownloadFacebookFriendsTask.class.getSimpleName();
GraphObject graphObject;
ArrayList<FacebookFriend> myList = new ArrayList<FacebookFriend>();
#Override
protected Boolean doInBackground(FacebookFriend.Type... pickType) {
//
// Determine Type
//
String facebookRequest;
if (pickType[0] == FacebookFriend.Type.AVAILABLE) {
facebookRequest = "/me/friends";
} else {
facebookRequest = "/me/invitable_friends";
}
//
// Launch Facebook request and WAIT.
//
new Request(
Session.getActiveSession(),
facebookRequest,
null,
HttpMethod.GET,
new Request.Callback() {
public void onCompleted(Response response) {
FacebookRequestError error = response.getError();
if (error != null && response != null) {
Log.e(TAG, error.toString());
} else {
graphObject = response.getGraphObject();
}
}
}
).executeAndWait();
//
// Process Facebook response
//
//
if (graphObject == null) {
return false;
}
int numberOfRecords = 0;
JSONArray dataArray = (JSONArray) graphObject.getProperty("data");
if (dataArray.length() > 0) {
// Ensure the user has at least one friend ...
for (int i = 0; i < dataArray.length(); i++) {
JSONObject jsonObject = dataArray.optJSONObject(i);
FacebookFriend facebookFriend = new FacebookFriend(jsonObject, pickType[0]);
if (facebookFriend.isValid()) {
numberOfRecords++;
myList.add(facebookFriend);
}
}
}
// Make sure there are records to process
if (numberOfRecords > 0){
return true;
} else {
return false;
}
}
#Override
protected void onProgressUpdate(Boolean... booleans) {
// No need to update this, wait until the whole thread finishes.
}
#Override
protected void onPostExecute(Boolean result) {
if (result) {
/*
User the array "myList" to create the adapter which will control showing items in the list.
*/
} else {
Log.i(TAG, "Facebook Thread unable to Get/Parse friend data. Type = " + pickType);
}
}
}
The FacebookFriend class I created
public class FacebookFriend {
String facebookId;
String name;
String pictureUrl;
boolean invitable;
boolean available;
boolean isValid;
public enum Type {AVAILABLE, INVITABLE};
public FacebookFriend(JSONObject jsonObject, Type type) {
//
//Parse the Facebook Data from the JSON object.
//
try {
if (type == Type.INVITABLE) {
//parse /me/invitable_friend
this.facebookId = jsonObject.getString("id");
this.name = jsonObject.getString("name");
// Handle the picture data.
JSONObject pictureJsonObject = jsonObject.getJSONObject("picture").getJSONObject("data");
boolean isSilhouette = pictureJsonObject.getBoolean("is_silhouette");
if (!isSilhouette) {
this.pictureUrl = pictureJsonObject.getString("url");
} else {
this.pictureUrl = "";
}
this.invitable = true;
} else {
// Parse /me/friends
this.facebookId = jsonObject.getString("id");
this.name = jsonObject.getString("name");
this.available = true;
this.pictureUrl = "";
}
isValid = true;
} catch (JSONException e) {
Log.w("#", "Warnings - unable to process Facebook JSON: " + e.getLocalizedMessage());
}
}
}
Facebook has revised their policies now. You can’t get the whole friendlist anyway if your app does not have a Canvas implementation and if your app is not a game. Of course there’s also taggable_friends, but that one is for tagging only.
You will be able to pull the list of friends who have authorised the app only.
The apps that are using Graph API 1.0 will be working till April 30th, 2015 and after that it will be deprecated.
See the following to get more details on this:
User Friends
Facebook Application Development FAQ
In Swift 4.2 and Xcode 10.1:
If you want to get the friends list from Facebook, you need to submit your app for review in Facebook. See some of the Login Permissions:
Login Permissions
Here are the two steps:
1) First your app status is must be in Live
2) Get required permissions form Facebook.
1) Enable our app status live:
Go to the apps page and select your app
https://developers.facebook.com/apps/
Select status in the top right in Dashboard.
Submit privacy policy URL
Select category
Now our app is in Live status.
One step is completed.
2) Submit our app for review:
First send required requests.
Example: user_friends, user_videos, user_posts, etc.
Second, go to the Current Request page
Example: user_events
Submit all details
Like this submit for all requests (user_friends , user_events, user_videos, user_posts, etc.).
Finally submit your app for review.
If your review is accepted from Facebook's side, you are now eligible to read contacts, etc.
As Simon mentioned, this is not possible in the new Facebook API. Pure technically speaking you can do it via browser automation.
this is against Facebook policy, so depending on the country where you live, this may not be legal
you'll have to use your credentials / ask user for credentials and possibly store them (storing passwords even symmetrically encrypted is not a good idea)
when Facebook changes their API, you'll have to update the browser automation code as well (if you can't force updates of your application, you should put browser automation piece out as a webservice)
this is bypassing the OAuth concept
on the other hand, my feeling is that I'm owning my data including the list of my friends and Facebook shouldn't restrict me from accessing those via the API
Sample implementation using WatiN:
class FacebookUser
{
public string Name { get; set; }
public long Id { get; set; }
}
public IList<FacebookUser> GetFacebookFriends(string email, string password, int? maxTimeoutInMilliseconds)
{
var users = new List<FacebookUser>();
Settings.Instance.MakeNewIeInstanceVisible = false;
using (var browser = new IE("https://www.facebook.com"))
{
try
{
browser.TextField(Find.ByName("email")).Value = email;
browser.TextField(Find.ByName("pass")).Value = password;
browser.Form(Find.ById("login_form")).Submit();
browser.WaitForComplete();
}
catch (ElementNotFoundException)
{
// We're already logged in
}
browser.GoTo("https://www.facebook.com/friends");
var watch = new Stopwatch();
watch.Start();
Link previousLastLink = null;
while (maxTimeoutInMilliseconds.HasValue && watch.Elapsed.TotalMilliseconds < maxTimeoutInMilliseconds.Value)
{
var lastLink = browser.Links.Where(l => l.GetAttributeValue("data-hovercard") != null
&& l.GetAttributeValue("data-hovercard").Contains("user.php")
&& l.Text != null
).LastOrDefault();
if (lastLink == null || previousLastLink == lastLink)
{
break;
}
var ieElement = lastLink.NativeElement as IEElement;
if (ieElement != null)
{
var htmlElement = ieElement.AsHtmlElement;
htmlElement.scrollIntoView();
browser.WaitForComplete();
}
previousLastLink = lastLink;
}
var links = browser.Links.Where(l => l.GetAttributeValue("data-hovercard") != null
&& l.GetAttributeValue("data-hovercard").Contains("user.php")
&& l.Text != null
).ToList();
var idRegex = new Regex("id=(?<id>([0-9]+))");
foreach (var link in links)
{
string hovercard = link.GetAttributeValue("data-hovercard");
var match = idRegex.Match(hovercard);
long id = 0;
if (match.Success)
{
id = long.Parse(match.Groups["id"].Value);
}
users.Add(new FacebookUser
{
Name = link.Text,
Id = id
});
}
}
return users;
}
Prototype with implementation of this approach (using C#/WatiN) see https://github.com/svejdo1/ShadowApi. It is also allowing dynamic update of Facebook connector that is retrieving a list of your contacts.
Try /me/taggable_friends?limit=5000 using your JavaScript code
Or
try the Graph API:
https://graph.facebook.com/v2.3/user_id_here/taggable_friends?access_token=
If you are still struggling with this issue on a development mode.
Follow the same process as mentioned below:
create a test app of your main app,
create test users, automatically install app for test users and assign them 'user_friend' permission.
Add your test users as a friend with each other.
I followed the same process after going through alot of research and finally it worked.
In the Facebook SDK Graph API v2.0 or above, you must request the user_friends permission from each user in the time of Facebook login since user_friends is no longer included by default in every login; we have to add that.
Each user must grant the user_friends permission in order to appear in the response to /me/friends.
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.loginBehavior = FBSDKLoginBehavior.web
fbLoginManager.logIn(withReadPermissions: ["email","user_friends","public_profile"], from: self) { (result, error) in
if (error == nil) {
let fbloginresult : FBSDKLoginManagerLoginResult = result!
if fbloginresult.grantedPermissions != nil {
if (fbloginresult.grantedPermissions.contains("email")) {
// Do the stuff
}
else {
}
}
else {
}
}
}
So at the time of Facebook login, it prompts with a screen which contain all the permissions:
If the user presses the Continue button, the permissions will be set. When you access the friends list using Graph API, your friends who logged into the application as above will be listed
if ((FBSDKAccessToken.current()) != nil) {
FBSDKGraphRequest(graphPath: "/me/friends", parameters: ["fields" : "id,name"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil) {
print(result!)
}
})
}
The output will contain the users who granted the user_friends permission at the time of login to your application through Facebook.
{
data = (
{
id = xxxxxxxxxx;
name = "xxxxxxxx";
}
);
paging = {
cursors = {
after = xxxxxx;
before = xxxxxxx;
};
};
summary = {
"total_count" = 8;
};
}
I'm trying to share a link(my Google Play app link) using ShareDialog from Facebook SDK but the problem is that when the URL is my app's Google Play link the other information is not displayed correctly... Actually it's displaying only the link from Google Play without name or description!
Here's the code:
FacebookDialog shareDialog = new FacebookDialog.ShareDialogBuilder(
this)
.setLink("https://play.google.com/store/apps/details?id=<myapp>")
.setDescription("Test")
.setName("Test for facebook")
.build();
uiHelper.trackPendingDialogCall(shareDialog.present());
I tried everything and with other URL's actually is working(displaying name, description, caption etc.) but not with the app's URL.
Does anyone know why a Google Play link won't work with text, description or caption?
Actually if you specify the contentUrl (as in 4.0) or link (as in your case), it overrides the name, description, etc. You just don't need to give other things as it then becomes responsibility of url host to supply the details that should be shown when it gets posted on Facebook timeline.
Although, if you want to share something like Message from user followed by your app link. Then I would suggest to go for Graph API (I wasted 2-3 days in posting something like this via ShareApi/ShareDialog but ended up with using Graph API only.)
Code to share using Graph API:
// Constants to be used when sharing message on facebook time line.
private static final int FACEBOOK_ERROR_PERMISSION = 200;
private static final String PARAM_EXPLICIT = "fb:explicitly_shared";
private static final String PARAM_GRAPH_PATH = "/me/feed";
private static final String PARAM_MSG = "message";
private static final String PARAM_LINK = "link";
// Create the parameter for share.
final Bundle params = new Bundle();
params.putBoolean(PARAM_EXPLICIT, true);
params.putString(PARAM_LINK, BirdingUtah.APP_URL);
// If message is empty, only our link gets posted.
String message = "This is the message to share";
if (!TextUtils.isEmpty(message))
params.putString(PARAM_MSG, message);
// Send the request via Graph API of facebook to post message on time line.
new GraphRequest(AccessToken.getCurrentAccessToken(), PARAM_GRAPH_PATH,
params, HttpMethod.POST, new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse graphResponse) {
searchDialog.dismiss();
if (graphResponse.getError() == null) {
// Success in posting on time line.
Logger.toastShort(R.string.msg_share_success);
Logger.debug(TAG, "Success: " + graphResponse);
} else {
FacebookRequestError error = graphResponse.getError();
if (error.getErrorCode() == FACEBOOK_ERROR_PERMISSION)
// Cancelled while asking permission, show msg
Logger.toastLong(R.string.msg_share_permission);
else
// Error occurred while posting message.
Logger.toastShort(R.string.msg_share_error);
Logger.error(TAG, "Error: " + error);
}
// Enable the button back again if profile and access token are non null.
if (Profile.getCurrentProfile() != null || AccessToken.getCurrentAccessToken() != null)
mShareButton.setEnabled(true);
}
}).executeAsync();
Hi,
I am new to android trying to integrate twitter with my application. I need to do get twitter profile name and profile picture once the user is logged in. I am able to get profile name but not the profile picture. How can I get the profile picture?
You can get some information in this way:
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient();
twitterApiClient.getAccountService().verifyCredentials(false, false, new Callback<User>() {
#Override
public void success(Result<User> userResult) {
String name = userResult.data.name;
String email = userResult.data.email;
// ... other infos
// Get the profile pic
// _normal (48x48px) | _bigger (73x73px) | _mini (24x24px)
String photoUrlNormalSize = userResult.data.profileImageUrl;
String photoUrlBiggerSize = userResult.data.profileImageUrl.replace("_normal", "_bigger");
String photoUrlMiniSize = userResult.data.profileImageUrl.replace("_normal", "_mini");
String photoUrlOriginalSize = userResult.data.profileImageUrl.replace("_normal", "");
}
#Override
public void failure(TwitterException exc) {
Log.d("TwitterKit", "Verify Credentials Failure", exc);
}
});
From the official doc:
You can obtain a user’s most recent profile image from GET users/show. Within the user object, you’ll find the profile_image_url
and profile_image_url_https fields. These fields will contain the
resized “normal” variant of the user’s uploaded image. This “normal”
variant is typically 48x48px.
By modifying the URL, you can retrieve other variant sizings such as
“bigger”, “mini”, and “original”.
If you've fetched the user profile, look out for the json entry called 'profile_image_url'. Some documenetation from twitter on this can also be found here. Use this in conjunction with an ImageDownloader to download the image to be used as a bitmap in your project. This is the number one google result of how to download and display an image:
http://getablogger.blogspot.com/2008/01/android-download-image-from-server-and.html
private TwitterApp mTwitter;
mTwitter.getUserProfileImage();
Returns the profile pic of the Logged in user.
Also u can customize the pic according refer : Android Twitter getting profile image size issue
I had used a facebook app to post message on wall from https://github.com/facebook/facebook-android-sdk.
Here after user allows the app to use his/her profile, dialog feed comes with an editable area to publish or skip. I want a predefined message there but user will not be able to modify it. I am able to send the predifined message but its editable. How to make it uneditable.
Does any one knows how to do it??
You can just use a function to post directly to the users wall. Just make sure that it is clear to the user that the button posts directly, perhaps use a dialog to get them to confirm they want to post. Here is the code I use:
/**
* Post to a friends wall
* #param msg Message to post
* #param userId Id for friend to post to or null to post to users wall
*/
public void postToWall(String msg, String userID) {
Log.d("Tests", "Testing graph API wall post");
try {
if (isSession()) {
String response = mFacebook.request((userID == null) ? "me" : userID);
Bundle parameters = new Bundle();
parameters.putString("message", msg);
response = mFacebook.request(((userID == null) ? "me" : userID) + "/feed", parameters, "POST");
Log.d(TAG,response);
if (response == null || response.equals("") ||
response.equals("false")) {
Log.v("Error", "Blank response");
}
} else {
// no logged in, so relogin
Log.d(TAG, "sessionNOTValid, relogin");
mFacebook.authorize(this, PERMS, new LoginDialogListener());
}
} catch(Exception e) {
e.printStackTrace();
}
}
The dialog contains a WebView that loads the actual content from a Facebook URL. So to modify the editable area, you would need to modify the DOM of this webpage. See this question for more information about doing that. It is unclear to me from the answers in that question if this is possible. If it is, you'll need to add the code to the FbDialog class in the Facebook Android SDK.
I'm new to Facebook API on Android, and basically, what I'm trying to do is creating custom wall post for an application I'm developing.
Like when you listen a Shazam a song and you can share the result with your friends.
I believe I've got to create a custom attachment. Here's my code for setting the attachment:
mPostButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Bundle myParams = new Bundle();
String attachment="{\"name\":\"Gran Turismo 5\"," +
"\"href\":\"http://www.unknown.com/?lang=fr\"," +
"\"caption\":\"Sony Computer Entertainment\",\"description\":" +
"\"Une vidéo proposée par Cedemo.\",\"media\":" +
"[{\"type\":\"image\",\"src\":" +
"\"http://www.unknown.com/prepicture//thumb_title/15/15061_1.jpg\"," +
"\"href\":\"http://www.unknown.com/?lang=fr\"}],\"properties\":" +
"{\"Autre lien\":{\"text\":\"Cedemo\",\"href\":\"http://www.unknown.com\"}}}";
myParams.putString("attachment", URLEncoder.encode(attachment);
mFacebook.dialog(Option.this, "stream.publish",myParams,
new SampleDialogListener());
And then, later on:
public class SampleDialogListener extends BaseDialogListener {
public void onComplete(Bundle values) {
final String postId = values.getString("post_id");
if (postId != null) {
Log.d("Facebook-Example", "Dialog Success! post_id=" + postId);
mAsyncRunner.request(postId,values, new WallPostRequestListener());
} else {
Log.d("Facebook-Example", "No wall post made");
}
}
}
I didn't wrote the attachment String, It's just a test taken from another question made in this forum. Anyway, when I call myAsync.request, my app shows an error message, how am I supposed to pass the attachment to my dialog?
Hope I've been clear enough.
Are you sure you need to set custom parameters? It sounds like you can just want to post a Facebook message directly to the wall: you can do this by simply handing in the message parameter as a string -- you only need all that JSON if you want to attach an image etc. And note on facebook's page it says using this api call won't post a status update that others can see on their feed, it will just appear on their own wall. If you just want to post a message with a link you should just be able to use your mAsyncRunner (once you have your valid Facebook session) using this:
String message = "Post this to my wall";
Bundle parameters = new Bundle();
parameters.putString("message", message);
mAsyncRunner.request("me/feed", parameters, "POST", new WallPostRequestListener());
Also may help if you posted the error/response code you're getting from Facebook.