从浏览器启动安卓应用程序

8
我看了几个与我的标题类似的Stack Overflow问题。每个问题都有答案,原作者似乎很满意,但是当我尝试复制他们的结果时,却一无所获。显然我做错了什么,但我似乎无法弄清楚。

供参考,这些是我一直在查看的问题:

最终,我想在用户执行OAuth身份验证请求后重新启动我的应用程序。但是,我的真实应用程序有点太大了,无法在此处发布。对于这个问题,我准备了一个简单的应用程序,以展示我所做的事情。我有两个活动。这主要是因为我看到的每个示例都使用了一个使用VIEW操作的活动。我更喜欢使用MAIN操作,但是我在这里都使用了一下,以展示我尝试过两种方法。

AndroidManifest.xml(原始版本;请参见下面的编辑版本)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.example" android:versionCode="1" android:versionName="1.0-SNAPSHOT">
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
    <activity android:name=".HelloAndroidActivity">
        <intent-filter>
            <data android:scheme="ex1"/>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
    <activity android:name=".CallbackActivity">
        <intent-filter>
            <data android:scheme="ex2"/>
            <action android:name="android.intent.action.VIEW"/>
        </intent-filter>
    </activity>
</application>

AndroidManifest.xml(根据评论进行编辑)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.example" android:versionCode="1" android:versionName="1.0-SNAPSHOT">
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
    <activity android:name=".HelloAndroidActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
    <activity android:name=".CallbackActivity">
        <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="www.this-so-does-not-exist.com" android:scheme="http" />
        </intent-filter>
    </activity>
</application>

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

HelloAndroidActivity.java

package org.example;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroidActivity extends Activity {

    private TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textView = (TextView) findViewById(R.id.textView);
    }

    @Override
    public void onResume() {
        super.onResume();
        Intent intent = getIntent();
        Uri data = intent.getData();
        if (data != null) {
            textView.setText("Hello Web!");
        }
    }

}

CallbackActivity.java

package org.example;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;

public class CallbackActivity extends Activity {

    private TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textView = (TextView) findViewById(R.id.textView);
    }

    @Override
    public void onResume() {
        super.onResume();
        Intent intent = getIntent();
        Uri data = intent.getData();
        if (data != null) {
            textView.setText("Hello Web!");
        }
    }

}

这个构建过程非常顺利。然后,在浏览器中,如果我输入ex1://helloworld或ex2://helloworld,取决于如何操作,我会得到不同的结果。如果我在url栏中输入它,我会得到一个针对ex1://helloworld的谷歌搜索。如果我通过重定向来完成操作,我会得到“网页不可用”的提示。如果我尝试直接启动类似以下内容的意图:

    Intent intent = new Intent(Intent.ACTION_MAIN);
    ComponentName componentName = new ComponentName(
            "org.example",
            "org.example.HelloAndroidActivity");
    intent.setComponent(componentName);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setData(Uri.parse("ex1://helloworld"));
    intent.addCategory(Intent.CATEGORY_BROWSABLE);
    startActivity(intent);

我得到了默认的“Hello my-example!”。我不确定我的操作有什么问题。有什么见解吗?
2个回答

14

你不能使用MAIN -- 在Android中,URL只能从浏览器或WebViewVIEW

此外,你的任何Intent过滤器都不包括BROWSABLE类别,因此它们永远不会与浏览器一起使用。

不建议自己发明方案。你可以使用一个常规的HTTP方案,用于一些你控制的域名。 这个示例项目演示了这一点。特别是,你可以遵循此过滤器所显示的模式:

<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="www.this-so-does-not-exist.com" android:scheme="http" />
</intent-filter>

www.this-so-does-not-exist.com替换为您拥有的内容,并可能添加一个path以缩小过滤器的范围。您也可以看到这种技术是由ZXing的条形码扫描应用程序使用的。


1
@Tim:我不知道它是否可以从地址栏中工作。关键是要让它从链接中工作。 - CommonsWare
我正在尝试在安卓4.3上使用您的URLHandler演示版本。它没有按预期工作,因为针对mimeType“application/pdf”的BROWSABLE VIEW意图不会在浏览器中单击PDF链接时打开URLHandler活动(已测试Chrome和Dolphin)。例如,Chrome向我显示了一系列准备处理PDF的不同应用程序,但您的演示版并不在其中。问题出在哪里?先行致谢! - Stan
@Stan:Chrome 试图找到处理 http 方案而不是 PDF MIME 类型的东西。如果您查看 LogCat,您将看到类似于以下内容:I/ActivityManager(1177): START u0 {act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=http://commonsware.com/Android/excerpt.pdf cmp=android/com.android.internal.app.ResolverActivity (has extras)}。如果您在选择器中选择 Web 浏览器,则会启动下载,然后显示一个带有 URLHandler 的选择器,以查看已下载的文件。 - CommonsWare
@Stan:你不能强制其他应用程序必须启动第三方活动。具体而言,我希望浏览器应用程序能够自行处理它们知道如何处理的内容:HTML、图像等。 - CommonsWare
1
@KunalKalwar:“我们可以在一个intent-filter中添加多个类别吗?”--是的,这是允许的。它应该作为逻辑OR:Intent可以匹配任何提供的类别。个人而言,我会针对许多单独简单的<intent-filter>元素进行设计,即使会导致一些元素的重复。 - CommonsWare
显示剩余7条评论

0
试一下这个,如果你想从浏览器启动你的应用程序 我昨天已经做了这个
1)在本地主机上制作HTML页面
<html>
<head>
</head>
<body>
<a href="yourownscheme://example.com/">Test link</a>
</body>
</html>

2) 创建一个类

   import org.xml.sax.Parser;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class URLHandler extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);



    TextView uri=(TextView)findViewById(R.id.uri);
    TextView uri2=(TextView)findViewById(R.id.uri);


    if (Intent.ACTION_MAIN.equals(getIntent().getAction())) {
      String intentUri=(new Intent("yourownscheme://example.com/")).toUri(Intent.URI_INTENT_SCHEME).toString();



      uri.setText(intentUri);

    }
   }
  }

3) 下面是清单

<?xml version="1.0" encoding="utf-8"?>
<manifest android:versionCode="1"
          android:versionName="1.0"
          package="yourpackage name"
          xmlns:android="http://schemas.android.com/apk/res/android">

  <supports-screens android:largeScreens="true"
                    android:normalScreens="true"
                    android:smallScreens="false" />
  <application android:icon="@drawable/cw"
               android:label="@string/app_name">



      <activity
        android:name=".URLHandler"
        android:label="@string/app_name" 
        android:exported="true">
        <intent-filter>

            <data  android:scheme="yourownscheme://example.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>


  </application>
</manifest>

4) 当你在模拟器上安装了你的应用程序后,打开浏览器并转到 localhost,点击链接和你的应用程序,如果它已经安装,它将启动,否则会出现错误。


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