Android中Intent组件的入门学习心得
什么是 Intent ?
Intent是Android开发中一个非常重要且常用的类,Intent是一个消息传递对象,可以用来从其他应用组件请求操作,使用Intent可以在一个组件中同一APP中的另一个组件或者是启动另一个APP的组件(这里所说的组件包括Activity、Service和Broadcast)。
ctivity、service和broadcast receiver之间是通过Intent进行通信的,而另外一个组件Content Provider本身就是一种通信机制,不需要通过Intent。我们来看下面这个图就知道了:
如果Activity1需要和Activity2进行联系,二者不需要直接联系,而是通过Intent作为桥梁。通俗来讲,Intnet类似于中介、媒婆的角色。
Intent 的类型?
Intent 有两种类型,分别是 显式 Intent 和 隐式 Intent 。
显式 Intent: 通过提供目标应用的软件包名称或完全限定的组件类名来指定可处理 Intent 的应用。通常,您会在自己的应用中使用 显式 Intent 来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,您可能会启动您应用内的新 Activity 以响应用户操作,或者启动服务以在后台下载文件。
隐式 Intent: 不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理。例如,如需在地图上向用户显示位置,则可以使用 隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。使用 隐式 Intent 时,Android 系统通过将 Intent 的内容与在设备上其他应用的清单文件中声明的 Intent 过滤器 进行比较,从而找到要启动的相应组件。如果 Intent 与 Intent 过滤器匹配,则系统将启动该组件,并向其传递 Intent 对象。如果多个 Intent 过滤器兼容,则系统会显示一个对话框,支持用户选取要使用的应用。
Intent 的组成
intent由组件名称(Component name)、操作(Action)、数据(Data)、类别(Category)、额外的数据(Extra)和标志(Flag)六个部分组成。
组件名称 Component name:
组件名称是要启动的组件名称。如果使用的是 显式 Intent 则必须指定此参数,否则 Intent 无法识别要传递给哪个应用组件。不指定此参数则为 隐式 Intent ,系统将根据其他 Intent 信息决定要接受 Intent 的应用组件。如果想要启动特定的组件,则必须要指定此参数为该组件的名称。
操作 Action:
操作指定要执行的通用操作的字符串。可以自定义自己的操作,但是通常应该使用由 Intent 类或其他框架类定义的操作常量(例如 ACTION_VIEW
、ACTION_SEND
)。
数据 Data:
数据是引用待操作数据或该数据 MIME 类型的 URI 对象。提供的数据类型通常由 Intent 的操作决定。创建 Intent 时,除了指定 URI 以外,指定数据类型(其 MIME 类型)往往也很重要。
类别 Category:
类别是一个包含应处理 Intent 组件类型的附加信息的字符串。可以将任意数量的类别描述放入一个 Intent 中,但大多数 Intent 均不需要类别。以下是一些常见类别:
CATEGORY_BROWSABLE
:
目标 Activity 允许本身通过网络浏览器启动,以显示链接引用的数据,如图像或电子邮件。
CATEGORY_LAUNCHER
:
此类别描述了该 Activity 是任务的初始 Activity,当系统启动时首先启动此 Activity。
额外的数据 Extra:
携带完成请求操作所需的附加信息的键值对。正如某些操作使用特定类型的数据 URI 一样,有些操作也使用特定的 extra。
标志 Flag:
标志在 Intent 类中定义,充当 Intent 的元数据。标志可以指示 Android 系统如何启动 Activity(例如,Activity 应属于哪个任务),以及启动之后如何处理(例如,Activity 是否属于最近的 Activity 列表)。
显式 Intent 的使用
首先新建一个 Activity
以及相应的布局文件。
MyActivity
import androidx.annotation.Nullable; import android.app.Activity; import android.os.Bundle; public class MyActivity extends Activity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.myactivity); } }
myactivity.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"`在这里插入代码片` android:layout_height="match_parent" android:orientation="vertical" tools:context=".MyActivity"> <TextView android:text="这是一个新的页面" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
在清单文件 AndroidManifest.xml
中注册 MyActivity
。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication1"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApplication1"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MyActivity"/> </application> </manifest>
此处android:name
中使用 .MyActivity 是为了程序在运行时直接将该 name 添加到 package 后,这样方便程序去寻找此Activity并启动,也可以将package复制添加到 android:name 中,例如<activity android:name="com.example.myapplication1.MyActivity"/> 。
在 MainActivity 中设定一个按钮 id 为 startNew ,当按下该按钮时启动 MyActivity 。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.startNew).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startActivity(new Intent(MainActivity.this,MyActivity.class)); } }); } }
此处在 new Intent(MainActivity.this,MyActivity.class)
中指明了要启动的 Activity 的名称,所以为显式 Intent 。
运行效果:
隐式 Intent 的使用
首先在清单文件 AndroidManifest
中修改 MyAcitivity
的相关定义。
<activity android:name=".MyActivity" android:exported="true"> <intent-filter> //为此intent定义一个新的action名称 <action android:name="NewAction"/> //若指定category为DEFAULT,则指明此intent的行为方式是Activity <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
修改 MainActivity
,将原本的显式 Intent 启动方式改为隐式 Intent ,即通过自定义的 action 名称来启动相对应的 Activity 。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.startNew).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //此处使用NewAction调用MyActivity startActivity(new Intent("NewAction")); } }); } }
这样就成功通过隐式 Intent 启动 MyActivity 。
通常建议将 定义为 “包.intent.action.组件名” 。可以通过在组件中定义静态变量来更加方便地访问该组件。例如,public static final String ACTION = "com.example.myapplication1.intent.action.MyActivity";
调用时直接使用 MyActivity.ACTION 即可。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.startNew).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //此处使用NewAction调用 startActivity(new Intent(MyActivity.ACTION)); } }); } }
运行效果与显式 Intent 相同。
通过隐式 Intent ,组件可以对不同APP之间的组件进行访问。如果想让本应用的组件可以被其他的应用进行访问,则需要对 activity 标签加上一个属性 android:exported ,当 android:exported 为 true 时,本组件可以被其他应用组件访问,为 false 时则不可被其他应用访问,并弹出异常警告。可以在启动其他应用组件时加上异常捕获语句,例如,
public void onClick(View view) { try { startActivity(new Intent(MyActivity.ACTION)); }catch (Exception e){ Toast.makeText(MainActivity.this,"无法启动指定的Activity",Toast.LENGTH_SHORT).show(); } }
本文大部分参考了Android中对Intent部分的描述,希望本文对大家更好地使用Intent对象有所帮助。
总结
上一篇:Handler实现线程之间的通信下载文件动态更新进度条
栏 目:Android代码
下一篇:浅谈Android Studio 3.0 的一些小变化
本文地址:http://www.codeinn.net/misctech/197445.html