会变色的我 發表於 2025-11-1 14:09:58

Android Intent详解(最新推荐)

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、Intent 核心作用</li><li>二、Intent 类型</li><ul class="second_class_ul"><li>1. 显式 Intent(Explicit Intent)</li><li>2. 隐式 Intent(Implicit Intent)</li></ul><li>三、Intent 核心属性</li><ul class="second_class_ul"><li>1. Action(动作)</li><li>2. Category(类别)</li><li>3. Data 与 Type(数据与类型)</li><li>4. Extra(附加数据)</li><li>5. Flag(标记)</li></ul><li>四、Intent 过滤器(Intent Filter)</li><ul class="second_class_ul"><li>过滤器匹配规则</li><li>示例:为Activity配置过滤器</li></ul><li>五、特殊用法</li><ul class="second_class_ul"><li>1. 启动组件并获取返回结果</li><li>2. PendingIntent(延迟Intent)</li><li>3. 发送广播 Intent</li></ul><li>六、注意事项</li><ul class="second_class_ul"></ul><li>总结</li><ul class="second_class_ul"></ul></ul></div><p>在Android开发中,<code>Intent</code> 是组件间通信的核心机制,用于在Activity、Service、BroadcastReceiver等组件之间传递消息、启动组件或共享数据。它相当于一个&ldquo;意图&rdquo;载体,描述了操作的目的、数据和附加信息,是Android组件解耦的关键。</p>
<p class="maodian"></p><h2>一、Intent 核心作用</h2>
<ul><li><strong>启动组件</strong>:启动Activity(<code>startActivity()</code>)、启动Service(<code>startService()</code>/<code>bindService()</code>)、发送广播(<code>sendBroadcast()</code>)。</li><li><strong>传递数据</strong>:在组件间传递基本类型、对象、集合等数据。</li><li><strong>指定操作</strong>:通过&ldquo;动作&rdquo;&ldquo;数据&rdquo;等描述要执行的操作(如&ldquo;打开网页&rdquo;&ldquo;发送邮件&rdquo;),实现跨应用交互。</li></ul>
<p class="maodian"></p><h2>二、Intent 类型</h2>
<p>根据目标组件的指定方式,Intent分为<strong>显式Intent</strong>和<strong>隐式Intent</strong>,适用场景不同。</p>
<p class="maodian"></p><h3>1. 显式 Intent(Explicit Intent)</h3>
<p><strong>特点</strong>:直接指定目标组件的完整类名(<code>ComponentName</code>),明确告诉系统要启动哪个组件。<br /><strong>适用场景</strong>:启动<strong>应用内部组件</strong>(如本应用的Activity、Service),因为开发者明确知道目标组件的类名。</p>
<p><strong>示例:启动应用内的SecondActivity</strong></p>
<div class="jb51code"><pre class="brush:java;">// Kotlin
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)</pre></div>
<div class="jb51code"><pre class="brush:java;">// Java
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);</pre></div>
<p><strong>进阶:通过ComponentName指定</strong><br />如需动态指定组件(如跨进程启动已知类名的组件),可通过<code>ComponentName</code>构造:</p>
<div class="jb51code"><pre class="brush:java;">val component = ComponentName(packageName, "com.example.app.SecondActivity")
val intent = Intent().setComponent(component)
startActivity(intent)</pre></div>
<p class="maodian"></p><h3>2. 隐式 Intent(Implicit Intent)</h3>
<p><strong>特点</strong>:不直接指定目标组件,而是通过&ldquo;动作(Action)&rdquo;&ldquo;类别(Category)&rdquo;&ldquo;数据(Data)&rdquo;等描述操作意图,由系统根据这些信息匹配最合适的组件(如系统浏览器、邮件应用)。<br /><strong>适用场景</strong>:启动<strong>跨应用组件</strong>(如调用系统浏览器打开网页、调用相机拍照),无需知道目标组件的类名。</p>
<p><strong>示例:打开指定网页(调用系统浏览器)</strong></p>
<div class="jb51code"><pre class="brush:java;">val intent = Intent(Intent.ACTION_VIEW) // 动作:查看内容
intent.data = Uri.parse("https://www.example.com") // 数据:网页地址
startActivity(intent)</pre></div>
<p>系统会匹配所有声明了<code>ACTION_VIEW</code>且支持<code>http</code>协议的组件(通常是浏览器),并让用户选择打开方式。</p>
<p class="maodian"></p><h2>三、Intent 核心属性</h2>
<p>Intent通过一系列属性描述操作意图,核心属性包括<code>Action</code>、<code>Category</code>、<code>Data</code>、<code>Type</code>、<code>Extra</code>、<code>Flag</code>等。</p>
<p class="maodian"></p><h3>1. Action(动作)</h3>
<p>一个字符串,描述要执行的操作(如&ldquo;查看&rdquo;&ldquo;发送&rdquo;&ldquo;编辑&rdquo;)。系统预定义了大量Action,也可自定义。</p>
<p><strong>常用系统Action</strong>:</p>
<table><thead><tr><th>Action常量</th><th>含义</th><th>适用场景</th></tr></thead><tbody><tr><td><code>Intent.ACTION_VIEW</code></td><td>查看数据</td><td>打开网页、图片、文档等</td></tr><tr><td><code>Intent.ACTION_SEND</code></td><td>发送数据</td><td>分享文本、图片(调用分享面板)</td></tr><tr><td><code>Intent.ACTION_CALL</code></td><td>拨打电话</td><td>需要<code>CALL_PHONE</code>权限</td></tr><tr><td><code>Intent.ACTION_EDIT</code></td><td>编辑数据</td><td>编辑联系人、图片等</td></tr><tr><td><code>Intent.ACTION_MAIN</code></td><td>应用入口</td><td>launcher启动应用的主Activity</td></tr></tbody></table>
<p><strong>自定义Action</strong>:<br />需使用全限定名(避免冲突),如<code>com.example.app.ACTION_CUSTOM</code>,用于应用内组件通信或跨应用约定。</p>
<p class="maodian"></p><h3>2. Category(类别)</h3>
<p>对Action的补充,描述组件的额外特性(如&ldquo;默认组件&rdquo;&ldquo; launcher入口&rdquo;)。一个Intent可包含多个Category,系统会匹配所有声明的类别。</p>
<p><strong>常用系统Category</strong>:</p>
<ul><li><code>Intent.CATEGORY_DEFAULT</code>:默认类别,隐式启动Activity时<strong>必须包含</strong>(否则匹配失败)。</li><li><code>Intent.CATEGORY_LAUNCHER</code>:标记应用的主入口(与<code>ACTION_MAIN</code>配合,显示在 launcher 上)。</li></ul>
<p><strong>示例</strong>:隐式启动时添加默认类别</p>
<div class="jb51code"><pre class="brush:java;">val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("https://www.example.com")
intent.addCategory(Intent.CATEGORY_DEFAULT) // 必须添加,否则可能匹配失败
startActivity(intent)</pre></div>
<p class="maodian"></p><h3>3. Data 与 Type(数据与类型)</h3>
<ul><li><code>Data</code>:通过<code>Uri</code>指定操作的数据(如<code>content://contacts/people/1</code>表示某个联系人,<code>http://example.com</code>表示网页)。</li><li><code>Type</code>:指定数据的MIME类型(如<code>image/jpeg</code>、<code>text/plain</code>),若<code>Data</code>已包含类型信息(如<code>http</code>对应<code>text/html</code>),<code>Type</code>可省略。</li></ul>
<p><strong>注意</strong>:<code>Data</code>和<code>Type</code>会相互覆盖,若需同时设置,需用<code>setDataAndType()</code>而非分别调用<code>setData()</code>和<code>setType()</code>:</p>
<div class="jb51code"><pre class="brush:java;">// 正确:同时设置Data和Type
intent.setDataAndType(Uri.parse("content://media/external/images/1"), "image/jpeg")
// 错误:setType()会覆盖Data的类型信息
intent.data = Uri.parse("content://media/external/images/1")
intent.type = "image/jpeg" // 此操作会清除data</pre></div>
<p class="maodian"></p><h3>4. Extra(附加数据)</h3>
<p>键值对形式的附加数据,用于在组件间传递数据(如传递用户ID、文本内容)。支持基本类型、数组、集合,以及实现<code>Serializable</code>或<code>Parcelable</code>的对象。</p>
<p><strong>存储与获取数据</strong>:</p>
<div class="jb51code"><pre class="brush:java;">// 存储数据
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("userId", 123) // 基本类型
intent.putExtra("username", "张三") // 字符串
intent.putExtra("isVip", true) // 布尔值
// 传递对象(需实现Parcelable或Serializable)
val user = User("张三", 20) // 假设User实现了Parcelable
intent.putExtra("user", user)
startActivity(intent)</pre></div>
<div class="jb51code"><pre class="brush:java;">// 目标组件中获取数据
val userId = intent.getIntExtra("userId", -1) // 第二个参数为默认值
val username = intent.getStringExtra("username") // 可为null
val isVip = intent.getBooleanExtra("isVip", false)
val user = intent.getParcelableExtra&lt;User&gt;("user") // 需指定泛型</pre></div>
<p><strong>注意</strong>:</p>
<ul><li>传递大量数据(如大图片)可能导致<code>TransactionTooLargeException</code>,建议用其他方式(如全局变量、文件)。</li><li><code>Parcelable</code>比<code>Serializable</code>效率更高(Android推荐用<code>Parcelable</code>)。</li></ul>
<p class="maodian"></p><h3>5. Flag(标记)</h3>
<p>通过<code>addFlags()</code>设置,用于控制组件的启动模式、任务栈(Task)行为等。</p>
<p><strong>常用Flag</strong>:</p>
<table><thead><tr><th>Flag</th><th>作用</th></tr></thead><tbody><tr><td><code>Intent.FLAG_ACTIVITY_NEW_TASK</code></td><td>启动新任务栈(常用于Service中启动Activity)</td></tr><tr><td><code>Intent.FLAG_ACTIVITY_CLEAR_TOP</code></td><td>若目标Activity已在栈中,清除其上方所有Activity</td></tr><tr><td><code>Intent.FLAG_ACTIVITY_SINGLE_TOP</code></td><td>若目标Activity在栈顶,则复用,不创建新实例</td></tr><tr><td><code>Intent.FLAG_GRANT_READ_URI_PERMISSION</code></td><td>授予Uri的读权限(跨应用访问文件时需用)</td></tr></tbody></table>
<p><strong>示例</strong>:启动新任务栈中的Activity(如从Service启动)</p>
<div class="jb51code"><pre class="brush:java;">val intent = Intent(this, NotificationActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // 必须添加,否则Service中启动会崩溃
startActivity(intent)</pre></div>
<p class="maodian"></p><h2>四、Intent 过滤器(Intent Filter)</h2>
<p>隐式Intent需要通过<strong>Intent过滤器</strong>匹配目标组件。过滤器在<code>AndroidManifest.xml</code>中声明,用于告诉系统&ldquo;该组件能处理哪些Intent&rdquo;。</p>
<p>一个组件可声明多个过滤器,只要Intent匹配其中一个即可启动该组件。</p>
<p class="maodian"></p><h3>过滤器匹配规则</h3>
<p>Intent与过滤器的匹配需满足<strong>3个条件</strong>(全部匹配):</p>
<ol><li><strong>Action匹配</strong>:Intent的Action必须在过滤器的<code>action</code>列表中(或过滤器无Action,Intent也无Action)。</li><li><strong>Category匹配</strong>:Intent的所有Category必须在过滤器的<code>category</code>列表中(过滤器至少包含<code>CATEGORY_DEFAULT</code>,否则隐式启动失败)。</li><li><strong>Data/Type匹配</strong>:Intent的Data/Type需与过滤器的<code>data</code>规则匹配(如协议、MIME类型)。</li></ol>
<p class="maodian"></p><h3>示例:为Activity配置过滤器</h3>
<p>声明一个能处理&ldquo;查看图片&rdquo;和&ldquo;编辑图片&rdquo;的Activity:</p>
<div class="jb51code"><pre class="brush:java;">&lt;activity android:name=".ImageHandlerActivity"&gt;
    &lt;intent-filter&gt;
      &lt;!-- Action:支持查看和编辑图片 --&gt;
      &lt;action android:name="android.intent.action.VIEW" /&gt;
      &lt;action android:name="android.intent.action.EDIT" /&gt;
      &lt;!-- Category:必须包含默认类别 --&gt;
      &lt;category android:name="android.intent.category.DEFAULT" /&gt;
      &lt;!-- Data:支持图片类型(image/*),协议不限 --&gt;
      &lt;data android:mimeType="image/*" /&gt;
    &lt;/intent-filter&gt;
&lt;/activity&gt;</pre></div>
<p>当其他应用发送包含<code>ACTION_VIEW</code>、<code>CATEGORY_DEFAULT</code>、<code>image/jpeg</code>类型的Intent时,系统会将该Activity列为可选目标。</p>
<p class="maodian"></p><h2>五、特殊用法</h2>
<p class="maodian"></p><h3>1. 启动组件并获取返回结果</h3>
<p>通过<code>Activity Result API</code>(替代旧版<code>startActivityForResult()</code>)启动Activity并获取返回数据。</p>
<p><strong>示例</strong>:启动相机拍照并获取照片</p>
<div class="jb51code"><pre class="brush:java;">// 1. 注册结果回调
val takePictureLauncher = registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess -&gt;
    if (isSuccess) {
      // 拍照成功,处理照片(photoUri为拍照后保存的路径)
      imageView.setImageURI(photoUri)
    }
}
// 2. 启动相机(photoUri为提前创建的临时文件路径)
val photoUri = createTempPhotoUri() // 自定义方法:创建保存照片的Uri
takePictureLauncher.launch(photoUri)</pre></div>
<p class="maodian"></p><h3>2. PendingIntent(延迟Intent)</h3>
<p>一种特殊的Intent,用于在<strong>未来某个时刻</strong>由其他组件(如系统服务)执行。常用于通知(Notification)、闹钟(AlarmManager)、快捷方式等场景。</p>
<p><strong>特点</strong>:</p>
<ul><li>包含触发时的权限和上下文,即使创建它的应用已退出,仍可正常执行。</li><li>支持三种操作:启动Activity(<code>getActivity()</code>)、启动Service(<code>getService()</code>)、发送广播(<code>getBroadcast()</code>)。</li></ul>
<p><strong>示例:通知中添加PendingIntent(点击通知打开Activity)</strong></p>
<div class="jb51code"><pre class="brush:java;">// 创建打开DetailActivity的Intent
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("id", 100)
// 创建PendingIntent(FLAG_IMMUTABLE:不可变,安全性更高)
val pendingIntent = PendingIntent.getActivity(
    this,
    0, // 请求码(区分不同PendingIntent)
    intent,
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
// 构建通知
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("新消息")
    .setContentText("点击查看详情")
    .setSmallIcon(R.drawable.ic_notification)
    .setContentIntent(pendingIntent) // 绑定PendingIntent
    .build()
// 显示通知
notificationManager.notify(NOTIFICATION_ID, notification)</pre></div>
<p class="maodian"></p><h3>3. 发送广播 Intent</h3>
<p>通过<code>sendBroadcast()</code>发送广播,由注册了对应过滤器的<code>BroadcastReceiver</code>接收。</p>
<p><strong>示例:发送自定义广播</strong></p>
<div class="jb51code"><pre class="brush:java;">// 发送广播
val intent = Intent("com.example.app.ACTION_CUSTOM_BROADCAST")
// 限制广播仅本应用接收(Android 8.0+ 推荐)
intent.setPackage(packageName)
sendBroadcast(intent)</pre></div>
<div class="jb51code"><pre class="brush:java;">&lt;!-- 注册广播接收器(Manifest中) --&gt;
&lt;receiver android:name=".MyReceiver"&gt;
    &lt;intent-filter&gt;
      &lt;action android:name="com.example.app.ACTION_CUSTOM_BROADCAST" /&gt;
    &lt;/intent-filter&gt;
&lt;/receiver&gt;
</pre></div>
<div class="jb51code"><pre class="brush:java;">// 广播接收器实现
class MyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
      if ("com.example.app.ACTION_CUSTOM_BROADCAST" == intent.action) {
            // 处理广播
      }
    }
}
</pre></div>
<p class="maodian"></p><h2>六、注意事项</h2>
<p><strong>隐式Intent的安全性</strong>:Android 10(API 29)后,隐式启动Activity需指定包名(<code>setPackage()</code>)或通过<code>resolveActivity()</code>检查是否有匹配组件,否则可能抛出异常:</p>
<div class="jb51code"><pre class="brush:java;">val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com"))
if (intent.resolveActivity(packageManager) != null) { // 检查是否有匹配组件
    startActivity(intent)
} else {
    // 提示用户无可用应用
}</pre></div>
<ul><li><strong>数据大小限制</strong>:Intent传递数据通过Binder机制,总大小限制约<strong>1MB</strong>,超过会导致<code>TransactionTooLargeException</code>,建议用文件或跨进程通信(IPC)替代。</li><li><strong>PendingIntent的 FLAG 选择</strong>:Android 12(API 31)后,创建PendingIntent需指定<code>FLAG_IMMUTABLE</code>或<code>FLAG_MUTABLE</code>:<ul><li><code>FLAG_IMMUTABLE</code>:Intent不可修改(推荐,安全性高)。</li><li><code>FLAG_MUTABLE</code>:允许修改Intent(仅在需要动态更新Intent时使用)。</li></ul></li></ul>
<p class="maodian"></p><h2>总结</h2>
<p><code>Intent</code> 是Android组件通信的&ldquo;桥梁&rdquo;,通过显式/隐式方式连接组件,支持数据传递和操作描述。掌握其核心属性(Action、Category、Data、Extra)、过滤器匹配规则,以及特殊用法(PendingIntent、Activity Result),是实现组件交互和跨应用功能的基础。合理使用Intent能大幅提升应用的灵活性和扩展性。</p>
<p>到此这篇关于Android&nbsp;Intent详解(最新推荐)的文章就介绍到这了,更多相关Android&nbsp;Intent内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Android&nbsp;Intent基础用法及作用详解</li><li>Android面试Intent采用了什么设计模式解析</li><li>Android使用Intent传递组件大数据</li><li>android使用intent传递参数实现乘法计算</li><li>Android使用Intent显示实现页面跳转</li><li>Android使用Intent隐式实现页面跳转</li><li>Android Intent实现页面跳转的两种方法</li><li>Android Intent实现页面跳转的方法示例</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: Android Intent详解(最新推荐)