2014-06-11 17 views
8

Ho onestamente trascorso ore su questo tentativo di farlo funzionare. Purtroppo Facebook & App Link's documentation non è abbastanza chiaro. Anche lo App Links video from F8.Utilizzo dell'API di hosting collegamenti di app per il collegamento condiviso su Facebook dall'app iOS

App Requisiti:

  1. link per FB come una storia Open Graph, che gli utenti possono fare clic su per portarli direttamente nella mia app e fare compiti specifici (la mia applicazione ha bisogno di ricevere i parametri specifici da il collegamento)
  2. Condividere il collegamento a FB senza accesso FB (ovvero tramite la finestra di dialogo Condividi e passare all'app FB iOS nativa anziché utilizzare le chiamate API).

Progress finora:

Sto utilizzando il seguente codice per creare il ospitato App Link (come ho solo contenuti mobili) come da FB developer's website under Publishing iOS SDK.

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: 
          @"{My app name}", @"name", 
          {custom URL}, @"al:iphone:url", 
          @"{app store ID}", @"al:iphone:app_store_id", 
          @"{My app name}", @"al:iphone:app_name", 
          @"{\"should_fallback\": false}", @"web", 
          fbAccessToken, @"access_token", 
          nil 
          ]; 

/* make the API call */ 
[FBRequestConnection startWithGraphPath:@"/{FB app id}/app_link_hosts" 
          parameters:params 
          HTTPMethod:@"POST" 
         completionHandler:^(
               FBRequestConnection *connection, 
               id result, 
               NSError *error 
              ) { 
           /* handle the result */ 
           NSLog(@"Result = %@",result); 
           if(error) NSLog(@"error = %@",error); 
          }]; 

Poi ho postare la storia di OG su FB (questo è un messaggio che va bene ma senza un URL corretto)

// Create OG object 
id<FBGraphObject> object = 
[FBGraphObject openGraphObjectForPostWithType:@"{app name}:{FB object_name}" 
             title:@"Test Link" 
             image:@"https://cdn3.iconfinder.com/data/icons/picons-social/57/56-apple-512.png" // hosted wallpaper with unique id for background 
              url:nil // Assuming I need to put the url to the app link host object here?? 

            description:@"Click to on this test link!"]; 

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

// Link the object to the action 
[action setObject:object forKey:@"{FB object name}"]; 

// Check if the Facebook app is installed and we can present the share dialog 
FBOpenGraphActionParams *params = [[FBOpenGraphActionParams alloc] init]; 
params.action = action; 
params.actionType = @"{app name}:{FB action name}"; 

// 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:@"{app name}:{FB action name}" 
           previewPropertyName:@"{FB object name}" 
              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(@"Error publishing story: %@", error.description); 
               } else { 
                // Success 
                NSLog(@"result %@", results); 
               } 
              }]; 
} 

Per gestire l'URL in arrivo quando un utente fa clic sul link nella storia FB OG Ho aggiunto il seguente codice per AppDelegate.m come da documentazione FB - vedere Handling incoming links

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

    BOOL urlWasHandled = 
    [FBAppCall handleOpenURL:url 
      sourceApplication:sourceApplication 
      fallbackHandler: 
    ^(FBAppCall *call) { 
     // Parse the incoming URL to look for a target_url parameter 
     NSString *query = [url query]; 
     NSDictionary *params = [self parseURLParams:query]; 
     // Check if target URL exists 
     NSString *appLinkDataString = [params valueForKey:@"al_applink_data"]; 
     if (appLinkDataString) { 
      NSError *error = nil; 
      NSDictionary *applinkData = 
      [NSJSONSerialization JSONObjectWithData:[appLinkDataString dataUsingEncoding:NSUTF8StringEncoding] 
              options:0 
               error:&error]; 
      if (!error && 
       [applinkData isKindOfClass:[NSDictionary class]] && 
       applinkData[@"target_url"]) { 
       NSString *targetURLString = applinkData[@"target_url"]; 
       // Show the incoming link in an alert 
       // Your code to direct the user to the 
       // appropriate flow within your app goes here 
       [[[UIAlertView alloc] initWithTitle:@"Received link:" 
              message:targetURLString 
              delegate:nil 
            cancelButtonTitle:@"OK" 
            otherButtonTitles:nil] show]; 
      } 
     } 
    }]; 
    return urlWasHandled; 
} 

// 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 objectAtIndex:1] 
         stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
     [params setObject:val forKey:[kv objectAtIndex:0]]; 
    } 
    return params; 
} 

Qualcuno ha stato in grado di ottenere questo lavoro ? Non sono ancora chiaro su come funziona il collegamento app ospitato e dove metterlo (presumo dovrebbe andare nel parametro 'url' quando si chiama il metodo openGraphObjectForPostWithType FBGraphObject.

Non voglio davvero creare un sito Web per archiviare tutti gli URL e aggiungere i meta tag App Link (dovrei fare tutto questo tramite l'app dato che ogni App Link sarà dinamico e unico per ogni utente da cui viene generato nell'app). !

Please help

+1

si può includere i risultati delle richieste fatte da una delle frammenti di codice di cui sopra? Un paio di osservazioni che ho: 1.) richiediamo che le chiamate dell'host del link dell'app abbiano un token di accesso all'app (piuttosto che un utente), quindi in genere tali richieste non dovrebbero essere fatte su un client mobile. 2.) Per gli oggetti OG, dovresti usare l'URL fb.me che ti diamo una volta creato l'host link dell'app (vedi questo documento su come ottenere l'URL fb.me - https://developers.facebook.com/docs/applinks/hosting-api) –

+0

@MingLi Grazie per la direzione! Ora ho il token di accesso dell'app che funziona. Farò qualche test per vedere se riesco a ottenere l'URL personalizzato che passa informazioni alla mia app correttamente. C'è un limite al numero di host di link app che l'app può avere e per quanto tempo sono attivi? – Tim

+0

@MingLi La mia app pubblica ora OG con il link App in hosting. Quando faccio clic sul collegamento in FB iOS, passa alla mia app, ma NSString * query = [url query] (in AppDelegate) restituisce null nonostante venga restituito un URL di massa? Questo è basato sul codice dalla pagina degli sviluppatori FB. Qualche idea su cosa potrebbe essere sbagliato? – Tim

risposta

1

Con l'aiuto di Mingli da FB sono riuscito a farlo funzionare con il seguente codice:?

- (void)shareToOpenGraphCountdownInvite 
{ 
    NSURL *url = [NSURL URLWithString:@"https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id={insert your FB app ID here}&client_secret={insert client secret here}"]; 
    NSString *fullToken = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil]; 
    NSArray *components = [fullToken componentsSeparatedByString:@"="]; 
    FBAppAccessToken = [components objectAtIndex:1]; 

    NSDictionary *paramsForAppLinksHost = [NSDictionary dictionaryWithObjectsAndKeys: 
              FBAppAccessToken, @"access_token", 
              @"{your app name}", @"name", 
              @"{your app's custom url}", @"al:ios:url", 
              @"{app store ID}", @"al:ios:app_store_id", 
              @"{your app name}", @"al:ios:app_name", 
              @"{\"should_fallback\": false}", @"web", 
              nil 
              ]; 

    [FBRequestConnection startWithGraphPath:@"/{FB app ID}/app_link_hosts" 
           parameters:paramsForAppLinksHost 
           HTTPMethod:@"POST" 
          completionHandler:^(
               FBRequestConnection *connection, 
               id result, 
               NSError *error 
              ) { 
           AppLinksHostURL_ID = [result objectForKey:@"id"]; // store this ID in an NSString 
           [self postOGStoryWithCustomURL]; 
           if(error) NSLog(@"error = %@", error.description); 

          }]; 
} 

- (void)postOGStoryWithCustomURL 
{ 
    NSString *urlString = [NSString stringWithFormat:@"https://fb.me/%@/%@", AppLinksHostURL_ID, customURL]; 

    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[self pathForS3ObjectWithFilename:previewImageFilename]]]]; 

    // Create OG object 
    id<FBGraphObject> object = 
    [FBGraphObject openGraphObjectForPostWithType:@"timeflyz:countdown_invite" 
              title:eventBeingShared.eventName 
              image:image 
               url:urlString // fb.me app links hosted url here 
             description:@"{insert description here}"]; 

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

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

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

    // 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:@"timeflyz:create" 
            previewPropertyName:@"countdown_invite" 
               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(@"Error publishing story: %@", error.description); 
                } else { 
                 //               NSLog(@"result %@", results); 
                 if([[results objectForKey:@"completionGesture"] isEqualToString:@"post"]) { 
                  NSLog(@"Posted successfully!"); 
                  [[NSNotificationCenter defaultCenter] postNotificationName:@"showShareSuccessfullMessage" object:self userInfo:nil]; 
                 } else 
                  NSLog(@"Something else happened - user didn't post"); 
                } 
               }]; 


    } 

nota che "CustomURL" è un NSString che segue il modello" variabile1 = risultato1 & variabile2 = result2 ... "

+0

Non si dovrebbe utilizzare/memorizzare l'app FB segreta sul lato client. È necessario creare URL di collegamenti di app sul lato server e quindi eseguire una query per gli URL AppLink dal lato client. – Mat

+0

Questo è il requisito anche per me ... condividere la storia del grafico aperto senza effettuare il login ... tuttavia, anche con il tuo approccio, sto recuperando l'URL che non ha parametri personalizzati. L'URL ricevuto è simile a fb : // bridge/ogshare? Version = 20140410 & cipher = . Qualche idea? Devo registrarmi ovunque tranne che per avere la mia app FB, giusto? –

+0

Per non parlare del dialogo di condivisione funziona per me, ma l'unico problema è che voglio target_URL di nuovo per l'elaborazione personalizzata che manca qui. Questo è il problema per me. –

1

Questo sta funzionando per Graph v2.5 e SDK 4.8. Sicuramente non facile e non documentato. Ma grazie Tim per l'ispirazione. Sto usando un oggetto grafico personalizzato, non so come funzioni con quelli predefiniti. Sto anche usando l'host di collegamenti di app poiché non ho un'app web. Ho ottenuto il {app_access_token} da Graph API Explorer, seleziona la tua app quindi ottieni token di accesso all'app

Per prima cosa ho creato storie di grafici, azioni e tipi di oggetto sullo sviluppatore di Facebook (la tua app di Facebook). Assicurati di avere uno schema di query dell'app per la tua app in info.plist LSApplicationQueriesSchemes dovrebbe contenere uno schema che punta alla tua app Mi riferirò ad esso come {app_scheme}.

Quindi nella mia app per iOS creo un nuovo collegamento per ogni condivisione.

- (void)createAppLinkHost:(void(^)(NSString* appLinkURL))success error:(void(^)(NSError* error))failure{ 

NSString *url = [NSString stringWithFormat:@"{app_scheme}://%li",self.object.identifier]; 
NSString *appAccessToken = {app_access_token}; 
NSString *iosLink = [NSString stringWithFormat:@"[{\"url\":\"%@\",\"app_name\":\"%@\",\"app_store_id\":%i},]",url,@"{app_name}",{app_store_id_int}]; 
NSDictionary *appLinkHostParams = @{@"access_token":appAccessToken, 
            @"name":@"{link name}", 
            @"web":@"{\"should_fallback\": false}", 
            @"ios":iosLink 
            }; 

FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]initWithGraphPath:@"/{fb_appId}/app_link_hosts" 
                   parameters:appLinkHostParams 
                  tokenString:appAccessToken 
                   version:@"v2.5" 
                   HTTPMethod:@"POST"]; 
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) { 
    if (!error) { 
     NSString *appLinkHostId = [result objectForKey:@"id"]; 
     NSString *urlString = [NSString stringWithFormat:@"https://fb.me/%@", appLinkHostId]; 
     success(urlString); 
    } 
    else{ 
     NSLog(@"--ERROR-- [FACEBOOK APP LINK HOST] %@",error); 
     failure(error); 
    } 
}]; 

}

Se l'errore, controllare. Gli errori dall'host di app link hanno più senso del resto dell'SDK di Facebook. Graph API Explorer è utile per sapere quali dati inviare.

Una volta ottenuto un successo, prendi AppLinkHost e condividilo.

if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"fbauth2://"]]){ 
[self createAppLinkHost:^(NSString *appLinkURL) { 
    SURL *imageURL = [NSURL URLWithString:self.activity.imageURL];; 
    FBSDKSharePhoto *photo = [FBSDKSharePhoto photoWithImageURL:imageURL userGenerated:NO]; 
    //Custom objects needs to be set from facebook first. 
    //Set object properties 
    NSDictionary *properties = @{ 
           @"og:type": @"{namespace}:{graph_object}", 
           @"og:title": @"title", 
           @"og:description": @"body", 
           @"og:image": @[photo], 
           @"og:url":appLinkURL, 
           @"fb:app_id":@"{fb_appId}", 
           @"{namespace}:{custom_property}":@(self.object.identifier), //optional 
           };    
    //Create GraphObject 
    FBSDKShareOpenGraphObject *object = [FBSDKShareOpenGraphObject objectWithProperties:properties]; 

    //Create Action 
    FBSDKShareOpenGraphAction *action = [FBSDKShareOpenGraphAction actionWithType:@"{namespace}:{graph_action}" object:object key:@"{namespace}:{graph_object}"]; 

    FBSDKShareOpenGraphContent *openGraphcontent = [[FBSDKShareOpenGraphContent alloc] init]; 
    openGraphcontent.action = action; 
    openGraphcontent.previewPropertyName = @"{namespace}:{graph_object}"; 

    [FBSDKShareDialog showFromViewController:self withContent:openGraphcontent delegate:self]; 
} error:^(NSError *error) {}]; 

}

Problemi correlati