本文主要是介绍初识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中穿梭的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!