Android 显示Intent和隐示Intent

Android 显示Intent和隐示Intent
效果图
显示Intent                 隐示Intent


显示Intent和隐示Intent

显式Intent:通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,一般是在相同的应用程序内部实现的。

隐式Intent:通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间。

Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动服务、以及发送广播等场景,由于服务、广播等概念你暂时还未涉及,那么本章我们的目光无疑就锁定在了启动活动上面。

一.显式Intent

Intent 有多个构造函数的重载,其中一个是 Intent(Context packageContext, Class cls)。这个构造函数接收两个参数,第一个参数 Context 要求提供一个启动活动的上下文,第二个参数 Class 则是指定想要启动的目标活动,通过这个构造函数就可以构建出 Intent 的“意图”。然后我们应该怎么使用这个 Intent 呢?Activity 类中提供了一个 startActivity()方法,这个方法是专门用于启动活动的,它接收一个 Intent 参数,这里我们将构建好的 Intent 传入 startActivity()

方法就可以启动目标活动了。

一般情况下,一个Android应用程序中需要多个屏幕,即是多个Activity类,并且在这些Activity之间进行切换通过Intent机制来实现的。在同一个应用程序中切换Activity时,我们通常都知道要启动的Activity具体是哪一个,因此常用显式的Intent来实现的。

下面的例子是在同一应用程序中MainActivity启动SecondActivity,下面的代码中,主要是为“转到SecondActivity”按钮添加了OnClickListener,使得按钮被点击时执行onClick()方法,onClick()方法中则利用了Intent机制,来启动SecondActivity。

activity_main.xml

xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.chenxiaoyang.intent.MainActivity">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/app_name"
        android:textSize="30dp"/>

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="转到SecondActivity"/>
LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实例化Button
        mButton = (Button) findViewById(R.id.btn);
        //响应按钮btn事件
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //显示方式声明Intent,直接启动SecondActivity
                Intent it = new Intent(MainActivity.this, SecondActivity.class);
                //启动Activity
                startActivity(it);
            }
        });
    }
}

activity_second.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_second"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.chenxiaoyang.intent.SecondActivity">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/app_name_second"
        android:textSize="30dp"/>

    <Button
        android:id="@+id/secondBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="返回"/>
LinearLayout>

SecondActivity

public class SecondActivity extends AppCompatActivity {
    private Button mButtonSecond;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        //实例化Button
        mButtonSecond = (Button) findViewById(R.id.secondBtn);
        //响应按钮secondBtn事件
        mButtonSecond.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //显示方式声明Intent,直接启动MainActivity
                Intent intent = new Intent(SecondActivity.this, MainActivity.class);
                //启动Activity
                startActivity(intent);
            }
        });
    }
}

AndroidManifest.xml清单文件

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

activity>
<activity android:name=".SecondActivity">
activity>
Android 显示Intent和隐示Intent_第1张图片

二.隐示Intent

相比于显示Intent,隐示Intent则含蓄了许多,它并不明确指出我们想要启动哪一个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Initent,并帮我们找出适合的活动去启动。

什么叫做合适的活动呢?简单来说就是可以响应我们这个隐式 Intent 的活动,那么目前SecondActivity 可以响应什么样的隐式 Intent 呢?额,现在好像还什么都响应不了,不过很快就会有了。

新建一个SecondActivity类,通过在标签下配置的内容,可以指定当前活动能够响应的 action和 category,打开 AndroidManifest.xml,添加如下代码: 

<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="com.example.activitytest.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>
    intent-filter>
activity>
Android 显示Intent和隐示Intent_第2张图片

activity_main..xml

xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.chenxiaoyang.initent.MainActivity">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/app_name"
        android:textSize="30dp"/>

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="转到SecondActivity"/>
LinearLayout>

标签中我们指明了当前活动可以响应 com.example.chenxiaoyang.initent.ACTION_START 这个 action,而标签则包含了一些附加信息,更精确地指明了当前的活动能够响应的 Intent 中还可能带有的 category。只有中的内容同时能够匹配上 Intent 中指定的 action 和 category 时,这个活动才能响应该 Intent。

修改 MainActivity 中按钮的点击事件,代码如下所示: 

public class MainActivity extends AppCompatActivity {
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实例化button
        mButton= (Button) findViewById(R.id.btn);
        // 响应按钮Button事件
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 实例化Intent
                Intent intent = new Intent();
                //设置Intent的Action属性  
                intent.setAction("com.example.chenxiaoyang.initent.ACTION_START");
                // 启动Activity 
                startActivity(intent);
            }
        });
    }

可以看到,我们使用了 Intent 的另一个构造函数,直接将 action 的字符串传了进去,表明我们想要启动能够响应 com.example.chenxiaoyang.initent.ACTION_START 这个 action 的活动。那前面不是说要同时匹配上才能响应的吗?怎么没看到哪里有指定category 呢?这是因为 android.intent.category.DEFAULT 是一种默认的 category,在调用startActivity()方法的时候会自动将这个 category 添加到 Intent 中。重新运行程序,在 FirstActivity 的界面点击一下按钮,你同样成功启动 SecondActivity了。不同的是,这次你是使用了隐式 Intent 的方式来启动的,说明我们在标签下配置的 action 和 category 的内容已经生效了!每个 Intent 中只能指定一个 action,但却能指定多个 category。目前我们的 Intent 中只有一个默认的 category,那么现在再增加一个。

修改MainActivity中按钮的点击事件,代码如下所示: 

//新添加的Category
intent.addCategory("com.example.chenxiaoyang.initent.MY_CATEGORY");

Android 显示Intent和隐示Intent_第3张图片

可以调用 Intent 中的 addCategory()方法来添加一个 category,这里我们指定了一个自定义的 category,值为 com.example.activitytest.MY_CATEGORY。

现在重新运行程序,在MainActivity的界面点击一下按钮,你会发现,程序崩溃了会有以下错误


错误信息中提醒我们,没有任何一个活动可以响应我们的 Intent,为什么呢?这是因为我们刚刚在 Intent 中新增了一个 category,而 SecondActivity 的标签中并没有声明可以响应这个 category,所以就出现了没有任何活动可以响应该 Intent 的情况。现在我们在中再添加一个 category 的声明,如下所示: 

<category android:name="com.example.chenxiaoyang.initent.MY_CATEGORY"/>
Android 显示Intent和隐示Intent_第4张图片

再次运行程序就会发现一切都正常了


使用隐式 Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使得 Android 多个应用程序之间的功能共享成为了可能。比如说你的应用程序中需要展示一个网页,这时你没有必要自己去实现一个浏览器,而是只需要调用系统的浏览器来打开这个网页就行了。 

这里我们首先指定了 Intent 的 action 是 Intent.ACTION_VIEW,这是一个 Android 系统内置的动作,其常量值为 android.intent.action.VIEW。然后通过 Uri.parse()方法,将一个网址字符串解析成一个 Uri 对象,再调用 Intent 的 setData()方法将这个 Uri 对象传递进去。

重新运行程序,在 FirstActivity 界面点击按钮就可以看到打开了系统浏览器 

activity_main.xml

xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_second"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.chenxiaoyang.initent.SecondActivity">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/app_name_second"
        android:textSize="30dp"/>

    <Button
        android:id="@+id/secondBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="跳转网页"/>
LinearLayout>
SecondActivity
public class SecondActivity extends AppCompatActivity {
    private Button mButtonSecond;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        //实例化Button
        mButtonSecond= (Button) findViewById(R.id.secondBtn);
        // 响应按钮Button事件
        mButtonSecond.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //实例化Intent
                Intent intent = new Intent(Intent.ACTION_VIEW);
                //指定Intent跳转网页
                intent.setData(Uri.parse("http://www.baidu.com"));
                // 启动Activity
                startActivity(intent);
            }
        });
    }
}

上述的代码中,可能你会对 setData()部分感觉到陌生,它接收一个 Uri 对象,主要用于指定当前 Intent 正在操作的数据,而这些数据通常都是以字符串的形式传入到 Uri.parse()方法中解析产生的。 

你可能感兴趣的:(Android)