Intents in Android

Intent in Android can be used to start another component in an App or a component of another App in a component. The components mentioned here refer to Activity, Service and Broadcast.

Table of contents

Purpose of Intent

Intent type

The composition of Intent

Explicit Intent usage example

Implicit Intent usage example

Force users to use App Chooser (default option)

Purpose of Intent

Intent mainly has the following important uses:

  1. Start Activity: You can pass an Intent object to the startActivity() method or startActivityForResult() method to start an Activity. The Intent object contains the information of the Activity to be started and other necessary data.

  2. Start Service: You can pass an Intent object to the startService() method or bindService() method to start a Service. The Intent object contains the information of the Service to be started and other necessary data.

  3. Send broadcast: Broadcast is a kind of information that all Apps can receive. The Android system will release various types of broadcasts, such as broadcasting a startup broadcast or a mobile phone charging broadcast. We can also send broadcasts to other apps, and we can pass the Intent object to the sendBroadcast() method, sendOrderedBroadcast() method or sendStickyBroadcast() method to send custom broadcasts.

Intent type

There are two types of Intent: explicit (explicit) and implicit (implicit).

Explicit Intent: If the Intent clearly contains the complete class name (package name and class name) of the component to be started, then the Intent is explicit, that is, explicit. The most typical situation of using explicit Intent is to start a component in your own App, because you must know the class name of the component you want to start. For example, in response to user actions, start an Activity in your App or start a Service to download files through an explicit Intent.

Implicit Intent: If the Intent does not contain the full class name of the component to be started, then the Intent is implicit, that is, implicit. Although the implicit Intent does not specify the class name of the component to be started, in general, the implicit Intent must specify the action that needs to be executed. Generally, implicit Intent is only used when we want to start another App's component through Intent in our own App, so that another App's component can receive and process the Intent. For example, if you want to show the user a location on a map, but your app does not support map display, then you can put the location information into an Intent, and then specify the corresponding action for it, through this implicit Intent requests other map-based apps (such as Google Map, Baidu Map, etc.) to display a specified location on the map. Implicit Intent also embodies a design philosophy of Android: my own App does not need to cover all functions, but can be combined with other Apps to provide users with a good user experience. The link between your own App and other Apps is the implicit Intent.

When an explicit Intent is created to start an Activity or Service, the system will immediately start the components specified in the Intent.

When an implicit Intent is created for use, the Android system will compare and filter the information contained in the implicit Intent with the Intent Filters of the components registered in the manifest file of all other Apps on the device, and find out the information that meets the requirements for receiving the intent. App and corresponding components that handle the implicit Intent. If a component in multiple apps meets the conditions, Android will pop up a dialog box to let the user choose which app needs to be started.

Intent Filter, that is, Intent Filter, a component can contain 0 or more Intent Filters. The Intent Filter is written in the manifest file of the App, which specifies the type of Intent that the component can handle by setting the action or uri data type, etc. If you set an Intent Filter for your Activity, then this makes it possible for other apps to start your Activity through an implicit Intent. Conversely, if your Activity does not contain any Intent Filter, then the Activity can only be started through an explicit Intent. Since we generally do not expose the full class name of our component, in this case, other apps are basically impossible. Started our Activity through explicit Intent (because they don't know the full class name of the Activity), it can only be started by our own App through explicit Intent.

It should be noted that in order to ensure the security of the App, we should always use an explicit Intent to start the Service and do not set any Intent Filter for the Service. Starting a Service through an implicit Intent is risky, because you are not sure which Service in which App will start up in response to your implicit Intent. What's more sad is that because the Service runs in the background without a UI, the user I don't know which Service is running. Starting from Android 5.0 (API level 21), when calling the bindService() method with an implicit Intent, Android will throw an exception, but there are also corresponding techniques to convert an implicit Intent to an explicit Intent, and then use the explicit Intent There is no problem in calling the bindService() method.

The composition of Intent

Android can find the components to be started according to the information carried in the Intent, and the Intent also carries some data information so that the components to be started can do corresponding processing according to the data in the Intent.

Intent consists of 6 parts of information:

  1. Action

  2. Data

  3. Category

  4. Type (data type)

  5. Component

  6. Extra (extended information)

  7. Flag (flag bit)

According to the role of information, it can be divided into three categories:

  • Component Name, Action, Data, and Category are one category. These 4 pieces of information determine which component Android will start. Among them, Component Name is used in explicit Intent, Action, Data, Category, Extras, and Flags are used in implicit Used in Intent.

  • Extras is a category, which contains specific data information for the actual processing of components.

  • Flags is a class, which is the metadata of Intent, which determines some behaviors of Android for its operation.

Component name

The name of the component to start. If you want to use an explicit Intent, then you must specify this parameter. Once the component name is set, Android will directly pass the Intent to the component specified by the component name to start it. If the component name is not set, then the Intent is implicit, and the Android system will make some comparisons and judgments based on other Intent information (such as action, data, category, etc. to be introduced below) to decide which component to start. So, if you start a component in your own App, you should start it through an explicit Intent by specifying the component name (because you know the full class name of the component).

It should be noted that when starting the Service, you should always specify the Component Name. Otherwise, you are not sure which component of which App is started, and the user cannot see which Service is started.

The corresponding field of the component name in the Intent is the ComponentName object, and you can specify the value by the full class name of the component to be started (including the package name of the application), such as com.example.ExampleActivity. You can specify the component name through the Intent's setComponent() method, setClass() method, setClassName() method, or the Intent constructor.

Action

It is a string representing the operation to be performed, such as view or selection, which corresponds to the action tag <action /> in the Intent Filter .

You can specify your unique action to facilitate the use of Intent in your App or call components in your App through Intent in other Apps. The Intent class and some other framework-level classes in Android also provide many well-defined actions with certain general meanings. The following are some common actions used to start the Activity: You can refer to the Android official document Intent.ACTION_VIEW

Its value is "android.intent.action.VIEW". When you have some information that you want to display to the user through other activities, you can specify the action of the Intent as ACTION_VIEW, such as viewing a picture in a picture application , or display a location in a map application.

Intent.ACTION_SEND

Its value is "android.intent.action.SEND". This action is often used for "sharing". When you have some data that you want to share through other apps (such as QQ, WeChat, Baidu Cloud, etc.), you can Use this action to construct an Intent object and pass it to the startActivity() method. Since there may be multiple App Activities on the mobile phone that all support the ACTION_SEND action, it is very likely that the situation shown in the following picture will appear for the user to specify Choose which App to share your data with:

Write picture description here

You can specify the intent's action by calling the intent object's setAction() method or in the Intent's constructor.

If you define your own action, be sure to prefix the action with the package name of your App. This is a good programming practice to avoid confusion, for example:

static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
type effect
ACTION_MAIN Indicates the program entry
ACTION_VIEW Automatically display Data in the most appropriate way
ACTION_EDIT Provides an editable
ACTION_PICK Select a Data and return it
ACTION_DAIL Display the number pointed to by Data on the dial interface Dailer
ACTION_CALL Dial the number pointed to by Data
ACTION_SEND Send Data to the specified place
ACTION_SENDTO Send multiple sets of Data to the specified place
ACTION_RUN Run Data, no matter what Data is
ACTION_SEARCH perform search
ACTION_WEB_SEARCH perform a web search
ACRION_SYNC Perform synchronization of a Data
ACTION_INSERT add an empty item to the container

Broadcast Actions:

type effect
ACTION_TIME_TICK The current time changes and sends the time instantly, only through the system. calling format"android.intent.action.TIME_TICK"
ACTION_TIME_CHENGED Set the time. calling format"android.intent.action.TIME_SET"

Data

The data in the Intent mentioned here refers to the MIME type of the Uri object and data, which corresponds to the data tag in the Intent Filter <data />.

A complete Uri consists of scheme, host, port, path, the format is

<scheme>://<host>:<port>/<path>
//例content://com.example.project:200/folder/subfolder/etc

Uri is like a data link, and components can obtain the final data source based on this Uri. Uri and action are usually used in combination, for example, if we set action to ACTION_VIEW, we should provide the Uri of the document to be edited and modified.

When creating an Intent object, in addition to specifying the Uri, it is also important to specify the MIME type of the data. For example, an Activity can display pictures, but cannot play videos. The Uri for displaying pictures may be very similar to the Uri for playing videos. In order to prevent Android from mistakenly passing an Intent object containing video Uri to an Activity that can only display pictures, We need to specify the MIME type as an image in the Intent Filter of the Activity

For example <data android:mimeType="image/*" ... />

And set the MIME of the corresponding image type for the Intent object, so that Android will pass the Intent to the eligible components based on the Uri and MIME type. Then there is a special case, if Uri uses the content: protocol, then this means that the data provided by Uri will come from the local device, that is, the data is provided by ContentProvider. In this case, Android will automatically infer the MIME type based on Uri. In this case, we no longer need to specify the MIME type ourselves.

If you only set the Uri of the data, you need to call the setData() method of the Intent object; if you only set the MIME type of the data, you need to call the setType() method of the Intent object; if you want to set the Uri and MIME type of the data at the same time, you need to call the Intent object The setDataAndType() method.

It should be noted that if you want to set the Uri and MIME type of the data at the same time, do not call the setData() method and the setType() method of the Intent object successively, because the setData() method and setType() method are mutually exclusive, that is, if Calling the setData() method will reset the MIME type set by the setType() method in the Intent to null. If the setType() method is called, the Uri that has been set by the setData() method in the Intent will be reset to empty. Therefore, when you need to set the Uri and MIME types of the data at the same time, you must call the setDataAndType() method of the Intent object instead of calling the setData() method and the setType() method separately.

Category

The category contains some other information about how the component handles the Intent. Although any number of categories can be added to the Intent, most Intents do not need a category. Here are some common categories:

  • The CATEGORY_BROWSABLE target component will allow itself to be launched by a web browser through a link, which may be a picture link or e-mail message.

  • CATEGORY_LAUNCHER is used to identify that the Activity is the entry Activity of an App.

type effect
CATEGORY_DEFAULT Set a component Component to be started by implicit
CATEGORY_LAUNCHER Set an action to execute at the top level. And the icon defined by the Activity containing this attribute will replace the icon defined in the application
CATEGORY_BROWSABLE This category must be added when the Intent points to the network
CATEGORY_HOME Make the Intent point to the Home interface
CATEGORY_PREFERENCE The defined Activity is a preference panel Preference Panel

You can find more predefined categories in the Intent class.

Extras

Extras, as the name suggests, are additional data information . There is a Bundle object in the Intent that stores key-value pairs, and the component receiving the Intent can read the required information from it to complete the corresponding work. Some Intents need to rely on Uri to carry data, and some Intents rely on extras to carry data information.

You can add extra data in the form of various key-value pairs to the Intent by calling various overloaded putExtra(key, value) methods of the Intent object. You can also directly create a Bundle object, pass in many key-value pairs to the Bundle object, and then set a piece of them to the Intent object by calling the putExtras(Bundle) method of the Intent object.

For example, if you create an Intent object whose action is ACTION_SEND, and then want to use it to start e-mail to send mail, then you need to set two extra values ​​for the Intent object: use Intent.EXTRA_EMAIL as the key value to set the recipient, Set the email subject with Intent.EXTRA_SUBJECT as the key value.

type effect
EXTRA_BCC An array of strings storing the addresses of bcc recipients
EXTRA_CC An array of strings storing email cc addresses
EXTRA_EMAIL String array to store email addresses
EXTRA_SUBJECT store email subject string
EXTRA_TEXT Store email content
EXTRA_KEY_EVENT Store the key that triggers the Intent as a KeyEvent object
EXTRA_PHONE_ NUMBER Store the phone number when calling ACTION_CALL

The Intent class also specifies many predefined extras in the form of EXTRA_*, such as the ones we mentioned above (Intent.EXTRA_EMAIL and Intent.EXTRA_SUBJECT). If you want to declare your own custom extras, make sure to prefix your extras with your App's package name, for example:

static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";

Flags

The flag is the meaning of the mark . It is expected that the operating mode of this intent is used to instruct the system how to start an Activity, and the tag flag can be used setFlags()or addFlags()used in the Intent.

type effect
FLAG_ACTIVITY_CLEAR_TOP equivalent toSingleTask
FLAGE_ACTIVITY_SINGLE_TOP equivalent toSingleTop
FLAG_ACTIVITY_NEW_TASK similar toSingleInstance
FLAG_ACTIVITY_NO_HISTORY When leaving the Activity, the Activity will be removed from the task stack

Explicit Intent usage example

Intent intent = new Intent(this, ActivityB.class);
startActivity(intent);

The above code specifies that the ComponentName of the component to be started is ActivityB in the Intent constructor. The intent object is explicit. When startActivity(intent) is called, the Android system will immediately start ActivityB.

Implicit Intent usage example

As mentioned before, when using implicit Intent, you need to specify its action. If your app cannot complete a certain function, but other apps may complete the function, then you can use the implicit Intent to start other apps to complete the corresponding function. For example, if you have a piece of text information and want to share it through other apps, then the implicit Intent object is used to start the potential app that supports sharing. The sample code is as follows:

Intent sendIntent = new Intent();
// 设置action, action对隐式Intent来说是非常重要的
sendIntent.setAction(Intent.ACTION_SEND);
// 设置数据的MIME类型为纯文本类型
sendIntent.setType("text/plain");
// 设置额外的数据
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
​
// 获取包管理器
PackageManager pm = getPackageManager();
// 先判断系统中有没有潜在的App的Activity支持对该sendIntent的接收与处理
if (pm.resolveActivity(sendIntent, 0) != null) {
    startActivity(sendIntent);
}

上面的代码中,我们构建了一个Intent对象,并没有给其设置component name,所以该Intent是一个隐式的Intent对象。我们首先给intent设置了action的值为Intent.ACTION_SEND,action对隐式Intent来说是非常重要的。然后我们将intent的数据的MIME类型设置为纯文本类型(“text/plain”),告知Android我们的Intent持有的是文本类型的数据。最后我们将实际的文本数据通过putExtra()方法作为额外数据设置进去。

需要注意的是,在构建好了Intent对象之后,我们没有立即执行startActivity(sendIntent)方法,而是将sendIntent作为参数传递给了PackageManager的resolveActivity()方法中,该方法会让Android根据该sendIntent找到潜在的适合启动的组件的信息,并以ResolveInfo类的对象的形式返回结果,如果返回null,表示当前系统中没有任何组件可以接收并处理该sendIntent。如果返回不是null,就表明系统中至少存在一个组件可以接收并处理该sendIntent,只有在这种情况下,我们才会执行代码startActivity(sendIntent),在通过intent启动组件之前先判断要启动的组件存不存在是个良好的编程习惯,因为如果系统中不存在支持你的intent的组件,那么当你调用startActivity()、startService()、bindService()等方法的时候,Android就会抛出异常。

强制用户使用App Chooser(默认选项)

如果我们的Intent是隐式的,当我们通过startActivity(intent)尝试启动组件的时候,可能Android系统会显示上面的截图文件询问用户要启动哪个App,有时候用户会将某一个App设置为默认的App,这样下次我们再执行代码startActivity(intent)的时候就有可能不会再出现选择App的界面,而是直接运行上次用户设置为默认App的应用。这对于用户选择一个默认浏览器打开网页这种情形是有好处的,因为一般一个用户习惯于用一个自己喜欢的浏览器。

但是如果用户不想每次都用同一个默认App处理这样的情形怎么办呢?这时候我们可以在代码中明确地使用App选择对话框,比如党我们的App执行一个action为ACTION_SEND的分享功能时,我们想让用户分享自己数据的代码,但是我们不确定用户想通过哪个App去分享,我们想每次都弹出App选择对话框让用户决定想通过哪个App分享,示例代码如下所示:

Intent sendIntent = new Intent(Intent.ACTION_SEND);
...
​
String title = "请选择想通过哪个App分享数据";
​
// 验证是否有App能够接收并处理sendIntent
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    // 根据sendIntent创建一个需要显示App选择对话框的intent对象
    Intent chooserIntent = Intent.createChooser(sendIntent, title);
    // 我们使用chooserIntent作为startActivity()方法的参数,而非sendIntent
    startActivity(chooserIntent);
}

First we created our original sendIntent and set action and other related information on it, then we passed sendIntent to the Intent.createChooser() method to create another chooserIntent. Later, we judge whether there is an app in the system that can receive and process sendIntent by calling the Intent.resolveActivity(PackageManager) method, which is equivalent to the resolveActivity() method of the PackageManager mentioned above. Finally, we use chooserIntent as the parameter of the startActivity() method instead of sendIntent. The chooserIntent will force the Android system to display the interface where the user chooses the App to process the Intent.

Guess you like

Origin blog.csdn.net/fry3309/article/details/125281469