草庐IT

ios - 上传 Facebook 照片并自动注销用户(Kiosk 应用程序)

coder 2024-01-25 原文

我有一个专为在自助服务终端环境中使用而设计的 iPad 应用程序。

用户流应该是

  • 拍照
  • 从 iPad 相册 View 中选择照片
  • 分享到 Facebook 和/或 Twitter
  • 图片发布后自动注销用户

我的 Twitter 自动注销功能正常,我的问题出在 Facebook 部分。

我已经实现了用于内部测试的 Graph API,并且希望能够以这种方式发布完整的故事,但我认为一旦授权和发布是无法从 Facebook 应用程序注销的完成。

作为后备方案,我可以使用动态消息对话框并从那里自动注销,但据我所知,无法从那里上传本 map 片以分享到 Facebook。

我的Facebook分享代码如下:

- (IBAction)facebookShare:(id)sender {

/// Package the image inside a dictionary
NSArray* image = @[@{@"url": self.mergeImages, @"user_generated": @"true"}];

// Create an object
id<FBGraphObject> object =
[FBGraphObject openGraphObjectForPostWithType:@"me/feed:photo"
                                        title:@"a photo"
                                        image:self.mergeImages
                                          url:nil
                                  description:nil];

// Create an action
id<FBOpenGraphAction> action = (id<FBOpenGraphAction>)[FBGraphObject graphObject];

// Set image on the action
[action setObject:image forKey:@"image"];

// Link the object to the action
[action setObject:object forKey:@"photo"];

// Hardcode the location based on Facebook Place ID
id<FBGraphPlace> place = (id<FBGraphPlace>)[FBGraphObject graphObject];
[place setId:@"279163865580772"]; // Singley + Mackie
[action setPlace:place];

// Check if the Facebook app is installed and we can present the share dialog
FBOpenGraphActionShareDialogParams *params = [[FBOpenGraphActionShareDialogParams alloc] init];
params.action = action;
params.actionType = @"me/feed:share";

// If the Facebook app is installed and we can present the share dialog
if([FBDialogs canPresentShareDialogWithOpenGraphActionParams:params]) {
    // Show the share dialog
    [FBDialogs presentShareDialogWithOpenGraphAction:action
                                          actionType:@"photo_overlay:share"
                                 previewPropertyName:@"photo"
                                             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 publishing story: %@", error.description]);
                                                 } else {
                                                     // Success
                                                     NSLog(@"result %@", results);
                                                 }
                                            }];

    // If the Facebook app is NOT installed and we can't present the share dialog
} else {
    // Put together the Feed dialog parameters
    NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                   @"name",
                                   @"caption",
                                   @"description",
                                   @"link",
                                   @"picture",
                                   nil];
    // Show the feed dialog
    [FBWebDialogs presentFeedDialogModallyWithSession:nil
                                           parameters:params
                                              handler:^(FBWebDialogResult result, NSURL *resultURL, 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 publishing story: %@", error.description]);
                                                  } else {
                                                      if (result == FBWebDialogResultDialogNotCompleted) {
                                                          // User cancelled.
                                                          NSLog(@"User cancelled.");
                                                      } else {
                                                          // Handle the publish feed callback
                                                          NSDictionary *urlParams = [self parseURLParams:[resultURL query]];

                                                          if (![urlParams valueForKey:@"post_id"]) {
                                                              // User cancelled.
                                                              NSLog(@"User cancelled.");

                                                          } else {
                                                              // User clicked the Share button
                                                              NSString *result = [NSString stringWithFormat: @"Posted story, id: %@", [urlParams valueForKey:@"post_id"]];
                                                              NSLog(@"result %@", result);
                                                            }
                                                      }
                                                  }

                                                  // Auto log the user out
                                                  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
                                                  NSLog(@"defaults fbDidLogout  ........%@",defaults);
                                                  if ([defaults objectForKey:@"FBAccessTokenKey"])
                                                  {
                                                      [defaults removeObjectForKey:@"FBAccessTokenKey"];
                                                      [defaults removeObjectForKey:@"FBExpirationDateKey"];
                                                      [defaults synchronize];
                                                  }

                                                  NSHTTPCookie *cookie;
                                                  NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
                                                  for (cookie in [storage cookies])
                                                  {
                                                      NSString* domainName = [cookie domain];
                                                      NSRange domainRange = [domainName rangeOfString:@"facebook"];
                                                      if(domainRange.length > 0)
                                                      {
                                                          [storage deleteCookie:cookie];
                                                      }
                                                  }

                                                  [FBSession.activeSession closeAndClearTokenInformation];

                                              }];

}
}
// A function for parsing URL parameters.
- (NSDictionary*)parseURLParams:(NSString *)query {
    NSArray *pairs = [query componentsSeparatedByString:@"&"];
    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
    for (NSString *pair in pairs) {
        NSArray *kv = [pair componentsSeparatedByString:@"="];
        NSString *val =
        [kv[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        params[kv[0]] = val;
    }
    return params;
}

我广泛搜索了 Stack Overflow 以寻找答案,但没有找到任何解决方案。

最佳答案

我终于明白了!在此发布答案,希望对处于相同情况的其他人有所帮助。

首先,将以下内容添加到您的 AppDelegate.m 中:

-(BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication fallbackHandler:^(FBAppCall *call) {
    // Facebook SDK * App Linking *
    // For simplicity, this sample will ignore the link if the session is already
    // open but a more advanced app could support features like user switching.
    if (call.accessTokenData) {
        if ([FBSession activeSession].isOpen) {
            NSLog(@"INFO: Ignoring app link because current session is open.");
        }
        else {
            [self handleAppLink:call.accessTokenData];
        }
    }
}];
}

// Helper method to wrap logic for handling app links.
- (void)handleAppLink:(FBAccessTokenData *)appLinkToken {
    // Initialize a new blank session instance...
    FBSession *appLinkSession = [[FBSession alloc] initWithAppID:nil
                                                     permissions:nil
                                                 defaultAudience:FBSessionDefaultAudienceNone
                                                 urlSchemeSuffix:nil
                                              tokenCacheStrategy:[FBSessionTokenCachingStrategy nullCacheInstance] ];
    [FBSession setActiveSession:appLinkSession];
    // ... and open it from the App Link's Token.
    [appLinkSession openFromAccessTokenData:appLinkToken
                          completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
                              // Forward any errors to the FBLoginView delegate.
                              if (error) {
                                  //[self.loginViewController loginView:nil handleError:error];
                              }
                          }];
}

无论您在应用中的哪个位置调用发布操作,请将此行添加到您的头文件中:

@property (strong, nonatomic) FBRequestConnection *requestConnection;

以及您的实现文件中的以下内容:

@synthesize requestConnection;

- (IBAction)facebookShare:(id)sender {

NSArray *permissions = [[NSArray alloc] initWithObjects:
                        @"publish_actions", @"publish_checkins", nil];

UIImage *img = self.facebookImage;
[FBSession openActiveSessionWithPublishPermissions:permissions
                                   defaultAudience:FBSessionDefaultAudienceEveryone allowLoginUI:YES
                                 completionHandler:^(FBSession *session,FBSessionState s, NSError *error) {
                                     [FBSession setActiveSession:session];
                                     if (!error) {
                                         // Now have the permission
                                         [self processPostingImage:img WithMessage:@"Enter_your_message_here"];
                                     } else {
                                         // Facebook SDK * error handling *
                                         // if the operation is not user cancelled
                                         if (error.fberrorCategory != FBErrorCategoryUserCancelled) {
                                             [self presentAlertForError:error];
                                         }
                                     }
                                 }];

}

-(void)logout {
    [FBSession.activeSession closeAndClearTokenInformation];
    [FBSession.activeSession close];
    [FBSession setActiveSession:nil];
}

- (void)processPostingImage:(UIImage *) img WithMessage:(NSString *)message {
    FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
    FBRequestHandler handler =
    ^(FBRequestConnection *connection, id result, NSError *error) {
        // output the results of the request
        [self requestCompleted:connection forFbID:@"me" result:result error:error];
    };
    FBRequest *request=[[FBRequest alloc] initWithSession:FBSession.activeSession graphPath:@"me/photos" parameters:[NSDictionary dictionaryWithObjectsAndKeys:UIImageJPEGRepresentation(img, 0.7),@"source",message,@"message",@"{'value':'EVERYONE'}",@"privacy", nil] HTTPMethod:@"POST"];
    [newConnection addRequest:request completionHandler:handler];
    [self.requestConnection cancel];
    self.requestConnection = newConnection;
    [newConnection start];
}

// FBSample logic
// Report any results.  Invoked once for each request we make.
- (void)requestCompleted:(FBRequestConnection *)connection
                 forFbID:fbID
                  result:(id)result
                   error:(NSError *)error
{

    // not the completion we were looking for...
    if (self.requestConnection &&
        connection != self.requestConnection)
    {
        return;
    }

    // clean this up, for posterity
    self.requestConnection = nil;

    if (error)
    {

    }
    else
    {
        [self logout];
    };
}

- (void) presentAlertForError:(NSError *)error {
    // Facebook SDK * error handling *
    // Error handling is an important part of providing a good user experience.
    // When fberrorShouldNotifyUser is YES, a fberrorUserMessage can be
    // presented as a user-ready message
    if (error.fberrorShouldNotifyUser) {
        // The SDK has a message for the user, surface it.
        [[[UIAlertView alloc] initWithTitle:@"Something Went Wrong"
                                    message:error.fberrorUserMessage
                                   delegate:nil
                          cancelButtonTitle:@"OK"
                          otherButtonTitles:nil] show];
    } else {

    }
}

注意: 要使其与自动注销一起使用,您还必须在设备上禁用 Safari。这可以通过转到“设置”>“通用”>“限制”>“允许 Safari”>“关闭”来完成。关闭后,Facebook IBAction 将在应用程序本身内弹出一个 UIWebView。点击时,当前用户可以输入他们的 Facebook 凭据,然后应用程序将发布图像,并注销用户,以便下一个用户可以使用该应用程序而无需访问前一个用户的 Facebook 详细信息。

关于ios - 上传 Facebook 照片并自动注销用户(Kiosk 应用程序),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22331275/

有关ios - 上传 Facebook 照片并自动注销用户(Kiosk 应用程序)的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  3. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  4. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  5. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  6. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  7. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  8. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  9. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  10. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

随机推荐