有没有一种方法可以将来自Android浏览器的消息传递给应用程序?

13
我有这样一个情况,希望将一些数据从移动网站传递到本机Android应用程序。一个复杂的问题是,在正常情况下,当加载移动网站时,本机Android应用程序可能尚未安装。
以下是示例:
我是ExampleApp的用户,想要与您共享ExampleApp中的特定数据,而您从未安装ExampleApp。
我向您发送一封电子邮件,并附有一个链接到移动网页的链接,该链接知道打开链接时您要查看哪个数据。但是,由于数据仅在本机应用程序中可用,而不是在移动网络中,因此您将被带到一个页面,询问您去Android市场并安装ExampleApp。
您安装了ExampleApp,理想情况下,您将直接转到我与您分享的数据。
大问题在于查看移动网页和安装ExampleApp之间的断开。
我考虑了几种解决方案,但都没有成功(也许我实现不正确):
1. 在我们的域上设置一个cookie,包括移动网页加载时的数据。然后,在打开ExampleApp时,启动一个WebView请求同一域上的页面并检查cookie的值。使用它来确定ExampleApp中显示哪些数据。 2. 使用JavaScript localStorage存储对数据的引用,并使用WebView从ExampleApp获取该域上的页面并请求localStorage的内容。
在这两种情况下,似乎WebView和浏览器相互隔离,因此无法在两者之间获取cookie/localStorage。
是否有其他方法可以“留下踪迹”或设置消息,稍后安装的应用程序可以从浏览器访问?
编辑:鉴于一些回复,我应该提到,我只希望您单击链接一次,而不是必须单击一次,安装应用程序,然后再次单击以打开正确的位置。

我会担心那些可以从我的浏览器获取消息的应用程序。似乎那些所谓的“酷游戏”会被营销公司用来采集数据并收费。我希望你不能这样做! - corsiKa
4个回答

11

解决方案其实很简单,我有点惊讶为什么没有人能在一年多的时间内想出来。因此,这就是:

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

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

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

这里是相关的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>

顺便说一下,我已经决定博客这个问题。


你用这个通过测试了吗?在原问题中,isEff提到他的Cookies无法工作(沙盒环境),所以我想知道你是否能够从应用程序中的浏览器访问Cookie“TestCookie”。谢谢。 - DougA
1
当然,我测试过它能够正常工作!请注意,在设置cookie并检索它,然后启动自定义意图的网站始终在原生Android浏览器中打开,而不是WebView中打开。因此,cookie将可用。 - Florian
1
太好了!你提到了“原生浏览器”,但是非原生浏览器如Firefox或SkyFire呢?我希望它能在所有浏览器上运行,而不仅仅是默认浏览器。(如果你能测试一下那些浏览器,那肯定会帮助很多人!) - DougA
用户选择使用哪个浏览器并不重要,重要的是在安装应用程序之前和之后使用相同的浏览器进行请求。也就是说,我只想强调应用程序在安装后不使用 WebView 打开 URL(在此情况下,Cookie 将不可用,因为 WebView 处于沙盒中)。 - Florian
真是太棒了,Florian。 - Slawomir
在URL路径中添加Cookie是否会存在任何安全问题? - AbdullahC

4
有没有其他方法可以“留下面包屑”或设置一条消息,后来安装的应用程序可以从浏览器中访问?
我认为有一个更简单的解决方案,类似于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!如果您单击此处的链接,它将带您到Android Market,在那里您可以安装ExampleApp!然后,尝试单击将您带到此页面的链接,它将启动ExampleApp并为您提供...嗯...所有这些好数据”。
步骤3:在ExampleApp中实现一个具有VIEW操作、BROWSEABLE类别和标识您的方案和域(如果需要,则为基本路径)的data元素的intent-filter的活动。
如果用户没有安装ExampleApp并单击链接,则会看到步骤2中的Web页面,从中可以安装ExampleApp。
如果用户已经安装ExampleApp并单击链接,则会看到您的活动,该活动可以通过getIntent().getData()获取URL并执行一些有用的操作。
更新
在评论中,您写道:
移动网页=>存储数据=>用户安装应用程序=>用户打开应用程序=>应用程序检索数据=>应用程序直接打开检索到的内容
在我看来,您对用户要做什么做出了太多假设。我放粗体字的箭头之间可能会有几天、几周或几个月的延迟。
如果您要自己分发(例如,从您的Web服务器),则始终可以选择“烧录”一个带有数据的自定义APK,但然后您必须处理自己的更新管理。
或者,如果您采用基于帐户的系统,请在将其发送到Android Market之前让他们在您的网站上创建一个帐户。在该帐户下存储数据,并在他们从应用程序连接回该帐户时,您可以将数据与应用程序匹配起来。

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

0

使用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>

抱歉,我想我的问题应该更清楚一些。这个想法是让人们安装应用程序,因为这是他们唯一能看到内容的方式。所以它是:移动网页=>存储数据=>用户安装应用程序=>用户打开应用程序=>应用程序检索数据=>应用程序直接打开检索到的内容。 - iseff
1
啊,这样说就清楚多了。我认为这是不可能的,而且这也不是预期的行为。用户安装了应用程序后,重新访问他们收到的链接是可以接受的。 - fredley

0

请参考:https://dev59.com/nWs05IYBdhLWcg3wPPWB#7577379

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

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

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


推荐人在某些设备上显得不可靠,无法正常工作。像“Google Play 推荐人测试”和“安装推荐人测试”这样的市场应用程序在我的 Galaxy S III 上无法显示推荐人信息。 - Ilya Kogan

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