初识Android(二):Intent的使用,在Activity中穿梭

2024-03-23 07:08

本文主要是介绍初识Android(二):Intent的使用,在Activity中穿梭,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用Intent的目的:启动器点击图标只会进入程序的主Activity,如何进入其他的Activity,实现不同Activity之间的交互。使用intent来实现。

Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前空前要执行的动作,还可以在不同组件之间传递数据。

Intent一般可用于启动Activity、启动Service、发送广播等场景。

Intent大致分为两种:显式Intent、隐式Intent

1、使用显式Intent

第一步肯定要创建新的一个Activity,并给新的Activity一个新的layout布局。

Intent有多个构造函数的重载,其中一个是

Intent(Context packageContext, Class<?> cls)

第一个参数Context:要求提供一个启动Activity的上下文。

第二个参数Class:指定我们想要启动的目标Activity。

使用Intent:Activity类提供了startActivity()方法,专门用于启动Intent,它接收一个intent参数。

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

class FirstActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.first_layout)button1.setOnClickListener {Toast.makeText(this,"You clicked Button1",Toast.LENGTH_SHORT).show()val intent = Intent(this, SecondActivity::class.java)startActivity(intent)}}
}

第一个参数传入了this,即FirstActivity作为上下文。第二个参数传入SecondActivity::class.java,即打开SecondActivity。使用这种方式,意图很明显,称为显式Intent。

2、使用隐式Intent

隐式Intent不明确指明要启动哪一个Activity,二十指定一系列的 action 和 category等信息,由系统自动去分析这个Activity,并帮助我们找到合适的Activity去启动。

在AndroidManifest.xml中的SecondActivity中添加如下代码:

        <activityandroid:name=".SecondActivity"android:exported="false"android:label="This is the second Activity"><intent-filter><action android:name="com.example.activitytest.ACTION_START"/><category android:name="android.intent.category.DEFAULT"/></intent-filter></activity>

在<action>标签中我们指定了当前Activity可以相应com.example.activitytest.ACTION_START这个action。

在<category>中指明了当前Activity能够相应的Intent中可能带有的category。

只有<action>和<category>同时匹配Intent中的action和category时,这个Activity才能响应这个Intent。

在按钮点击事件中添加代码:

        button1.setOnClickListener {Toast.makeText(this,"You clicked Button1",Toast.LENGTH_SHORT).show()val intent = Intent("com.example.activitytest.ACTION_START")startActivity(intent)}

这是Intent的另一个构造函数,直接输入了action的字符串,就可以响应SecondActivity。

能启动SecondActivity的原因,是因为SecondActivity的category标签使用的是默认值DEFAULT。在调用 startActivity()时,会自动传入 默认的category。

每一个Intent只能传入一个 action ,但是可以指定多个 category 。当我们在点击事件中的Intent中再添加一个category,程序会崩溃,找不到这个Activity。

        button1.setOnClickListener {Toast.makeText(this,"You clicked Button1",Toast.LENGTH_SHORT).show()val intent = Intent("com.example.activitytest.ACTION_START")intent.addCategory("com.example.activitytest.MY_CATEGORY")startActivity(intent)}

程序会崩溃,查看错误日志(logcat中的error日志),可发现由于系统无法找到对应的Intent!!!

 解决办法:

在SecondActivity的<category>添加上缺少的category即可。

        <activityandroid:name=".SecondActivity"android:exported="false"android:label="This is the second Activity"><intent-filter><action android:name="com.example.activitytest.ACTION_START"/><category android:name="android.intent.category.DEFAULT"/><category android:name="com.example.activitytest.MY_CATEGORY"/></intent-filter></activity>

3、更多隐式Intent用法

        隐式Intent不仅能够打开自己的Activity,还可以启动其他程序的Activity,从而实现不同应用程序之间的交互。

        可以通过按钮点击事件,使用隐式intent打开一个网址,具体代码如下:

        button1.setOnClickListener {Toast.makeText(this,"You clicked Button1",Toast.LENGTH_SHORT).show()val intent = Intent(Intent.ACTION_VIEW)intent.data = Uri.parse("https://www.csdn.net/")startActivity(intent)}

首先、通过指定Intent的action是Intent.ACTION_VIEW,这是Android内置的一个动作,其常量值为android.intent.action.VIEW

然后、通过Uri.parse(),将一个网址字符串解析成一个Uri对象。再通过Intent的setData() 方法,将uri对象传递进入Intent对象。这里的 intent.data 是语法糖。系统内部自动调用setData方法。

setData()方法:这个方法其实并不复杂,它接收一个Uri对象,主要用于指定当前Intent正在操作的数据,而这些数据通常是以字符串形式传入Uri.parse()方法中解析产生的。

可以在<intent-filter>中添加<data>标签,用于当前Activity能更精确的响应对应的数据。<data>标签包含以下配置:

android:scheme。用于指定数据的协议部分,如上例中的https部分。
android:host。用于指定数据的主机名部分,如上例中的www.baidu.com部分。
android:port。用于指定数据的端口部分,一般紧随在主机名之后。
android:path。用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内
容。
android:mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

只有当<data>标签中指定的内容和Intent中的内容完全一致时,此Activity才能响应该Intent。

例子:

创建一个新的ThirdActivity,并创建一个新的third_layout,代码如下:

<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=".ThirdActivity"><Buttonandroid:id="@+id/button3"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Button 3"/></LinearLayout>

在AndroidManiTest.xml中进行注册:

        <activityandroid:name=".ThirdActivity"android:exported="true" ><intent-filter tools:ignore="AppLinkUrlError"><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="https" /></intent-filter></activity>

补充:这里的android:exported 此元素是设置当前Activity是否可以由其他应用程序启动:

设置为true:则任何应用都可以访问该Activity,并且可以通过其确切的类名启动。即允许不同进程间进行通信。

设置为false:则Activity只能由相同应用程序的组件、具有相同用户 ID 的应用程序或特权系统组件启动。这是没有意图过滤器时的默认值。

当mainActivity中有<intent-filter>标签时,应该设置android:exported为true,否则会报错。

 因为我们对ThirdActivity也赋予了相应的<intent-filter>并且它的action也为android.intent.action.VIEW,响应的data也为https,因此当点击按钮时,会默认弹出一个列表,可供选择,进入网页还是进入新的ThirdActivity。

除了,调用https协议之外,还可以调用很多其他协议,例如 geo 表示地理位置,tel 表示拨打电话

通过按钮进行电话拨打的代码如下:

        button1.setOnClickListener {Toast.makeText(this,"You clicked Button1",Toast.LENGTH_SHORT).show()val intent = Intent(Intent.ACTION_DIAL)intent.data = Uri.parse("tel:10086")startActivity(intent)}

设置Intent的action为Intent.ACTION_DIAL,然后再data部分调用Uri.parse(),协议为tel.

其它的类似。

4、向下一个Activity传递数据

Intent不仅可以用来打开其它的Activity,还可以用来进行数据传输。

传输方法很简单,Intent提供了一系列的 putExtra() 方法重载,可以把想要传输的数据暂时封存到Intent中,启动新的Activity后,再从Intent中取出。

打开Activity 时,先将strData存放在了intent中,代码如下:

        button1.setOnClickListener {val strData = "Message"val intent = Intent(this, SecondActivity::class.java)intent.putExtra("extra_name", strData)startActivity(intent)}

取出代码如下,需要在SecondActivity 的 onCreate() 函数中自行取出,代码如下:

class SecondActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.second_layout)val extraData = intent.getStringExtra("extra_data")Log.d("SecondActivity","extra data is $extraData")}
}

代码中的intent实际上是调用父类的getIntent()方法,从而来获得启动SecondActivity 的intent。然后调用getStringExtra()方法并传入相应的键值,就可以得到传递的数据了。这里由于我们传递的是字符串,所以使用getStringExtra()方法来获取传递的数据。如果传递的是整型数据,则使用getIntExtra()方法;如果传递的是布尔型数据,则使用getBooleanExtra()方法,以此类推。

5、向上一个Activity传递数据

由于返回上一个Activity,仅需back即可。没有专门的Intent,并不能像向下传递消息一样。

Activity类提供了一个启动Activity的 startActivityForResult() 方法

button1.setOnClickListener {val intent = Intent(this, SecondActivity::class.java)startActivityForResult(intent, 1)
}

接下来在SecondActivity中添加点击事件:

        button2.setOnClickListener {val intent = Intent()intent.putExtra("data_return", "Hello FirstActivity")setResult(RESULT_OK, intent)finish()}

着同样创建了一个intent,并没有意图,仅用来进行数据传输。

紧接着把要传递的数据存放在Intent中,然后调用了setResult()方法。这个方法非常重要,专门用于向上一个Activity返回数据。

setResult()方法接收两个参数:

第一个参数用于向上一个Activity返回处理结果,一般只使用RESULT_OK或RESULT_CANCELED这两个值;

第二个参数则把带有数据的Intent传递回去。最后调用了finish()方法来销毁当前Activity。

Tips:当前返回数据是通过SecondActivity中的按钮来返回,但是一般返回上一Activity直接使用back,因此需要另一种写法:

由于我们是使用startActivityForResult()方法来启动SecondActivity的,在SecondActivity被销毁之后会回调上一个Activity的onActivityResult()方法,因此我们需要在FirstActivity中重写这个方法来得到返回的数据,如下所示:

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when (requestCode) {1 -> if (resultCode == RESULT_OK) {val returnedData = data?.getStringExtra("data_return")Log.d("FirstActivity", "returned data is $returnedData")}}}

onActivityResult()方法带有3个参数:第一个参数requestCode,即我们在启动Activity时传入的请求码;第二个参数resultCode,即我们在返回数据时传入的处理结果;第三个参数data,即携带着返回数据的Intent。由于在一个Activity中有可能调用startActivityForResult()方法去启动很多不同的Activity,每一个Activity返回的数据都会回调到onActivityResult()这个方法中,因此我们首先要做的就是通过检查requestCode的值来判断数据来源。确定数据是从SecondActivity返回的之后,我们再通过resultCode的值来判断处理结果是否成功。最后从data中取值并打印出来,这样就完成了向
上一个Activity返回数据的工作。

但是目前版本已经被Google淘汰,需要使用更新的  Activity Result API,用法如下:

参考Activity Result API详解,是时候放弃startActivityForResult了_guolin的博客-CSDN博客_startactivityforresult废弃如果你将项目中的appcompat库升级到1.3.0或更高的版本,你会发现startActivityForResult()方法已经被废弃了。这个方法相信所有做过Android的开发者都用过,它主要是用于在两个Activity之间交换数据的。那么为什么这个如此常用的方法会被废弃呢?官方给出的说法是,现在更加建议使用Activity Result API来实现在两个Activity之间交换数据的功能。我个人的观点是,startActivityForResult()方法并没有什么致命的问题,只是https://guolin.blog.csdn.net/article/details/121063078?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3.pc_relevant_aa&utm_relevant_index=6

    private val requestDataLauncher =registerForActivityResult(ActivityResultContracts.StartActivityForResult()){if (it.resultCode == RESULT_OK) {val returnData = it.data?.getStringExtra("data_return")Log.d("FirstActivity","data return is $returnData")}}

通过  registerForActivityResult()  来注册对Activity的结果的监听。

registerForActivityResult()方法接收两个参数:

第一个参数是一种Contract类型,由于我们是希望从另外一个Activity中请求数据,因此这里使用了StartActivityForResult。

第二个参数是一个Lambda表达式,当有结果返回时则会回调到这里,然后我们在这里获取并处理数据即可。
 

这篇关于初识Android(二):Intent的使用,在Activity中穿梭的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/837520

相关文章

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud