有没有办法将消息从 Android 浏览器传递到应用程序?

Posted

技术标签:

【中文标题】有没有办法将消息从 Android 浏览器传递到应用程序?【英文标题】:Is there a way to pass a message from an Android browser to an app? 【发布时间】:2011-07-04 16:22:58 【问题描述】:

我有一种情况,我希望将一些数据从移动网站传递到原生 android 应用程序。一个复杂的问题是,在正常情况下,加载移动网站时可能不会安装原生 Android 应用程序。

这是一个例子:

我是 ExampleApp 的用户,我想与从未安装过 ExampleApp 的您分享来自 ExampleApp 的特定数据。

我会向您发送一封电子邮件,其中包含指向移动网页的链接,该链接知道您在打开链接时想要查看哪些数据。但是,由于数据仅在本机应用程序中可用,而不是移动网络,因此您会被带到一个页面,要求您前往 Android Market 并安装 ExampleApp。

您安装了 ExampleApp,理想情况下,您会被直接带到我与您共享的数据片段。

最大的问题在于查看移动网页和安装 ExampleApp 之间的脱节。

我考虑了几个解决方案,但都没有成功(也就是说,我可能只是错误地实施了它们):

    在我们的域上设置一个 cookie,其中包含加载移动网页时的数据。然后,在打开 ExampleApp 时,启动一个 WebView 以请求同一域上的页面并检查 cookie 的值。使用它来确定要在 ExampleApp 中显示的数据。 使用 javascript localStorage 存储对数据的引用,并使用 WebView 获取该域上的页面并从 ExampleApp 中请求 localStorage 的内容。

在这两种情况下,似乎 WebView 和浏览器都在沙箱中彼此分离,因此您无法访问两者之间的 cookie/localStorage。

还有其他方法可以“留下 crumbtrail”或设置稍后安装的应用可以从浏览器访问的消息吗?

编辑:鉴于一些回应,我应该提一下,我只希望您在链接上单击一次,而不必单击一次,安装应用程序,然后再次单击以将应用程序打开到正确的位置。

【问题讨论】:

我会害怕从我的浏览器获取消息的应用程序。看起来我买的那个“酷游戏”会由营销公司支付,只是收集数据。我当然希望你不能这样做! 【参考方案1】:

解决方案其实很简单,我有点惊讶,一年多来没人能想出它。所以这里是:

基本思想是使用cookies来存储信息。数据流如下:

打开网页 -> 设置 cookie -> 重定向到市场 -> 安装应用程序 -> 使用网页启动浏览器 -> 读取 cookie -> 使用 cookie 数据启动自定义意图 -> 捕获意图并读取 cookie 数据

用户访问网页(例如通过扫描二维码标签)。网页的 url 包含对您要传递的数据的引用,或包含数据本身。该网站将数据设置为 cookie 并重定向到 Android 市场 (http://market.android.com/details?id=com.yourapp)。一旦您的应用程序启动,您就会打开浏览器并再次加载相同的网页。但是,这一次,它检测到 cookie 已经设置并重定向到自定义 URL 方案,例如 example://example.com/installed?id=DATA,而不是市场。使用 Intent 过滤器,您可以启动 Activity 并从 Intent 中提取信息。

这里是相关的Activity代码:

public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    Intent intent = getIntent();
    if(intent == null || intent.getData() == null || !"example".equals(intent.getData().getScheme())) 
        String url = "http://example.com/yourApp/index.php";
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setData(Uri.parse(url));
        startActivity(i);
        finish();
        return;
    else 
        Uri uri = intent.getData();
        if("example".equals(uri.getScheme())) 
            id = uri.getQueryParameter("id");
        
    
    ... initialise your activity ...

一个简单的PHP文件(网站),便于演示:

<?php
$value = "123";
if(!isset($_COOKIE["TestCookie"])) 
    setcookie("TestCookie", $value, time()+3600);  /* expire in 1 hour */
    header("Location: http://market.android.com/details?id=com.yourapp");
    exit;
else 
    header("Location: example://example.com/installed?id=".$_COOKIE["TestCookie"]);
    exit;

?>

以及意图过滤器:

<!-- Handle URLs like loyalty://example.com/merchant/123 -->
<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="example" android:host="example.com" />
</intent-filter>

顺便说一句,我已决定blog 处理此问题。

【讨论】:

你通过这个测试了吗?在最初的问题中,iseff 引用他的 Cookies 不起作用(沙盒环境),所以我想知道您是否能够从应用程序中的浏览器访问 cookie TestCookie。谢谢 当然,我已经测试过它可以工作!请注意,设置 cookie 并检索它然后启动自定义意图的网站始终在股票 Android 浏览器中打开,而不是在 WebView 中。因此 cookie 将可用。 太好了!您提到“股票浏览器”,但非股票浏览器(如 Firefox 或 SkyFire)呢?我希望它适用于所有浏览器,而不仅仅是默认浏览器。 (如果你也能成为一个亲爱的人并测试这些......我相信这会帮助很多人!) 用户选择使用哪个浏览器并不重要,重要的是两个请求使用相同的浏览器(安装应用程序之前和安装应用程序之后的一个)。 IE。我只是想强调一下,该应用在安装后不使用 WebView 打开 URL(其中 cookie 不可用,因为 WebView 是沙盒的)。 简直太棒了,弗洛里安。【参考方案2】:

有没有其他方法可以“留下 crumbtrail”或设置稍后安装的应用可以从浏览器访问的消息?

我认为有一个更简单的解决方案,是 Barcode Scanner 采用的解决方案的一种变体。

第 1 步:创建一个漂亮的 RESTful URL,其中包含您想要的信息。 RESTful 我的意思是没有?,没有#,没有那些废话。如果这是在一个不同的域名上,它会更简单,但这可能只是你现有域上的东西。出于这个答案的目的,我假设这个 URL 看起来像 http://android.exampleapp.com/our/custom/data/goes/in/here/somewhere

第 2 步:对于可以按照第 1 步的模式创建的所有 URL(http://android.exampleapp.com 中的任何内容),您的 Web 服务器应该提供一个页面,显示“嘿!您没有安装 ExampleApp!如果你点击这里的链接,它会带你到安卓市场,在那里你可以安装 ExampleApp!然后,尝试点击带你到这个页面的链接,它会启动 ExampleApp 并给你......嗯......所有这些好数据”。

第 3 步:在 ExampleApp 中实现一个活动,该活动包含一个带有 VIEW 操作的 &lt;intent-filter&gt;BROWSEABLE 类别和一个标识您的方案和域的 &lt;data&gt; 元素(以及,如果需要,基础路径,如果所有这些链接都相同的话)。

如果用户没有安装 ExampleApp 并单击链接,他们将看到的是您在第 2 步中的网页,他们可以从中安装 ExampleApp。

如果用户确实安装了 ExampleApp 并单击链接,他们看到的是您的活动,它可以通过 getIntent().getData() 获取 URL 并做一些有用的事情。


更新

在评论中,您写道:

移动网页 => 存储数据 => 用户安装应用 => 用户打开应用 => 应用检索数据 => 应用直接打开检索到的内容

恕我直言,您对用户将要做什么做出了太多假设。我用粗体标出的箭头之间可能有几天、几周或几个月的延迟。

如果您打算自己分发它(例如,从您的 Web 服务器上),您总是可以选择“刻录”一个自定义 APK,其中包含其中的数据,但是您必须处理管理更新自己。

或者,如果您使用基于帐户的系统,请让他们在您的网站上创建一个帐户,然后再将其发送到 Android 电子市场。将数据存储在该帐户下,当他们从应用连接回该帐户时,您可以将数据与应用匹配。

【讨论】:

这也是基于用户的两次点击来实现的。我希望将其减少为单击他们收到的 URL。然后我们可以轻松地让他们完成安装过程,他们可以立即看到数据。对此有什么想法? @iseff:“这也是基于用户两次点击来实现的。” - 无论您如何完成它,它都将不仅仅是两次点击。您以前在 Android 上安装过应用程序吗?市场中将有 2-3 次点击,以及使用通知启动应用程序,无论在市场之前或应用程序内点击。顺便说一句,我在回答中添加了更多注释。 当然,全部点击两次以上;我的意思是在 original 链接上单击两次(单击一次,发送到“下载应用程序”页面,安装应用程序,再次单击,发送到应用程序)。我正在寻找一个无缝的流程。我们当然已经考虑过注册过程,但同样,摩擦越少越好。就箭头之间的“天/小时/月”延迟而言,我们可以通过让市场链接​​进行数据存储来最小化这种延迟,然后,在大多数情况下,它会非常快。显然有很多方法可以解决这个问题,但我正在寻找最小的摩擦。 不,别再找了。如果有一种方法可以让网页直接调用另一个应用程序而无需用户点击确认,这将是一个需要修复的安全漏洞。【参考方案3】:

使用 GET 参数:http://exampleapps.com?token=mK7Fyt5 想想 YouTube 应用的工作方式。您将被发送到视频链接。如果您没有 YouTube 应用程序,您会看到移动网站(在您的情况下可能是安装链接)。如果这样做,系统会询问您是否使用本机应用打开 YouTube 链接,并且本机应用会传递调用它的 URL,从中可以解析出要显示的视频的参数。

使用以下意图过滤器:

<intent-filter>
    <data android:scheme="http" android:host="exampleapps.com"/>
    <action android:name="android.intent.action.VIEW" />
</intent-filter>

【讨论】:

对不起,我想我的问题应该更清楚了。这个想法是让人们安装应用程序,因为这是他们查看内容的唯一方式。所以它是:移动网页 => 存储数据 => 用户安装应用程序 => 用户打开应用程序 => 应用程序检索数据 => 应用程序直接打开检索到的内容 啊,这有点清楚了。我不认为这是可能的,而且无论如何这不是预期的行为,用户会同意在安装应用程序后返回到他们发送的链接的想法。【参考方案4】:

见:https://***.com/a/7577379/710284

您可以使用 INSTALL_REFERRER 链接,例如:http://market.android.com/details?id=your.package.name&referrer=your_wanted_parameter

在用户点击此链接并安装应用程序后,您的广播接收器将收到带有“your_wanted_pa​​rameter”值的广播 com.android.vending.INSTALL_REFERRER。

更多信息:http://code.google.com/mobile/analytics/docs/android/#android-market-trackingGet referrer after installing app from Android MarketGet Android Google Analytics referrer tag

【讨论】:

Referrer 似乎不可靠,并且在某些设备上不起作用。 “Referrer Test for Google Play”和“Install Referrer Test”等市场应用不会在我的 Galaxy S III 上显示推荐人。

以上是关于有没有办法将消息从 Android 浏览器传递到应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

将 Cookie 从 Java 传递到浏览器

如何将消息从 GCP 推送订阅传递到本地 PC?

有没有办法拦截 Android SMS 发送以转发到不同的传输?

有没有办法将 localstorage:getItem() 的结果从 webview 传递给活动

有没有办法在Android上将arraybuffer从javascript传递到java?

FCM:有没有办法订阅匹配正则表达式的所有主题?