Android(安卓)过滤器

意图过滤器

您已经了解了如何使用 Intent 调用另一个活动(activity)。Android OS 使用过滤器来确定活动,服务和广播接收器的集合,这些接收器可以在指定的一组动作,类别和与 Intent 相关的数据方案的帮助下处理 Intent。您将在清单文件中使用 <intent-filter> 元素列出与任何活动,服务或广播接收者关联的动作,类别和数据类型。

以下是 AndroidManifest.xml 文件的一部分实例,用于指定活动 com.cankaoshouce.helloworld.CustomActivity,可以通过上述两个操作(一个类别和一个数据)之一来调用该活动:

  1. <activity android:name=".MainActivity">
  2. <intent-filter tools:ignore="AppLinkUrlError">
  3. <action android:name="android.intent.action.VIEW" />
  4. <action android:name="com.cankaoshouce.helloworld.LAUNCH" />
  5. <category android:name="android.intent.category.DEFAULT" />
  6. <data android:scheme="https" />
  7. </intent-filter>
  8. </activity>

当 activity 活动被上面的过滤器所定义,其他 activity 就可以通过下面的方式来调用这个 activity。使用 android.intent.action.VIEW,使用 com.cankaoshouce.helloworld.LAUNCH 动作,并提供 android.intent.category.DEFAULT 类别。

元素指定要被调用的 activity 活动所期望的数据类型。上面的实例中,自定义活动期望的数据由 "https://" 开头。有这样的情况,通过过滤器,意图将被传递到多个 activity 活动或者服务,用户将被询问启动哪个组件。如果没有找到目标组件,将发生一个异常。

在调用活动之前,有一系列的 Android 检查测试:

  • 过滤器 <intent-filter> 需要列出一个或者多个的动作,不能为空;过滤器至少包含一个元素,否则将阻塞所有的意图。如果多个动作被提到,Android 在调用活动前尝试匹配其中一个动作。
  • 过滤器 <intent filter> 可以列出 0 个、1 个或多个类别。如果没有提到类别,那么 Android 总是通过这个测试,但是如果提到多个类别,那么为了通过类别测试,intent 对象中的每个类别都必须与过滤器中的类别匹配。
  • 每个元素可以指定一个 URI 和一个数据类型(元媒体类型)。这里有独立的属性,如 URI 中的每个部分:模式,主机,端口和路径。意图包含有 URI 和类型,只有它的类型匹配了过滤器中列出的某个类型,则通过数据类型部分的测试。

实例

以下实例是对上述实例的修改。在这里,我们将看到如果一个意图调用中定义的两个 activity 活动,Android 如何解决冲突,接下来如何使用过滤器调用自定义活动,第 3 个是如果 Android 没有提交为某个意图定义的适当 activity 的例外情况:

步骤描述
1使用 Android Studio IDE 创建 Android 应用程序,并命名为 Intent filter,包名为 com.cankaoshouce.helloworld
2修改 src/com.cankaoshouce.helloworld/MainActivity.java 文件,添加代码来定义 3 个监听器来对应布局文件中定义的 3 个按钮。
3添加 src/com.cankaoshouce.helloworld/CustomActivity.java 文件来包含一个活动,可以被不同的意图调用。
4修改 res/layout/activity_main.xml 文件在线性布局中添加 3 个按钮。
5添加 res/lauout/custom_view.xml 布局文件,添加简单地 来显示通过 intent 传递的数据。
6修改 AndroidManifest.xml 文件,添加 <intent-filter> 定义意图的规则来调用自定义活动。
7运行应用程序以启动 Android 模拟器,并验证应用程序中所做更改的结果。

以下是修改后的主要活动文件 src/MainActivity.java 的内容:

  1. package com.cankaoshouce.helloworld;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.net.Uri;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.widget.Button;
  8. public class MainActivity extends Activity {
  9. Button b1,b2,b3;
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14. b1=(Button)findViewById(R.id.button);
  15. b1.setOnClickListener(new View.OnClickListener() {
  16. @Override
  17. public void onClick(View v) {
  18. Intent i = new Intent(android.content.Intent.ACTION_VIEW,
  19. Uri.parse("https://cankaoshouce.com"));
  20. startActivity(i);
  21. }
  22. });
  23. b2 = (Button)findViewById(R.id.button2);
  24. b2.setOnClickListener(new View.OnClickListener() {
  25. @Override
  26. public void onClick(View v) {
  27. Intent i = new Intent("com.cankaoshouce.helloworld.LAUNCH",Uri.parse("https://cankaoshouce.com"));
  28. startActivity(i);
  29. }
  30. });
  31. b3 = (Button)findViewById(R.id.button3);
  32. b3.setOnClickListener(new View.OnClickListener() {
  33. @Override
  34. public void onClick(View v) {
  35. Intent i = new Intent("com.cankaoshouce.helloworld.LAUNCH",
  36. Uri.parse("http://cankaoshouce.com"));
  37. startActivity(i);
  38. }
  39. });
  40. }
  41. }

以下是修改后的主要活动文件 src/com.cankaoshouce.helloworld/CustomActivity.java 的内容:

  1. package com.cankaoshouce.helloworld;
  2. import android.app.Activity;
  3. import android.net.Uri;
  4. import android.os.Bundle;
  5. import android.widget.TextView;
  6. public class CustomActivity extends Activity {
  7. @Override
  8. public void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.custom_view);
  11. TextView label = (TextView) findViewById(R.id.show_data);
  12. Uri url = getIntent().getData();
  13. label.setText(url.toString());
  14. }
  15. }

以下是 res/layout/activity_main.xml 文件的内容:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical" >
  7. <TextView
  8. android:id="@+id/textView1"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:layout_alignParentTop="true"
  12. android:layout_centerHorizontal="true"
  13. android:layout_marginTop="67dp"
  14. android:text="意图|过滤器示例"
  15. android:textSize="30dp" />
  16. <TextView
  17. android:id="@+id/textView2"
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:layout_below="@+id/textView1"
  21. android:layout_centerHorizontal="true"
  22. android:layout_marginTop="32dp"
  23. android:text="参考手册"
  24. android:textColor="#ff87ff09"
  25. android:textSize="30dp" />
  26. <ImageButton
  27. android:id="@+id/imageButton"
  28. android:layout_width="wrap_content"
  29. android:layout_height="wrap_content"
  30. android:layout_below="@+id/textView2"
  31. android:layout_centerHorizontal="true"
  32. android:layout_marginTop="42dp"
  33. android:src="@drawable/logo" />
  34. <EditText
  35. android:layout_width="wrap_content"
  36. android:layout_height="wrap_content"
  37. android:id="@+id/editText"
  38. android:layout_below="@+id/imageButton"
  39. android:layout_alignRight="@+id/imageButton"
  40. android:layout_alignEnd="@+id/imageButton" />
  41. <Button
  42. android:id="@+id/button"
  43. android:layout_width="wrap_content"
  44. android:layout_height="wrap_content"
  45. android:layout_alignStart="@+id/imageButton"
  46. android:layout_alignLeft="@+id/imageButton"
  47. android:layout_alignTop="@+id/editText"
  48. android:layout_alignEnd="@+id/imageButton"
  49. android:layout_centerHorizontal="true"
  50. android:layout_marginStart="3dp"
  51. android:layout_marginLeft="3dp"
  52. android:layout_marginTop="32dp"
  53. android:layout_marginEnd="-2dp"
  54. android:text="启动浏览器" />
  55. <Button
  56. android:id="@+id/button2"
  57. android:layout_width="wrap_content"
  58. android:layout_height="wrap_content"
  59. android:layout_below="@+id/button"
  60. android:layout_alignStart="@+id/button"
  61. android:layout_alignLeft="@+id/button"
  62. android:layout_alignEnd="@+id/button"
  63. android:layout_centerHorizontal="true"
  64. android:layout_marginStart="2dp"
  65. android:layout_marginLeft="2dp"
  66. android:layout_marginTop="20dp"
  67. android:layout_marginEnd="-1dp"
  68. android:text="动过 LAUNCH 启动浏览" />
  69. <Button
  70. android:id="@+id/button3"
  71. android:layout_width="wrap_content"
  72. android:layout_height="wrap_content"
  73. android:layout_below="@+id/button2"
  74. android:layout_alignStart="@+id/button2"
  75. android:layout_alignLeft="@+id/button2"
  76. android:layout_alignParentEnd="true"
  77. android:layout_centerHorizontal="true"
  78. android:layout_marginStart="-17dp"
  79. android:layout_marginLeft="-17dp"
  80. android:layout_marginTop="29dp"
  81. android:layout_marginEnd="16dp"
  82. android:layout_toStartOf="@+id/editText"
  83. android:text="异常条件测试" />
  84. </RelativeLayout>

以下将是 res/layout/custom_view.xml 文件的内容:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical" android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <TextView android:id="@+id/show_data"
  6. android:layout_width="fill_parent"
  7. android:layout_height="400dp"/>
  8. </LinearLayout>

以下将是 AndroidManifest.xml 的内容:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. package="com.cankaoshouce.helloworld">
  5. <application
  6. android:allowBackup = "true"
  7. android:icon = "@mipmap/ic_launcher"
  8. android:label = "@string/app_name"
  9. android:supportsRtl = "true"
  10. android:theme = "@style/AppTheme">
  11. <activity android:name = ".MainActivity">
  12. <intent-filter>
  13. <action android:name = "android.intent.action.MAIN" />
  14. <category android:name = "android.intent.category.LAUNCHER" />
  15. </intent-filter>
  16. </activity>
  17. <activity android:name="com.cankaoshouce.helloworld.CustomActivity">
  18. <intent-filter tools:ignore="AppLinkUrlError">
  19. <action android:name = "android.intent.action.VIEW" />
  20. <action android:name = "com.cankaoshouce.helloworld.LAUNCH" />
  21. <category android:name = "android.intent.category.DEFAULT" />
  22. <data android:scheme = "https" />
  23. </intent-filter>
  24. </activity>
  25. </application>
  26. </manifest>

让我们尝试运行我们刚刚创建的 HelloWorld 应用程序。我假设您是在进行环境设置时创建的 AVD。要从 Android Studio 运行该应用,请打开您项目的 Activity 文件之一,然后运行图标从工具栏中单击 Eclipse Run Icon 图标。Android 在您的 AVD 上安装该应用程序并启动它,如果您的设置和应用程序一切正常,它将在 "模拟器" 窗口中显示。

现在让我们从第一个按钮 "使用VIEW Action启动浏览器" 开始。在这里,我们使用过滤器 "android.intent.action.VIEW" 定义了自定义活动,并且已经有一个针对 Android 定义的 VIEW 活动的默认活动,该活动正在启动网络浏览器,因此 android 显示以下两个选项来选择您需要的活动要启动。

现在,如果您选择浏览器,则 Android 将启动 Web 浏览器并打开 cankaoshouce.com 网站,但是如果您选择 My Indernt2 Application 选项,则 Android 将启动 CustomActivity,它仅捕获捕获的数据并在文本视图中显示。

现在使用后退按钮返回并单击 "通过LAUNCH Action启动浏览器" 按钮,此处 Android 应用过滤器选择定义 activity 活动,它只是启动您的自定义活动再次,使用 "后退" 按钮返回并单击 "异常条件" 按钮,此处 Android 尝试为给定的意图找到有效的过滤器,但未找到定义的有效活动,因为这一次我们将数据用作 http 而不是 https 尽管我们采取了正确的措施,所以 Android 引发了异常并显示以下屏幕: