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


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

这是一个例子:

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

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

您安装了ExampleApp,理想情况下,您将直接访问我与您共享的数据。

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

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

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

在这两种情况下,似乎WebView和浏览器都是相互远离的沙箱,因此您无法获得两者之间的cookies / localStorage。

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

编辑:鉴于一些回复,我应该提到我只希望你点击链接一次,不必点击一次,安装应用程序,然后再次点击打开应用程序到正确的地方。


6989
2018-02-25 23:45


起源

我会害怕从我的浏览器收到消息的应用程序。看起来我购买的“酷游戏”将由营销公司支付农业数据。我当然希望你不能这样做! - corsiKa


答案:


解决方案实际上非常简单,我有点惊讶,没有人能够提出它超过一年。所以这里是:

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

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

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

这是相关的活动代码:

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>

顺便说一句,我已经决定了 博客 关于这个问题。


10
2018-02-28 11:00



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


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

我认为有一个更简单的解决方案,一种条形码扫描仪所采用的解决方案。

步骤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!如果您在此处单击此链接,它将带您到Android Market,在那里您可以安装ExampleApp!然后,尝试单击链接这会带你到这个页面,它会启动ExampleApp并给你......嗯......所有这些好的数据“。

步骤3:在ExampleApp中实现具有的活动 <intent-filter> 随着 VIEW 行动, BROWSEABLE 类别,和 <data> 标识您的方案和域的元素(如果需要,还有基本路径,如果所有这些链接都相同)。

用户看到的内容,如果他们没有安装ExampleApp并单击链接,则是来自步骤#2的Web页面,他们可以从中安装ExampleApp。

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


UPDATE

在评论中,你写道:

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

恕我直言,你对用户将做什么做了太多的假设。我以粗体显示的箭头之间可能有数天,数周或数月的延迟。

如果你打算自己发布它(例如,你的Web服务器之外),你总是可以选择用它们里面的数据“烧”他们自己的APK,但是你必须自己处理管理更新。

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


4
2018-02-26 00:12



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


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

使用以下intent过滤器:

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

0
2018-02-26 00:10



对不起,我想我的问题应该更清楚了。我们的想法是让人们安装应用程序,因为这是他们可以看到内容的唯一方式。所以它是:移动网页=>商店数据=>用户安装应用程序=>用户打开应用程序=>应用程序检索数据=>应用程序直接打开检索到的内容 - iseff
啊,这有点清楚。我不认为这是可能的,无论如何这不是预期的行为,用户可以回到他们安装应用程序后发送的链接。 - fredley


看到: https://stackoverflow.com/a/7577379/710284

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

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

更多信息:
http://code.google.com/mobile/analytics/docs/android/#android-market-tracking
从Android电子市场安装应用后获取推荐人
获取Android Google Analytics引荐来源代码


0
2017-08-21 07:53



推荐人似乎不可靠,并且在某些设备上不起作用。诸如“Google Play的推荐人测试”和“安装推荐人测试”之类的市场应用程序不会在我的Galaxy S III上显示推荐人。 - Ilya Kogan