【问题标题】:Android Browser Facebook Redirect Does Not Always Trigger Intent for URLAndroid 浏览器 Facebook 重定向并不总是触发 URL 的意图
【发布时间】:2012-08-20 11:26:36
【问题描述】:

我陷入了困境,迫切需要一些帮助来解决我遇到的一个严重问题。

我花了几个月的时间编写一个 HTML5 应用程序/网站以及一个本机 Android 应用程序,它只是 HTML5 网站的 WebView 包装器。该应用程序的核心功能之一是用户可以将应用程序特定的 URL 共享到 Facebook 和 Twitter 等,以便他们的朋友可以关注共享的 URL,这将在他们的浏览器中打开我的应用程序的 HTML5 版本,或者最重要的是,如果他们是在 Android 上,他们安装了我的原生 Android 应用程序,他们被提示在我的应用程序中打开。

这是一个相当长的复杂问题,因此为简化起见,我将在整个帖子中始终使用一些特定术语:

  • “MyApp 用户”是指安装了我的原生 Android 应用的 Android 设备用户
  • “非 MyApp 用户”是指未安装我的原生 Android 应用的 Android 设备用户
  • “股票浏览器用户”使用股票浏览器的股票 Android 用户
  • “非库存浏览器用户”是指使用非库存浏览器的 Android 用户(请注意,三星 Galaxy SII 库存“互联网”应用程序被视为非库存)
  • Android 上的“选择应用程序对话框”出现的操作系统对话框询问用户他们想用什么应用程序打开操作/意图/url/文档,以及他们是否希望默认始终使用此应用程序

我的 AndroidManifest.xml 包含以下内容...

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="http" android:host="myapp.com" android:pathPrefix="/" />
</intent-filter>

经过测试,这在任何正常情况下都能完美运行。例如,如果“MyApp 用户”跟随指向http://myapp.com/sharedpage 的直接链接,则会出现“选择应用程序对话框”。太好了,我确实正确配置了我的 AndroidManifest.xml。

但是,在关键的 Facebook 分享场景中,事情并不总是有效。它并不总是有效,因为 Facebook 的原生 Android 应用程序和 Facebook 的移动网站 (http://m.facebook.com) 都不会直接链接到共享 URL,而是通过 Facebook 重定向页面链接。例如,如果http://myapp.com/sharedpage 被分享,Facebook 最终会提供以下 URL:

http://m.facebook.com/l.php?u=http%3A%2F%2Fmyapp.com%2Fsharedpage&h=EAQGpLtuF&enc=AZMXYZg7XwQ39zlWkKSGnLw62lEbtbMeWFmRwRZINoOcg0UgZe3fUVPgqQzV1nuTipSVnquV3a3ovqu7HQFUf3bb3ZJ1gYG8dEOJXzPf6RJGflf9_x8w-6CCXu8G2VZqgfD7lx6EbLTSKLnF56_o5khHybycPUlhpdfLsk6M9muer4jMOmPK6_kfjTq2gvnYNNpStcF0ilJD6nacPqx_1xsdYkUMpKYWbJfSo7qqv1S5xT5KRaLPxl8zmAkYc0FhwyTdn-tUGwRBbbdM4QCd2Z75Tb_VeJG3LvbDwFAbp6G3kH3LOSxVtTd5MST4pUW8xmhNeTUVBVXV16OD27QcsSWOlEfL72fxn11PDE5s4WWsXMnwhDJLUAWOAna7lziBnWzjZdlQK_amI9nhcegaOLDLNFCp125rZS3jxFXf7gtF9g0BsmnPZ2Gjxkc6UgQXhEYldllq9nwpShGbnZDlSg0_&s=1

如果“MyApp 用户”关注这些 Facebook 链接之一,则可能会发生以下两种情况之一,具体取决于他们使用的浏览器...

MyApp 股票浏览器用户:

如果用户安装了原生 Android 并使用原生 Android 浏览器,那么一切正常,因为会发生以下事件...

  • FB l.php URL 的 Intent 触发
  • FB URL 在 ANDROID 股票浏览器中打开
  • FB l.php 被加载并启动重定向到http://myapp.com/sharedpage
  • http://myapp.com/sharedpage URL 的 Intent 触发
  • “选择应用程序对话框”提示用户在 MY NATIVE APP 或浏览器中打开

MyApp 非股票浏览器用户:

但是如果用户...

  1. 已安装并使用非现货 Android 浏览器,例如Dolphin HD/mini、Opera Mobile/Mini 等,或
  2. 具有制造商定制的 Android 版本(例如在三星 Galaxy SII 等上),因此具有定制的浏览器

...那么这是主要问题,因为发生了以下事件...

  • 为 FB l.php URL 触发 Intent
  • FB URL 在非股票浏览器中打开
  • FB l.php 被加载并启动重定向到http://myapp.com/sharedpage
  • 非库存浏览器未触发 Intent,未出现“选择应用程序对话框”,未提示用户在我的应用程序中打开 URL
  • http://myapp.com/sharedpage URL 已加载并呈现在非库存浏览器的选项卡中

客户端重定向

为了确认导致问题的重定向,我创建了一个非常简单的 HTML 页面,名为“clientSideRedirector.htm”

<html><body><script>
   window.location.href = "http://myapp.com/sharedpage";
</script></body></html>

如果 My-App/non-stock 浏览器用户打开 http://myapp.com/clientSideRedirector.htm,则不会出现“应用程序选择对话框”。失败。

如果 My-App/stock 浏览器用户打开 http://myapp.com/clientSideRedirector.htm 会出现“应用选择对话框”。

这似乎与我们在 Facebook 分享/重定向中看到的一致。

服务器端 (302) 重定向

我还想尝试服务器端重定向,所以我创建了一个 .NET dotNetRedirect.ashx 页面:

public class ShareRedirect : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
            context.Response.Redirect("http://myapp.com/sharedpage");
    }
    public bool IsReusable { get { return false; } }
} 

这对客户端重定向有一个非常有趣且不同的结果。
如果 My-App 用户打开http://myapp.com/dotNetRedirect.htm,则无论用户浏览器如何,“应用程序选择对话框”都会出现。 所以这种类型的重定向似乎有效!


尝试的解决方案 A

(双重重定向:Facebook l.php 重定向到服务器端重定向到应用 URL)

我认为这可以解决我的 Facebook 分享问题。如果我将http://myapp.com/dotNetRedirect.ashx URL 共享给 Facebook,那么 Facebook 可能会重定向到 dotNetRedirect.htm 页面,然后服务器端重定向会强制打开“选择应用程序对话框”提示。

不幸的是,这不起作用,在非库存浏览器中,如果第一个重定向没有触发意图/“选择应用程序对话框”,进一步的重定向也不会出现。大量内脏。


尝试的解决方案 B

(使用自定义方案)

在用尽了服务器端的想法后,我想我应该研究一下使用自定义 URI 方案来触发“应用选择对话框”。

AndroidManifest.xml:

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="myapp" />
</intent-filter>

redirect.htm

<html><body><script>
   window.location.href = "myapp.com://sharedpage";
</script></body></html>

这确实有效,即使使用非库存浏览器,“选择应用程序对话框”也会通过 DB l.php URL 出现。然而,这并不是一个真正可行的解决方案,因为“非 MyApp 用户”在重定向到 myapp.com://sharedpage URL 时会留下“网页不可用”页面。 ]


还有其他人有什么好的想法或建议吗?

【问题讨论】:

  • 解决方法很简单:杀掉Facebook。您可以查看 Referer [sic] 标头,如果它来自 Facebook,请在您的页面顶部手动插入一个按钮,询问用户是否要在您的应用中打开该页面。

标签: android facebook redirect android-intent intentfilter


【解决方案1】:

我在搜索中做了一些进一步的开发,发现执行“假点击”是在大多数情况下(但不是全部)都有效的解决方案。

如果用户希望分享 URL http://myapp.com/sharedpage,那么我实际上将以下 URL 发布到 Facebook http://myapp.com/share.htm?redirectUrl=sharedpage

share.htm 只是一个 javascript 重定向页面,它会立即重定向到相应的页面。尽管在 Android 上它很聪明,而不是仅仅使用window.location.replace,它使用带有链接的按钮的虚假点击,这可以强制在某些设备/某些浏览器上触发意图。代码如下所示。

<!DOCTYPE HTML>
<html>
<body>
    <script type="text/javascript">
        var redirectUrlRelativeToThisPage = ""; // Read off the querystring here
        var isAndroidDevice = (/android/gi).test(navigator.userAgent);

        if (isAndroidDevice) {
            // Android device. If the user isn't using a stock browser then window.location.redirect() doesn't always
            // trigger an Intent (and prompt to open Native app) so instead attempt to fake click a hyperlink with the
            // URL as this works more reliably (but not always).
            var linkToFakeClick = document.createElement("a");
            linkToFakeClick.href = redirectUrlRelativeToThisPage;
            var fakeMouseClickEvent = document.createEvent("MouseEvents");
            fakeMouseClickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            linkToFakeClick.dispatchEvent(fakeMouseClickEvent);
        }
        // If we got here either we're not on an Android device or the fake click didn't work so just redirect normally
        window.location.replace(redirectUrlRelativeToThisPage);
    </script>
</body>
</html>

除了上面的示例代码,如果它适合您的场景,您还可以合并(如果假点击不起作用)两个不同的“我安装/没有安装应用程序”按钮,其中链接到自定义方案 URL(强制意图)和通常的 URL。

【讨论】:

  • 我尝试了您的解决方案。就我而言,由于非库存浏览器没有从某些应用程序中打开我的应用程序,因此我一直在将链接传播到(S-Planner,HTMLViewer),我试图在 javascript 代码中“假点击”完全相同的 url。但这不起作用。知道为什么吗?
  • 什么版本的安卓?最新版本 (4.4) 已切换到使用 Chromium for WebView,这可能就是原因。 developer.chrome.com/multidevice/webview/overview
  • 我在 Galaxy S3 4.3 版上进行测试。我在我的 javascript 中所做的所有事情都是检查某个标志的 url。如果该标志不存在,则我使用您的代码伪造单击具有相同 url 但添加了此标志的超链接。这样我就不会进入无限循环。这仍然不能识别我的应用程序的意图过滤器。感谢您在这里提供帮助。谢谢。
  • 我真的不能提供比我已经提供的更多的信息了。正如我在自己的努力中发现的那样,我已经特别提到过,该解决方案“在大多数情况下都有效 ---> 但并非所有情况下都适用
  • 废话。还是谢谢。
【解决方案2】:

一个非常肮脏的解决方法是在http://m.facebook.com/l.php 上放置一个意图过滤器:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data 
        android:scheme="http" 
        android:host="m.facebook.com" 
        android:path="/l.php" />
</intent-filter>

然后解析查询字符串并通过另一个意图传递实际 URL(如果它不适合您的应用)。

但不推荐它,因为它可能看起来有点奇怪,将您的应用视为与您的应用完全不相关的链接的选择。此外,如果用户第一次选择了您的应用,则会提示用户两次选择应用。唯一一次可以很好地工作(在链接不适合您的应用程序的情况下)是如果手机将您的应用程序设置为所有 http://m.facebook.com/l.php 请求的默认值。你仍然会搞乱 facebook 的内部运作。

希望 android 浏览器将来会更多地使用隐式意图,这是一个开始:https://code.google.com/p/chromium/issues/detail?id=235060

【讨论】:

    【解决方案3】:

    您是否考虑过使用 Facebook 深度链接? http://developers.facebook.com/docs/mobile/android/deep_linking/

    【讨论】:

    • 感谢您的建议,但我已经研究过深度链接,不幸的是,这不是一个可行的解决方案,因为它会将所有 Facebook 用户驱动到 Android Google Play 商店安装,无论他们是否在 Android 上.我的应用程序可作为网络应用程序提供给 iPhone 用户,因此他们只需重定向到网络应用程序 URL 而不是 Play 商店。这对于深层链接是不可能的。
    • 你确定吗?如果属实,这是 iPhone 的 facebook 应用程序上的一个错误。通过深度链接,您只需共享任何 URL,Android facebook 应用程序将使用 Intent 中提供的 url 启动您的应用程序的入口点,而不是打开浏览器。在 iPhone 上,它的行为应该与往常一样并打开链接。
    猜你喜欢
    • 2011-03-01
    • 2013-04-27
    • 2015-04-11
    • 1970-01-01
    • 2011-12-05
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多