如何在Android浏览器中创建一个链接,使其启动我的应用程序?

247

是否可以创建以下形式的链接:

<a href="anton://useful_info_for_anton_app">click me!</a>

如何启动我的Anton应用程序?

我知道Android Market应用程序可以通过“market”协议实现此功能,但其他应用程序能否进行类似操作?

以下是一个启动Android Market的链接示例:

<a href="market://search?q=pname:com.nytimes.android">click me!</a>

更新: 我接受了eldarerathis提供的答案,它非常好用,但我只想提一下,我在<intent-filter>标签的子元素顺序上遇到了一些问题。建议您简单地创建另一个<intent-filter>,并将该标签中的新子元素放在其中,以避免我所遇到的问题。例如,我的AndroidManifest.xml文件看起来像这样:

<activity android:name=".AntonWorld"
          android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter>
        <data android:scheme="anton" />
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

9
+1分是为了提及xml标签的顺序。虽然这在任何地方都没有记录,但当数据标签位于动作和类别标签下方时,它根本不起作用,因此我发现它非常重要。 - Adam
重定向到应用程序并在应用程序不存在时正确回退也可能会有些棘手,考虑到所有不同的Android浏览器(Chrome、默认、Webviews、Firefox等)的复杂性。https://branch.io服务可以帮助解决这个问题,并且是免费的。 - Alex Austin
@Anton 先生,您好。根据您的代码,我只能理解如何处理来自链接的数据。请问您能告诉我如何创建一个包含我的数据的链接吗?我想在按钮点击事件中创建带有数据的链接。请帮帮我。 - Ravindra Kushwaha
可能是从Android浏览器启动自定义Android应用程序的重复问题。 - Tot Zam
1
⚠️我遇到了一个调试难题,其他人也可能需要注意:在网页中使用<a href="">链接时,链接可以正常工作,并且通过adb启动时也可以正常工作,但是当您只在移动浏览器地址栏中键入URL时却无法正常工作。⚠️ - Johannes Brodwall
显示剩余2条评论
10个回答

286
请不要使用自己的自定义方案!!!URI方案是一个网络全局命名空间。你是否拥有全球范围内的“anton:”方案?没有?那就不要使用它。
其中一个选项是拥有一个网站,并为该网站上的特定URI设置意图过滤器。例如,这就是Market在其网站上拦截URI所做的事情:
        <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="market.android.com"
                android:path="/search" />
        </intent-filter>

另外,还有一种“intent:”方案。这使您可以将几乎任何Intent描述为URI,并在单击时尝试启动浏览器。要构建这种方案,最好的方法是编写构造要启动的Intent的代码,然后打印intent.toUri(Intent.URI_INTENT_SCHEME)的结果。

对于此意图,您可以使用一个操作来查找支持该操作的任何活动。出于安全原因,在启动它之前,浏览器将自动向意图添加可浏览类别;出于同样的原因,它也会剥离您提供的任何显式组件。

如果您想确保仅启动您的应用程序,则最好的方法是使用自己的作用域操作,并使用Intent.setPackage()来指示Intent仅与您的应用程序包匹配。

两者之间的权衡:

  • http URI需要您拥有自己的域。用户将始终有选择将URI显示在浏览器中。如果您的应用未安装,则具有非常好的回退属性,他们将简单地进入您的网站。

  • 意向URI要求您的应用程序已安装,并且仅限于Android手机。它们允许几乎任何意向(但始终包括BROWSABLE类别并且不支持显式组件)。它们允许您将启动定向到仅您的应用程序,而用户无法选择转而进入浏览器或任何其他应用程序。


33
另一方面,市场应用程序也可以处理 market:// 链接 :) - Felix
38
使用“市场”是一个错误,现已被删除。 - hackbod
83
人们在Android中使用自定义方案的原因是因为大多数项目都是与iPhone版本并行开发(或之后开发)的,这是使其在该平台上运行的唯一方法。 - LambergaR
12
同意 @LambergaR 的观点。现在我们需要找出一种方法,使得电子邮件中的链接可以在三个平台(BB、iPhone、Android)上正常工作。 - Maragues
7
如果您在网页中使用自定义方案的任何URI,在没有安装您的应用程序的Web浏览器上将无法正常工作。这对您来说似乎有点不可行,是吗? - hackbod
显示剩余18条评论

101

我认为你需要看一下你的清单文件中的 <intent-filter> 元素。具体来说,查看 <data> 子元素的文档。

基本上,你需要定义自己的方案。大致如下:

<intent-filter>
    <data android:scheme="anton" />
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" /> <--Not positive if this one is needed
    ...
</intent-filter>

那么您应该能够使用以 anton: URI 方案开头的链接启动您的应用程序。


3
试着查看这个帖子。它有一个很好的例子:https://dev59.com/7HA85IYBdhLWcg3wD_O8 - eldarerathis
4
参考文献中添加CATEGORY_BROWSABLE意味着“浏览器可以安全地调用目标活动以显示链接引用的数据,例如图像或电子邮件消息。” - greg7gkb
3
这在之前的Android版本上运作得很完美,但在棒棒糖上不行,有解决办法吗? - Salmaan
1
@eldarerathis 如果应用程序关闭,这个方法是有效的。但是如果应用程序在后台运行,并且活动与附加了意图过滤器的活动不同,我无法处理它。你是如何确保在所有活动中都能正常工作的?你会将意图过滤器放入所有活动中吗? - Mustafa Güven
5
这个回答已经过时了。在Chrome 40版本之后,它将不再适用。由于安全问题,Chrome已禁用自定义方案。 - Utsav Gupta
显示剩余9条评论

14

我有一个jQuery插件,可以从网页链接中启动原生应用程序:https://github.com/eusonlito/jquery.applink

您可以很容易地使用它:

<script>
$('a[data-applink]').applink();
</script>

<a href="https://facebook.com/me" data-applink="fb://profile">My Facebook Profile</a>

13

我也遇到了这个问题,看到很多荒谬的页面。我发现为了使您的应用程序可浏览,需要更改XML元素的顺序,像这样:

<activity
    android:name="com.example.MianActivityName"
    android:label="@string/title_activity_launcher">

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <intent-filter>                
        <data android:scheme="http" />     
        <!-- or you can use deep linking like  -->               

        <data android:scheme="http" android:host="xyz.abc.com"/>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <category android:name="android.intent.category.DEFAULT"/>

    </intent-filter>
</activity>

这个对我有用,也可能对你有帮助。


我按照相同的顺序编写XML标签,但在Android浏览器中输入我的URL时无法打开选择器对话框。 - Sunit Kumar Gupta
我没有看到太大的区别,如果我使用这个,它完美地工作了。谢谢 :) - IamVariable

6
这是我的配方: 创建一个静态HTML,重定向到您请求的应用程序URL,将该页面放在Web上。 这样,您分享的链接在Android看来就是“真正”的链接(它们将是“可点击的”)。 您“分享”一个常规HTTP链接www.your.server.com/foo/bar.html 此URL返回一个简单的8行HTML,重定向到您的应用程序URI(window.location =“blah://kuku”)(请注意,“blah”不再必须是HTTP或HTTPS)。 一旦您完成此操作并运行,您可以使用上述所有高级功能来增强HTML。 这适用于内置浏览器、Opera和Firefox(未测试其他浏览器)。 Firefox会询问“需要使用应用程序打开此链接”(确定,取消)。 其他浏览器显然不太担心安全问题,它们只需打开应用程序,无需任何问题。

太好了!它对我起作用了。所以我们添加了一个带有指向自定义方案的链接的HTML页面,该方案会重定向到我的应用程序。我的链接是<a href="iamnearby://register_activate">激活</a> - S. Koshelnyk

5

这种方法不会调用消除歧义对话框,也不会要求您打开应用程序或浏览器。

如果您在清单中注册了以下内容

<manifest package="com.myApp" .. >
  <application ...>
    <activity ...>
      <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:host="gallery"
          android:scheme="myApp" />
      </intent-filter>
    </activity>
    ..

例如,从手机上的电子邮件中单击此URL链接

<a href="intent://gallery?directLink=true#Intent;scheme=myApp;package=com.myApp;end"> 
  Click me 
</a>

那么,安卓将尝试查找一个包名为com.myApp的应用程序,该应用能够响应您的gallery意图并拥有myApp方案。如果找不到该应用程序,它会带您去商店寻找com.myApp,这应该是您的应用程序。


如何进入 Android 活动? - Mohsen Emami
清单文件中指定的<activity ...>将会打开,因为它是唯一附加了<intent-filter>的活动。 - sea cat
我该如何在手机上进行文本测试? - roghayeh hosseini
嗨,對我來說這個方法有效,但如果應用程式未安裝,我想在網頁上顯示一些訊息,該如何做到呢? - Dharini
@Dharini,我认为你无法做到这一点,因为你没有从浏览器(不是你自己的应用程序)获取应用程序是否安装的知识。在你自己的应用程序中,你可以通过查看是否有响应你意图的东西来检查另一个应用程序是否安装,但是从第三方(在你的情况下是浏览器)获取这些信息的方式是不存在的。 - sea cat

4

一旦您为应用程序设置好意图和自定义URL方案,以下JavaScript代码可在iOS和Android上的接收页面的顶部使用:

<script type="text/javascript">
// if iPod / iPhone, display install app prompt
if (navigator.userAgent.match(/(iPhone|iPod|iPad);?/i) ||
    navigator.userAgent.match(/android/i)) {
  var store_loc = "itms://itunes.com/apps/raditaz";
  var href = "/iphone/";
  var is_android = false;
  if (navigator.userAgent.match(/android/i)) {
    store_loc = "https://play.google.com/store/apps/details?id=com.raditaz";
    href = "/android/";
    is_android = true;
  }
  if (location.hash) {
    var app_loc = "raditaz://" + location.hash.substring(2);
    if (is_android) {
      var w = null;
      try {
        w = window.open(app_loc, '_blank');
      } catch (e) {
        // no exception
      }
      if (w) { window.close(); }
      else { window.location = store_loc; }
    } else {
      var loadDateTime = new Date();
      window.setTimeout(function() {
        var timeOutDateTime = new Date();
        if (timeOutDateTime - loadDateTime < 5000) {
          window.location = store_loc;
        } else { window.close(); }
      },
      25);
      window.location = app_loc;
    }
  } else {
    location.href = href;
  }
}
</script>

这仅在Android浏览器上进行了测试。 我不确定Firefox或Opera是否适用。 关键是,即使Android浏览器不会为window.open(custom_url,'_blank')抛出漂亮的异常,但它将失败并返回null,以供稍后测试。
更新:在Android上使用store_loc = "https://play.google.com/store/apps/details?id=com.raditaz";链接到Google Play。

1
加载日期时间/超时日期时间的意义是什么?这是否能绕过弹出拦截器或其他东西? - Matt Wolfe
在我的测试中似乎不起作用,window.open(...)将始终打开一个新窗口,即使方案未被处理。 - jtomson
@MattWolfe 抱歉回复晚了。在iPhone(Safari)上不会抛出任何异常。超时是为了关闭在页面重定向到应用程序后剩余的Safari中的陈旧窗口。我还没有找到一种方法可以在不经过Safari和大多数其他识别此类URL的应用程序的情况下打开URL。这是从Facebook进行“深度链接”的优点之一:您不会因通过移动Safari而获得那个陈旧的剩余窗口。 - Pete
@jtomson:有趣。我在模拟器和各种Android设备上进行了测试,从2.1到3(当时)。你在哪个设备和Android版本上进行测试? - Pete

4

您可能需要考虑使用一个库来处理深链接到您的应用程序:

https://github.com/airbnb/DeepLinkDispatch

您可以在已注释的 Activity 上添加意图过滤器,就像上面建议的那样。它将处理所有深度链接的路由和参数解析。例如,您的 MainActivity 可能会有类似这样的代码:

@DeepLink("somePath/{useful_info_for_anton_app}")
public class MainActivity extends Activity {
   ...
}

它也可以处理查询参数。

0

试试我的简单技巧:

        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if(url.startsWith("classRegister:")) {                  
                Intent MnRegister = new Intent(getApplicationContext(), register.class); startActivity(MnRegister);
            }               
            view.loadUrl(url);
            return true;
        }

还有我的HTML链接:

<a href="classRegister:true">Go to register.java</a>

或者你可以将 < a href="classRegister:true" > <- "true" value for class filename

然而,这个脚本适用于mailto链接 :)

        if (url.startsWith("mailto:")) {
            String[] blah_email = url.split(":");
            Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
            emailIntent.setType("text/plain");
            emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{blah_email[1]});
            emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, what_ever_you_want_the_subject_to_be)");
            Log.v("NOTICE", "Sending Email to: " + blah_email[1] + " with subject: " + what_ever_you_want_the_subject_to_be);
            startActivity(emailIntent);
        }

这本质上是对JavascriptInterface 的一次调用,采用此解决方法是正确的, 如果你需要支持2.3且遇到了JavascriptInterface的Bug。 - EpicPandaForce

0

想要通过浏览器打开应用程序吗?您可以使用以下代码实现:

HTML:

<a href="intent:#Intent;action=packageName;category=android.intent.category.DEFAULT;category=android.intent.category.BROWSABLE;end">Click here</a>

清单:

<intent-filter>
      <action android:name="packageName" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
</intent-filter>

这个 Intent Filter 应该在启动器活动中。

如果你想在浏览器链接点击时传递数据,只需参考 此链接


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