I'm using Quick blox and I downloaded Sample app (https://github.com/QuickBlox/quickblox-ios-sdk/tree/master/sample-chat) which uses QMChatViewController, QMServices.
I am using MessageStatusStringBuilder class methods in ChatViewController to get the status (read/delivered/sent) of message (here this message is not a string it is an instance of QBChatMessage) in ChatViewController so that I'm showing the message status when ever QMChatServiceDelegate calls backs were called.
I have a requirement to show the status(read/delivered/sent) of last message in DialogsViewController under each dialog also.
But in DialogsViewController lastTextMessage is a string but not a QBChatMessage instance.
How to update this message status?
One plus point is I will get callbacks from this QMChatServiceDelegate in DialogsViewController also, even I can't find the status of message from that.
So how to handle this?
First you should get the message with the extended request using date_send as key and dialog's lastMessageDate as value. Then using the instance of the MessageStatusStringBuilder class you can get the status of the last message.
QBChatDialog *dialog = ... // your dialog
QBResponsePage *resPage = [QBResponsePage responsePageWithLimit:1 skip:0];
NSMutableDictionary *extendedRequest = #{#"date_sent" : [NSString stringWithFormat:#"%tu", (NSUInteger)[dialog.lastMessageDate timeIntervalSince1970]]}.mutableCopy;
[QBRequest messagesWithDialogID:dialog.ID extendedRequest:extendedRequest forPage:resPage successBlock:^(QBResponse *response, NSArray *messages, QBResponsePage *responcePage) {
NSLog(#"status = %#",[self.stringBuilder statusFromMessage:[messages firstObject]]);
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];
I am trying to share a link using the FB messenger. When i try to share the link to facebook i keep getting an error. I googled for an answer and the couple of solutions i found did not help since everything in the plist is correct. If anyone has any advice i would really appreciate it, been trying to solve this all day.
Error:
Invalid use of FBAppCall, fb839771929379526 is not registered as a URL Scheme. Did you set 'FacebookUrlSchemeSuffix' in your plist?
Code:
// Check if the Facebook app is installed and we can present
// the message dialog
FBLinkShareParams *params = [[FBLinkShareParams alloc] init];
params.link = [NSURL URLWithString:filePath];
params.name = #"My Video";
// If the Facebook app is installed and we can present the share dialog
if ([FBDialogs canPresentMessageDialogWithParams:params]) {
// Enable button or other UI to initiate launch of the Message Dialog
// Present message dialog
[FBDialogs presentMessageDialogWithLink:[NSURL URLWithString:#"https://developers.facebook.com/ios"] handler:^(FBAppCall *call, NSDictionary *results, NSError *error) {
if(error) {
// An error occurred, we need to handle the error
// See: https://developers.facebook.com/docs/ios/errors
NSLog([NSString stringWithFormat:#"Error messaging link: %#", error.description
]);
} else {
// Success
NSLog(#"result %#", results);
}
}];
} else {
// Disable button or other UI for Message Dialog
}
}
My question is predicated on Jason Clark’s statement at f8 2014 that app links is designed to sit side by side well with deep linking technologies. I have a word game app published in 2013 to Canada and Australia using Facebook’s authentication but without deep linking. For the US market launch my intent was to add Facebook deep linking. Managed with the request and feed dialogs to send the Match Identifier UUID for both initiating a match and then bragging about the match (FriendSmash example) at that time to open the game on that match. My day job got in the way and I did not have time to finish QA and support a launch to the US. Last summer I upgraded SDKs (Facebook 3.14) and the url query no longer contained the string ‘notif’ to allow me to parse for the match Id. Therefore, I switched from using [FBSession.activeSession handleOpenURL:url] to the current [FBAppCall handleOpenURL:url …] and some other code from the new FriendSmash example. However, the url passed from the Facebook app no longer contains the ‘ref’ and therefore not the ‘notif’ which was the method documented to utilize my deep linking content. I have since updated my project to Facebook iOS SDK 3.21 (predicated in part by other SDKs, e.g. AWS not supporting arm64).
I currently use the following code to send the brag
- (void) sendBrag
{
// This function will invoke the Feed Dialog to post to a user's Timeline and News Feed
// It will attemnt to use the Facebook Native Share dialog
// If that's not supported we'll fall back to the web based dialog.
NSArray *friend = [[NSArray alloc] initWithObjects: bragMatch.opponentFacebookId, nil];
NSString *linkURL = [NSString stringWithFormat:#"http://www.ruleofwords.com/?deeplink_matchno=%#", bragMatch.initiatorMatchNo];
//NSString *linkURL = [NSString stringWithFormat:#"http://www.ruleofwords.com"];
NSString *pictureURL = #"https://pacific-castle-1361.herokuapp.com/rowappicon.png";
NSMutableString *msg = [[NSMutableString alloc]
initWithString:#"Just scored 0 points in Rule of Words. Good luck trying to beat that."];
[msg replaceOccurrencesOfString:#"0" withString:bragMatch.initiatorMatchPoints
options:NSBackwardsSearch range: NSMakeRange(0, [msg length])];
// Prepare the native share dialog parameters
FBLinkShareParams *shareParams = [[FBLinkShareParams alloc] init];
shareParams.friends = friend;
shareParams.link = [NSURL URLWithString:linkURL];
shareParams.name = #"Rule of Words Bragging Rights";
shareParams.caption= msg;
shareParams.picture= [NSURL URLWithString:pictureURL];
shareParams.linkDescription = #"Rule of Words, the contagious photography word social game on iPhone.";
if ([FBDialogs canPresentShareDialogWithParams:shareParams]){
[FBDialogs presentShareDialogWithParams:shareParams
clientState:nil
handler:^(FBAppCall *call, NSDictionary *results, NSError *error) {
if(error) {
NSLog(#"Error publishing story.");
} else if (results[#"completionGesture"] && [results[#"completionGesture"] isEqualToString:#"cancel"]) {
NSLog(#"User canceled story publishing.");
} else {
NSLog(#"Story published.");
}
}];
} else {
// Prepare the web dialog parameters
NSDictionary *params = #{
#"to": bragMatch.opponentFacebookId,
#"name" : shareParams.name,
#"caption" : shareParams.caption,
#"description" : shareParams.linkDescription,
#"picture" : pictureURL,
#"link" : linkURL
};
// Invoke the dialog
[FBWebDialogs presentFeedDialogModallyWithSession:nil
parameters:params
handler:
^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
if (error) {
NSLog(#"Error publishing story %#.", error);
} else {
if (result == FBWebDialogResultDialogNotCompleted) {
NSLog(#"User canceled story publishing.");
} else {
NSLog(#"Story published.");
}
}}];
}
}
(Aside - In my stepping through the sendBrag code the FBDialogs canPresentShareDialogWithParams always fails so that every time it defaults to a feed dialog. Anyone know what is the state is where the share dialog works? )
Then in my AppDelegate I have…
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
NSLog(#"app is %# and url is %# and sourceApp is %#", application, url, sourceApplication);
// attempt to extract a token from the url
return [FBAppCall handleOpenURL:url
sourceApplication:sourceApplication
fallbackHandler:^(FBAppCall *call) {
// If there is an active session
if (FBSession.activeSession.isOpen) {
// Check the incoming link
[self handleAppLinkData:call.appLinkData];
} else {
NSLog(#"Access Token is %#", call.accessTokenData);
if (call.accessTokenData) {
// If token data is passed in and there's
// no active session.
if ([self handleAppLinkToken:call.accessTokenData]) {
// Attempt to open the session using the
// cached token and if successful then
// check the incoming link
[self handleAppLinkData:call.appLinkData];
}
}
}
}];
- (void) handleAppLinkData:(FBAppLinkData *)appLinkData {
NSURL *targetURL = appLinkData.targetURL;
if (targetURL) {
//NSURL *targetURL = [NSURL URLWithString:targetURLString];
NSDictionary *targetParams = [self parseURLParams:[targetURL query]];
NSString *ref = [targetParams valueForKey:#"ref"];
// Check if ref parm is among incoming news feed link, otw attribution link
if ([ref isEqualToString:#"notif"]) {
// Get the request id
NSString *requestIDParam = targetParams[#"request_ids"];
NSArray *requestIDs = [requestIDParam
componentsSeparatedByString:#","];
// Get data (of last request) from Graph API call to request id endpoint
//
[self notificationGet:requestIDs[[requestIDs count]-1]];
}
}
}
- (void) notificationGet:(NSString *)requestid {
__block NSString *title;
__block NSString *message;
[FBRequestConnection startWithGraphPath:requestid
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
if (! error) {
if (result[#"data"])
{
title = [NSString stringWithFormat:
#"%# requests a match!", result[#"from"][#"name"]];
NSString *jsonString = result[#"data"];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
if (!jsonData) {
NSLog(#"JSON decode error: %#", error);
return;
}
NSError *jsonError = nil;
NSDictionary *requestData =[NSJSONSerialization JSONObjectWithData:jsonData options:0
error:&jsonError];
if (jsonError) {
NSLog(#"JSON decode error: %#", error);
return;
}
message = [NSString stringWithFormat:#"Match #: %#, Flashes: %#",
requestData[#"deeplink_matchno"],
requestData[#"flashes_gifted"]];
// set global opponentFacebookId for bragging
[[rowGlobals sharedGlobalVars] setRowGlobal:requestData[#"deeplink_matchno"]
forKey:#"deeplink_matchno"] ;
// Set up FB Deep Link Notification
// homeViewController is registered for notification
[[NSNotificationCenter defaultCenter]
postNotificationName:FBDeepLinkNotification
object:requestData[#"deeplink_matchno"]];
NSLog(#"successfully posted DeepLink notification") ;
} else {
title = [NSString stringWithFormat:#"%# sent you a request", result[#"from"][#"name"]];
message = result[#"message"];
}
// Delete the request notification
[self notificationClear:result[#"id"]];
} else {
title = #"General Deep Link Error" ;
message = #"Error occured with Facebook FBRequest Connection. This Facebook notification likely has been previously processed." ;
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil,
nil];
[alert show];
}];
}
Now I recognize I have some clean up to align the dialog setup with how I parse appLinkData to get the matchId UUID for my NSNotification to open on the game, but I am not getting that far to bother cleaning it up.
I have tried many meta tags on my site but at the moment I am just using
<meta property=”al:ios:url” content=”ruleofwords”>
where ruleofwords is a custom URL I added to my app’s plist.
but I cannot seem to put together any URL other than
NSString *linkURL = [NSString stringWithFormat:#"http://www.ruleofwords.com"];
which will launch my game by clicking on the Facebook link…
When I use anything like
NSString *urlLink = [NSString stringWithFormat:#"https://www.ruleofwords.com/?deeplink_matchNo=%#", bragMatch.initiatorMatchNo];
Then Facebook will only launch my web page without the custom URL link to my game.
Moreover, Facebook no longer launches it directly; it brings up my web page with an added link displayed as the offset brackets app Links logo.(Although not explicit it does technically follow the Facebook flow diagram). Touching this app Link logo does launch my game. This seems to be the case whether I have the meta tag on my website or not (now I may have other problems since we are only using Godaddy website builder).
Previously with the request dialog I had the ability to populate values such as #”data” with things like my match Id and gifts
NSData *jsonData = [NSJSONSerialization
dataWithJSONObject:#{
#"deeplink_matchno": bragMatch.initiatorMatchNo,
#"flashes_gifted": #"0"}
options:0
error:&error];
if (!jsonData) {
NSLog(#"JSON error: %#", error);
return;
}
NSString *challengeStr = [[NSString alloc]
initWithData:jsonData
encoding:NSUTF8StringEncoding];
NSMutableDictionary *params =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
bragMatch.opponentFacebookId, #"to",
#"Rule of Words Bragging", #"name",
msg, #"caption",
#"Rule of Words, the contagious photography word social game on iPhone.",
#"description",
urlLink, #"link",
#"https://pacific-castle-6969.herokuapp.com/rowappicon.png", #"picture",
challengeStr, #"data",
nil];
// Invoke the dialog
//[self.facebook dialog:#"feed" andParams:params andDelegate:self];
//[FBWebDialogs presentFeedDialogModallyWithSession:nil
[FBWebDialogs presentRequestsDialogModallyWithSession:nil
message:msg
title:nil
parameters:params
handler:
^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
if (error) {
// Case A: Error launching the dialog or publishing story.
NSString *errormsg = [NSString stringWithFormat:#"Error encountered posting Facebook brag with error %#", error.localizedDescription];
NSLog(#"%#", errormsg);
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Facebook Brag Error"
message:errormsg
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
} else {
if (result == FBWebDialogResultDialogNotCompleted) {
// Case B: User clicked the "x" icon
NSLog(#"Player canceled Facebook brag post via x icon.");
} else {
// Case C: Dialog shown and the user clicks Cancel or Share
NSDictionary *urlParams = [self parseURLParams:[resultURL query]];
//if (![urlParams valueForKey:#"post_id"]) {
if ([urlParams valueForKey:#"error_code"]) {
// User clicked the Cancel button
NSLog(#"error message is %#", [urlParams valueForKey:#"error_message"]);
NSLog(#"Player canceled Facebook brag post via Cancel button.");
} else {
// User clicked the Share button
//NSString *postID = [urlParams valueForKey:#"post_id"];
NSString *postID = [urlParams valueForKey:#"request"];
NSLog(#"Player Successfuly Posted RoW Match via Facebook brag, id: %#", postID);
}
}
}
}];
However, I no longer have al_applink_data in the passed URL for this request dialog, it just has an access_token with the original custom URL.
url is fb407545862655947://authorize/#access_token=CAAFyqSpfj8sBAGxahmdTCl1D9fs5hZBt3OfKP2MHCtM8STHadqEjlyFnXDTNHScjsxZCI6q0H8ZAppNSqJIJt83uN4LemkfklLjOdPTv3JZBtg3xTVZBKOhzdOMaZCGob5x2FPddZBzmaZBhIaE8dIgNqPfi9IlEuwQ2oHq6tEgA1w1pNESnHuDyK9gD7vswAC93nO7cCmCT4KBgxI22UDB3nINYZA058g8AZD&expires_in=3600 and sourceApp is com.facebook.Facebook
When I add the #”data” param with
[FBWebDialogs presentFeedDialogModallyWithSession:…]
although this argument is accepted by the feed dialog I the url does not get my match UUID or anything extra from my #”data” param…
url is ruleofwords:///?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fwww.ruleofwords.com%5C%2F%22%2C%22extras%22%3A%7B%22fb_ref%22%3A%22Default%22%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fbacktrack_id%3Ddlr5p6iu_6a-OeUn%22%2C%22app_name%22%3A%22Facebook%22%7D%7D and sourceApp is com.facebook.Facebook
So I am at a loss how I am supposed to inject content specific information so that I can open my game with the match, which the opponent has requested or bragged about. I probably would have given up a long time ago but I did once have deep linking working (SDK 3.5?). I am wondering if I should be at another release level of the SDK for deep linking. It seems like the Facebook platform has significantly changed how it packages appLinkData. And although Facebook’s documentation has improved over the past two years, many of the examples which are required to put this all together do not seem to be referring to the same level of SDK. So Facebook how do I inject content into appLinkData so I can support deep linking with SDK 3.21? I thought about adding the Bolts framework but Jason implied it was designed for outlinking apps, which is not my case.
I can directly type in my iPhone Safari something like ‘ruleofwords://matchId=UUID’ and get the app delegate to parse out the [url query] so I could probably implement deep linking with push notifications, but I still like the ability to have a Facebook user tap on a link and launch the specific match directly.
There doesn't appear to be a straight forward way to post a GIF to Tumblr from an iPhone device?
I use the TMTumblrSDK for oauth authentication, but I haven't found a way to get a GIF posted to Tumblr after authenticating. Using the post: methods always give me an error.
Not only that, but it appears even the native client doesn't post GIFs correctly, so I'm wondering if GIFs can even be posted from mobile.
Here is the main chunk of code that matters:
[TMAPIClient sharedInstance].OAuthConsumerKey = #"consumerKeyHere";
[TMAPIClient sharedInstance].OAuthConsumerSecret = #"secretHere";
[TMAPIClient sharedInstance].OAuthToken = #"token";
[TMAPIClient sharedInstance].OAuthTokenSecret = #"tokenSecret";
[[TMAPIClient sharedInstance] authenticate:#"testApp" callback:^(NSError * error) {
//authenticating works
[[TMAPIClient sharedInstance] userInfo:^(id userInfo, NSError *error) {
//userInfo works
NSString * stringData = [gifData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
[[TMAPIClient sharedInstance] post:#"myTumblrDomain.tumblr.com" type:#"photo" parameters:#{#"data": stringData,
#"tags": #"test",
#"caption": #"Test caption"} callback:^(id moreInfo, NSError *error) {
//401 here. Works if I use a text post instead
NSLog(#"Post Info %# Error %#", moreInfo, error);
}];
}];
}];
Some form of this has been asked/answered before but I'm still pretty hazy on the issue. I'm trying to post to a friends feed but keep getting "error com.facebook.sdk code = 5" errors when trying to use startWithGraphPath: from the new FB SDK for ios. The FBSession is active and open and the access_token appears to be correct... Here's some code:
-(void)inviteUser:(NSString *)whoever {
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
// No permissions found in session, so ask for it
[FBSession.activeSession reauthorizeWithPublishPermissions:[NSArray arrayWithObject:#"publish_actions"] defaultAudience:FBSessionDefaultAudienceFriends completionHandler:^(FBSession *session, NSError *error) {
if (!error){
[self sendInvite:whoever];
}
}
}];
}
-(void) sendInvite:(NSString *)whoever {
NSMutableDictionary *params =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
#"A name of something", #"name",
nil];
[FBRequestConnection
startWithGraphPath:[NSString stringWithFormat:#"%#/feed", whoever]
parameters:params
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
} else {
alertText = #"Posted successfully.";
}
// Show the result in an alert
[[[UIAlertView alloc] initWithTitle:#"Result"
message:alertText
delegate:self
cancelButtonTitle:#"OK!"
otherButtonTitles:nil]
show];
}];
I'm still new at this, and am probably missing something basic. But I'm just not seeing it.
Fixed it. I think there were two problems:
Not having the session properly communicated inside the app (i.e. I had the FBSession open in a loginController, but not in the sendInvite controller <- not the exact names, obviously). As a result, the access_token actually wasn't active. I should have followed the FB docs and put the FBSession methods in the appdelegate.
I was using "publish_action" permissions when I believe I should have been using "publish_stream."
Works smoothly with these two changes. I do have a follow-up question, though: how to post on someone else's wall using the new SDK's native share dialog? I'll probably ask this as a separate question.