无法在iOS或Android上使用新的AppLinks

32

最新更新请参见更新#5

我正在尝试为我的iOS和Android应用程序同时实现AppLinks:http://applinks.org

我已经完成了以下步骤:

  1. 设置应用程序的自定义URL scheme:inacho://
  2. 在我的App Delegate中进行设置:-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
  3. 在我的网站http://www.nachorater.com上添加meta标签:

<meta property="al:ios:app_store_id" content="581815579"/>
<meta property="al:ios:app_name" content="iNacho" />
<meta property="al:ios:url" content="inacho://default" />

我确认了URL scheme的功能,通过在Notes中键入链接(例如inacho://default),并单击它创建的链接。哇啦!它打开了我的应用程序。

但是当我尝试从Facebook或Quip点击www.nachorater.com的链接时,两个应用程序都似乎没有自动注意到网站已经设置了这些应用链接,并且只是在他们的浏览器中加载网站,而不是尝试打开我的应用程序。

有人成功过吗?

更新:

我遇到了一些元标签未被放置在模板的< head >部分的问题,我已经解决了。

现在iOS Facebook应用程序中来自链接:http://www.nachorater.com会添加一个不错的弹出窗口,让您像这样在iNacho应用程序中打开该URL:

screenshot

但是我的动态评论链接似乎没有起作用,然而Ming指出的Debug应用程序显示它们的元标签看起来是正确的。

例如:http://www.nachorater.com/getReview?reviewID=6396169718595584

使用https://developers.facebook.com/tools/debug/og/object?q=http%3A%2F%2Fwww.nachorater.com%2FgetReview%3FreviewID%3D6396169718595584进行调试时的元标签:

meta tags

更新#2:

我在我的iNacho Facebook时间轴上发布了一个新的nacho评论链接,然后尝试从Facebook Mobile应用程序上点击它。

它开始加载页面并弹出方便的指示器,让你可以打开iNacho应用程序,但是一旦页面加载完成,指示器就消失了(还没来得及单击它)。

更新#3:

现在从Facebook应用程序中,我可以触发一个inacho URL用于我的评论,但是只有在它消失之前点击小弹出窗口才行。如果我让页面完全在Facebook内置的Web视图中加载,小弹出窗口仍会消失。

这是AppLinks的问题吗?还是Facebook应用程序的问题?或者是设计上的原因?

更新#4:

我可能知道问题出在哪里。评论页面反过来为nacho评论加载一个动态图像。因此,通过加载页面,它具有指向加载图像的动态URL的img src标记。它被误解为某种“重定向”操作了吗?

img标签的示例(已呈现):<img width="300" src="/getReviewImage?imageID=6125868501958656"></img>

注意:还会动态加载其他脚本/ajax(Facebook和Twitter小部件之类)。

这是AppLinks或Facebook Mobile应用程序中的错误吗?它不应该关心ajax和动态图像


4
你是否删除了“al:ios:url”属性?它已经不在那里了。你可以在FB开发者网站https://developers.facebook.com/tools/debug/上的调试器中测试你的URL。另外,你使用的是哪个版本的FB应用程序? - Ming Li
1
谢谢提供这个工具,它帮了我大忙。我相信我已经解决了我的多个和缺失的 meta 标签问题,但仍然无法看到来自 Facebook 应用的结果。 - valheru
1
你也可以尝试在Twitter上发布链接,然后从Twitter移动应用程序中打开它。这至少会告诉你问题是限于Facebook还是普遍存在的问题。 - Puneet Sharma
2
我认为问题出在嵌入的 Twitter 时间线上。它似乎会向 twitter.com/i/jot 提交表单,这被视为重定向。 - Ming Li
大家好...我对这个问题有一些看法 - 在花费了数天的时间来解决这个问题后 - 我至少可以理解IOS。1. 确保您的页面是https而不是http。我没有找到任何文件表明这是必须的,但它解决了我的问题。2. applinks在不太多的工具中起作用 - 在Facebook应用程序中它可以工作(Safari不行)。 - Boaz
显示剩余17条评论
3个回答

8
我遇到了与AppLinks相关的同样问题,所以我决定完全放弃它们,只使用Facebook的应用链接主机:https://developers.facebook.com/docs/applinks/hosting-api 我的应用程序只适用于移动设备,一开始我误解了AppLinks的工作原理。我以为我只需要在一个通用的网页上放置al_ios_*元标签就可以了,但这是错误的。对于我网站上的每一项内容都需要单独的页面,并且每个页面都需要有自己的AppLinks元标签,以将特定内容的URL发送回我的应用程序。
当我做错了时,在Facebook中点击我的OpenGraph故事时,它会在Web浏览器中打开我的网站,并且底部工具栏中会有一个操作图标,我可以点击该图标并选择打开我的应用程序,或者我需要精确地点击OpenGraph故事中我的应用程序名称。任何一种方式都可以快速切换到我的应用程序,但URL不会针对我想要导航到的内容进行指定。而且,这两个选项都很糟糕——我只想点击故事的任何位置并直接进入我的应用程序,这就是我们在这里的原因。
解决方案
我将使用OpenGraph故事和共享对话框作为示例。
首先,您需要在服务器上创建一个托管的应用链接,而不是在应用程序中创建。在创建OpenGraph故事或任何要共享的内容之前,请调用您的服务器以完成以下两个操作:
1. 调用API以创建新的Facebook应用链接,这将返回一个ID。 2. 使用该ID调用第二个API以获取指向托管应用链接的URL。
这必须在服务器上完成,因为这些API调用需要一个应用程序访问令牌,而不是用户访问令牌。此令牌具有应用程序级别权限,而不是用户级别权限。您不能也不应该在移动应用程序中存储您的Facebook应用程序密钥,因为某些人可以反编译您的应用程序并更改您的Facebook应用程序。没有好处。使用服务器,因为它可以安全地知道您的应用程序密钥。
我的服务器端是PHP,所以这是如何完成此操作的示例。与API打交道并不是一件特别愉快的事情,所以我想分享一下希望能帮助其他人格式化请求:
# create a new facebook app link using cURL
$metadata = <what to handle in AppDelegate application:openURL:sourceApplication:annotation>;
$url = "https://graph.facebook.com/v2.1/app/app_link_hosts";
$ch = curl_init($url);

# create form post data
$deepLinkURL = "<myApp>://" . $metadata;
$iosArray = json_encode(array(array("url"          => $deepLinkURL,
                                    "app_store_id" => <appStoreId (number)>,
                                    "app_name"     => "<myAppName>")
                              )
                       );
$webFallbackArray = json_encode(array("should_fallback" => false));

$formQuery = http_build_query(array("access_token" => "<appId>|<appSecret>",
                                    "name"         => $metadata,
                                    "ios"          => $iosArray,
                                    "web"          => $webFallbackArray)
                              );

# options
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $formQuery);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

# get response
$responseJson = curl_exec($ch);
curl_close($ch);

# decode response from facebook
$jsonResponse = json_decode($responseJson, true);
$appLinkId = "";

# get appLinkId
foreach ($jsonResponse as $key => $val) {

    # get status
    if($key == "id") {
        $appLinkId = $val;
    }
}

# if response is good, need to request canonical URL from appLinkId
$errorMessage = "";
$canonicalUrl = "";

if(!empty($appLinkId)) {

    # create another instance of cURL to get the appLink object from facebook using the ID generated by the previous post request
    $getAppLinkUrl = "https://graph.facebook.com/" . $appLinkId;
    $ch2 = curl_init();

    # cURL options
    $queryString = http_build_query(array("access_token" => "<appId>|<appSecret>",
                                          "fields"       => "canonical_url",
                                          "pretty"       => true)
                                    );
    curl_setopt($ch2, CURLOPT_URL, $getAppLinkUrl . "?" . $queryString);
    curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);

    # get response
    $urlResponseJson = curl_exec($ch2);
    curl_close($ch2);

    # decode response from facebook
    $urlJsonResponse = json_decode($urlResponseJson, true);

    # parse response to get canonical URL
    foreach ($urlJsonResponse as $key => $val) {
        # get canonical URL
        if($key == "canonical_url") {
            $canonicalUrl = $val;
        }
    }

    # check for result
    if(empty($canonicalUrl)) {
        $errorMessage = "Unable to retreive URL.";
    }

} else {
    $errorMessage = "Unable to publish appLink.";
}

# encode response back to your app
if(empty($errorMessage)) {
    $response = json_encode(array("result"        => "success",
                                  "canonical_url" => $canonicalUrl));
} else {
    $response = json_encode(array("result" => "failed",
                                  "errorMessage" => $errorMessage));
}

#send response back to your app

回到你的应用程序中,一旦确认获得了良好的响应,请将你收到的规范化URL作为[FBGraphObject openGraphObjectForPostWithType:下面的url参数。现在,当你在Facebook应用程序中点击你的故事时,它将直接转到你的应用程序,没有网页上的繁琐操作。

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

// Create an object
id<FBGraphObject> object;

// set shareDialog parameters
FBOpenGraphActionParams *params = [[FBOpenGraphActionParams alloc] init];
params.action = action;
params.actionType = @"<myApp>:<myAction>";
params.previewPropertyName = @"<key>";
object = [FBGraphObject openGraphObjectForPostWithType:@"<myApp>:<myObject>"
                                                 title:<title>
                                                 image:<urlToPic>
                                                   url:<fb.me/xyz canonical URL>
                                           description:<someDescription>];

[action setObject:object forKey:@"<key>"];

etc...

我知道这已经有些过时了,但这是一个关于使用移动主机API的流程的绝佳写作!感谢@jday!! - anon_dev1234
嘿@jday,应用程序访问令牌是什么?在我的应用程序设置->高级->安全性中,我只能看到客户端令牌。那是吗? - natario
嘿 @mvai,你的Facebook应用程序仪表板上方就有了。现在它被命名为 App Secret。你必须点击 show 才能看到它。 - jday
这太棒了,它帮助了我很多。 - ken

5
当我在开发我的应用程序Sweep时,我在一定时间后加入了付费/分享墙。我遇到了同样的问题,即使有承诺,AppLinks在实际链接Facebook时真的很糟糕。基于这个问题,我建立了一个名为branch.io的服务,为我托管链接,并自动插入正确的Android/iOS AppLinks元标记。链接实际上像预期的那样工作,这是非常疯狂的。它使用客户端JS与AppLinks的组合,在每个Webview和本地浏览器中使它们正确重定向。
以下是创建iOS分享链接的高级指南:
  1. 要开始使用,您只需要在仪表板上配置应用程序在商店中的位置,该仪表板位于dashboard.branch.io。一旦全部设置完成,您就可以获得Branch应用程序密钥。

  2. pod“Branch”,或者您可以在此处克隆开源存储库: https://github.com/BranchMetrics/Branch-iOS-SDK

  3. 将Branch密钥作为字符串添加到您的plist文件中,键名为'branch_key'

  4. 在适当的方法中,将以下代码添加到您的AppDelegate中

在didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // your other init code
    Branch *branch = [Branch getInstance];
    [branch initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {     // previously initUserSessionWithCallback:withLaunchOptions:
        if (!error) {
            // params are the deep linked params associated with the link that the user clicked before showing up
            // params will be empty if no data found

            // here is the data from the example below if a new user clicked on Joe's link and installed the app
            NSString *name = [params objectForKey:@"user"]; // returns Joe
            NSString *profileUrl = [params objectForKey:@"profile_pic"]; // returns https://s3-us-west-1.amazonaws.com/myapp/joes_pic.jpg
            NSString *description = [params objectForKey:@"description"]; // returns Joe likes long walks on the beach...

            // route to a profile page in the app for Joe
            // show a customer welcome
        }
    }];
}

在处理URI调用的openUrl中:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    // pass the url to the handle deep link call
    // if handleDeepLink returns YES, and you registered a callback in initSessionAndRegisterDeepLinkHandler, the callback will be called with the data associated with the deep link
    if (![[Branch getInstance] handleDeepLink:url]) {
        // do other deep link routing for the Facebook SDK, Pinterest SDK, etc
    }
    return YES;
}
  1. 最后,要创建托管链接非常简单。您只需要调用getShortUrl来动态创建一个链接。您可以在链接中放置尽可能多的键和值(以在initSession回调中检索)

您可以将此代码片段放在任何想要创建链接的位置:

NSMutableDictionary *params = [[NSMutableDictionary alloc] init];

[params setObject:@"Joe" forKey:@"user"];
[params setObject:@"url.to.picture/mypic.png" forKey:@"profile_pic"];
[params setObject:@"Joe likes long walks on the beach..." forKey:@"description"];

// Customize the display of the link
[params setObject:@"Joe's MyApp Referral" forKey:@"$og_title"];
[params setObject:@"url.to.picture/mypic.png" forKey:@"$og_image_url"];
[params setObject:@"Join Joe in MyApp - it's awesome" forKey:@"$og_description"];

// Customize the redirect performance
[params setObject:@"http://myapp.com/desktop_splash" forKey:@"$desktop_url"];

Branch *branch = [Branch getInstance];
[branch getShortURLWithParams:params andCallback:^(NSString *url, NSError *error) {
    // show the link to the user or share it immediately
}];

安卓的方法调用和功能非常相似,可以在该网站上找到。

3
抱歉,如果我的回答不完全符合您的期望,但是我想分享我们在网站和应用程序上所做的事情。例如,我知道我们必须添加更多标签,以使其与Twitter卡片兼容,并且以下是我们页面中拥有的元属性列表:
meta property="twitter:card" content=""
meta property="twitter:title" content=""
meta property="twitter:description" content=""
meta property="twitter:image:src" content=""
meta property="twitter:app:id:iphone" content=""
meta property="twitter:app:name:iphone" content="Marmiton"
meta property="twitter:app:url:iphone" content=""
meta property="twitter:app:id:googleplay" content=""
meta property="twitter:app:name:googleplay" content=""
meta property="twitter:app:url:googleplay" content=""

而且你还有以下方法:

meta property="al:iphone:app_store_id" content=""
meta property="al:iphone:app_name" content=""
meta property="al:iphone:url" content=""
meta property="al:android:package" content=""
meta property="al:android:app_name" content=""
meta property="al:android:url" content=""

我们还定义了Facebook Opengraph元数据,例如fb:app_id。我提到这一点是因为当您在应用程序中接收深度链接时,您还可以在applinks链接中看到Facebook应用程序ID。
根据我们的测试结果:
- 在iOS上,Facebook不会直接打开深度链接,而Android会给出应用选择。有时它会在屏幕底部显示蓝色弹窗,有时您只需在Facebook(Safari)Web视图中点击分享按钮时,在操作表中添加一个链接(仅在首次加载时)。此链接的呈现方式取决于内容在Facebook上的共享方式。 - 在iOS上,Twitter会在卡片中添加应用程序链接。
希望这些信息能对您有所帮助。

1
谢谢尝试。在我看来,这似乎是 Facebook 目前的一个错误(直到他们修复它)。 - valheru
有人知道在哪里可以找到一份逐步教程,以便在安卓上实现它吗?我似乎无法让它正常工作。 - Princewill Obinna Iwuorie
我相信你已经阅读了这个链接:http://applinks.org/documentation/#navigatingonandroid - cire.boroguies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接