无法让新的AppLink在iOS或Android上运行

 樱花恋雪的玫瑰_484 发布于 2023-01-15 21:34

我遇到了与AppLinks相同的问题,并决定完全放弃它们,只使用facebook的应用程序链接主机:https://developers.facebook.com/docs/applinks/hosting-api

我的应用程序只是移动设备,我误解了AppLinks最初的工作方式.我想我可以把al_ios_*meta标签放在一个通用的网页上,但这是错误的.我的网站上的每个内容都需要有一个单独的页面,这些页面中的每一个都需要有自己的AppLinks元标记,才能将特定内容的URL发送回我的应用程序.

当我做错了,当我在Facebook上点击我的OpenGraph故事时,它会在网络浏览器中打开我的网站,底部工具栏中有一个动作图标,我可以点击并选择打开我的应用程序.或者我必须在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 = ;
$url = "https://graph.facebook.com/v2.1/app/app_link_hosts";
$ch = curl_init($url);

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

$formQuery = http_build_query(array("access_token" => "|",
                                    "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" => "|",
                                          "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作为url参数放在[FBGraphObject openGraphObjectForPostWithType:下面.现在,当您在Facebook应用程序中点击您的故事时,它将直接进入您的应用程序.没有网络废话.

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

// Create an object
id object;

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

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

etc...
</pre></p>
        <p class="fa-ul">
          
        <p>
      <hr/>
    <p>
  <p>
  
  <p id="answer-2141149811" class="row bg-light rounded my-2 mx-0">
    <p class="col shadow">
      <p>
        <i class="fa fa-git-square text-info"></i>Alex Austin..</abbr>
        <i class="fa fa-html5 text-primary"></i> 5</abbr>
      </p>
      <p><p>当我在我的应用程序上工作时,Sweep,在应用程序中花费了一定的时间之后我放了一个付费/共享墙.我遇到了同样的问题,即尽管有这样的承诺,但AppLinks实际上却真正吸引了Facebook.基于这个问题,我构建了一个名为branch.io的服务,为我提供链接,并自动为Android/iOS插入正确的AppLinks元标记.链接实际上按预期工作,就像疯了一样.它使用客户端JS和AppLinks的组合,使它们在每个webview和本机浏览器中正确地重定向</p>

<p>以下是在iOS上创建共享链接的高级指南:</p>

<ol>
<p><p>要开始使用,您只需在dashboard.branch.io的仪表板上的任一商店中配置应用的位置即可.完成所有设置后,您将获得Branch应用程序密钥.</p></p>
<p><p>pod"Branch"或者你可以在这里克隆开源代码:https:
 //github.com/BranchMetrics/Branch-iOS-SDK</p></p>
<p><p>使用键"branch_key"将分支键添加到plist文件中作为String</p></p>
<p><p>使用适当的方法将以下代码添加到AppDelegate</p></p>
</ol>

<p>在didFinishLaunchingWithOptions中:</p>

<pre class="brush:bash;">- (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
        }
    }];
}
</pre>

<p>在用于处理URI调用的openUrl中:</p>

<pre class="brush:bash;">- (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;
}
</pre>

<ol start="5">
<p>最后,要创建托管链接,它非常简单.您只需要调用getShortUrl来动态创建一个.您可以在链接中放置尽可能多的键和值(在initSession回调中检索)</p>
</ol>

<p>您可以将此代码段放在要创建链接的任何位置:</p>

<pre class="brush:bash;">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
}];
</pre>

<p>Android在方法调用和功能方面非常相似,可以在网站上找到.</p>        <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8923551941185667"
                crossorigin="anonymous"></script>
        <ins class="adsbygoogle"
             style="display:block; text-align:center;"
             data-ad-layout="in-article"
             data-ad-format="fluid"
             data-ad-client="ca-pub-8923551941185667"
             data-ad-slot="9961241226"></ins>
        <script>
            (adsbygoogle = window.adsbygoogle || []).push({});
        </script>
    </div>

    
    <div class="q_answer">
        <div class="q_answer_top">撰写答案</div>
        <div class="q_answer_box">
            <form action="https://ask.php1.cn/?s=index/questionAnswer&id=550377" method="post">
                <div class="q_answer_txt">
                    <textarea id="editor1" name="editor1" >回答问题...</textarea>
                </div>
                <script>
                    var config = {
                        extraPlugins: 'codesnippet',
                        codeSnippet_theme: 'monokai_sublime',
                        height: 200
                    };

                    CKEDITOR.replace( 'editor1', config );
                </script>
                <div class="q_answer_bt">
                    <input type="submit" value="提交回答">
                </div>
            </form>
        </div>
    </div>


</div>

    <div class="ask_main_right">
    <div class="ask_add_tips">
        <div class="ask_add_title">今天,你开发时遇到什么问题呢?</div>
        <a href="https://ask.php1.cn/?s=index/add"><div class="ask_add_bt">立即提问</div></a>
    </div>

    <div class="ask_tags">
        <div class="ask_tags_title">热门标签</div>
        <div class="ask_tags_list">
            <ul>
                                <div style="clear:both"></div>
            </ul>
        </div>
    </div>


    
</div>    <div style="clear: both"></div>
</div>

<div style="clear: both"></div>
<div class="bottom">
    PHP1.CN | 中国最专业的PHP中文社区 | <a href="https://www.php1.cn/pngimg/" target="_blank"  title="PNG素材下载">PNG素材下载</a> |  <a href="https://devbox.cn/" target="_blank"  title="DevBox开发工具箱">DevBox开发工具箱</a> | <a href="https://www.json1.cn/" target="_blank"  title="json解析格式化">json解析格式化</a> |<a href="https://news.php1.cn/" title="PHP资讯">PHP资讯</a> | <a href="https://school.php1.cn/" title="PHP教程">PHP教程</a> | <a href="https://database.php1.cn/" title="数据库技术">数据库技术</a> | <a href="https://server.php1.cn/" title="服务器技术">服务器技术</a> | <a href="https://web.php1.cn/" title="前端技术">前端开发技术</a> | <a href="https://www.php1.cn/phpframework.html" title="PHP框架">PHP框架</a> | <a href="https://tools.php1.cn/">开发工具</a>  | <a href="https://www.json1.cn/tools/" title="在线工具">在线工具</a><BR />
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved   <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010802041100" style="color:#444;"><img src="https://img.json1.cn/3cd4a/21981/c5a/4df0b47476da9030.png"/>京公网安备 11010802041100号</a>  |  <a href="https://beian.miit.gov.cn/" target="_blank">京ICP备19059560号-4</a> | PHP1.CN 第一PHP社区  版权所有 <BR />
          
</div>
<script>
    (function(){
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        }
        else {
            bp.src = 'https://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

<script type="text/javascript" src="//js.users.51.la/21559097.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushBash.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushCpp.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushCSharp.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushCss.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushDelphi.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushDiff.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushGroovy.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushJava.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushJScript.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushPhp.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushPlain.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushPython.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushRuby.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushScala.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushSql.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushVb.js"></script>
<script type="text/javascript" src="/style/SyntaxHighlighter/scripts/shBrushXml.js"></script>
<link type="text/css" rel="stylesheet" href="/style/SyntaxHighlighter/styles/shCore.css"/>
<link type="text/css" rel="stylesheet" href="/style/SyntaxHighlighter/styles/shThemeLiuQing.css"/>
<style>
    .syntaxhighlighter{
        width: 600px;
        padding-top:40px;padding-bottom:20px;
        border: 1px solid #333;
        background: url("/style/SyntaxHighlighter/top_bg.svg");
        background-size: 43px;
        background-repeat: no-repeat;
        margin-bottom: -7px;
        border-radius: 15px;
        background-position: 16px 12px;

    }
    .gutter{
        display: none;
    }
</style>
<script type="text/javascript">
    SyntaxHighlighter.all();
</script>

</body>
</html>