【达内课程】Android中Intent使用详解

编程入门 行业动态 更新时间:2024-10-09 21:27:13

【达内课程】Android中Intent使用<a href=https://www.elefans.com/category/jswz/34/1770044.html style=详解"/>

【达内课程】Android中Intent使用详解

文章目录

  • Intent在Android系统的作用
    • 传值
    • 激活系统组件
  • Intent属性
    • ComponentName
    • Action :动作 和 Category:分类
    • Data
    • Type
    • Extras
    • Flag:标识
  • IntentFilter 意图过滤器
  • Intent和Bundle传值的区别

Intent在Android系统的作用

Intent在Android系统的作用

  1. 激活系统组件,例如startActivity(Intent),startService(Intent)
  2. 在系统组件之间传递数据

传值

1、传递普通数据

两个Activity之间数据传递,从 MainActivity 跳转到 SecondActivity,同时传递数据

栗子:传值
activity_main

<LinearLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.siliconvalley.xy.sms.MainActivity"android:padding="15dp"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="请输入用户名" /><EditTextandroid:id="@+id/et_username"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="请选择性别" /><RadioGroupandroid:id="@+id/rg_male"android:layout_width="match_parent"android:layout_height="wrap_content"><RadioButtonandroid:id="@+id/rb_male"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="男" /><RadioButtonandroid:id="@+id/rb_female"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="女" /></RadioGroup><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="请输入年龄" /><EditTextandroid:id="@+id/et_age"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="number"/><Buttonandroid:id="@+id/btn_submit"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="提交"/></LinearLayout>

MainActivity

public class MainActivity extends Activity implements View.OnClickListener {private EditText etUserName;private RadioButton rbGenderMale;private EditText etAge;private Button btnSubmit;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);etUserName = (EditText) findViewById(R.id.et_username);rbGenderMale = (RadioButton) findViewById(R.id.rb_male);etAge = (EditText) findViewById(R.id.et_age);btnSubmit = (Button) findViewById(R.id.btn_submit);btnSubmit.setOnClickListener(this);}@Overridepublic void onClick(View v) {String username = etUserName.getText().toString().trim();String gender = rbGenderMale.isChecked()?"男":"女";int age = Integer.parseInt(etAge.getText().toString());Intent intent = new Intent(this,SecondActivity.class);intent.putExtra("_username",username);intent.putExtra("_gender",gender);intent.putExtra("_age",age);startActivity(intent);}
}

SecondActivity

public class SecondActivity extends Activity {private Button btnStart;private Button btnStop;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);Intent intent = getIntent();String u = intent.getStringExtra("_username");String g = intent.getStringExtra("_gender");int a = intent.getIntExtra("_age",0);Log.d("Intent","姓名:"+u+" 性别:"+g+" 年龄:"+a);}
}

Log

姓名:Lily 性别:女 年龄:11

注意:存和取一定要保持类型的一致,存入什么类型,取出的时候一定是什么类型

2、传递Parcelable和Serializable数据
具体请戳另一篇文章:Parcelable和Serializable

激活系统组件

使用 Intent 隐式的激活系统组件

在使用 Intent 激活系统组件时,使用 new Intent(this,SecondActivity.class)类似的语法中,明显的指定了被激活的组件的 Java 类,称之为“显式”的激活组件。

在 Android 系统中还支持隐式的激活系统组件,即在不知道被激活的组件的 Java 类时,可以通过设置 Intent 对象的 Action 属性来激活系统组件。显式的激活方式,只能激活当前应用中的系统组件。

栗子1:拨打电话

        Intent intent = new Intent();intent.setAction(Intent.ACTION_DIAL);//或者//intent.setAction(Intent.ACTION_VIEW);intent.setData(Uri.parse("tel:10086"));startActivity(intent);

直接呼叫

直接运行程序会报错,因为拨打电话是敏感操作可能产生费用,所以需要权限

在AndroidManifest.xml中增加权限

    <uses-permission android:name="android.permission.CALL_PHONE"/>

如果指定的 action 是 Intent.ACTION_DIAL,表示打开拨号界面,是不需要声明权限的。这里指定的是 Intent.ACTION_CALL,表示直接拨打电话,因此必须声明权限

栗子2:打开网页

			Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse(""));startActivity(intent);

栗子3:调用系统界面,给指定的号码发送短信,并附带短信内容

Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:13333333333"));
intent.putExtra("sms_body","TD");
startActivity(intent);

Intent属性

ComponentName

明确指定 Intent 将要启动哪个组件,因此这种 Intent 被称为显示Intent
没有指定ComponentName 属性的Intent被称为隐式 Intent。隐式 Intent 没有明确要启动哪个组件,应用会根据 Intent 指定的规则去启动符合条件的组件
ComponentName 不仅可以启动本程序中的activity,还可以启动其它程序的activity

可用语法如下:

这样是创建了1个 ComponentName 对象

Intent intent = new Intent(this,SecondActivity.class);
Intent intent = new Intent();
intent.setClass(this,SecondActivity.class);

或者通过字符串传入,但是必须传入完整包名,而上面的语法会自动导入包名,所以不用写

Intent intent = new Intent();
intent.setClassName(this,"包名.SecondActivity");
intent.setClassName("包名","包名.SecondActivity");

或者我们可以自己创建 ComponentName 对象

ComponentName componentName1 = new ComponentName(this,MainActivity.class);
intent.setComponent(componentName1);
ComponentName componentName2 = new ComponentName(this,"包名.MainActivity");
intent.setComponent(componentName2);
ComponentName componentName3 = new ComponentName("包名","包名.MainActivity");
intent.setComponent(componentName3);

Action :动作 和 Category:分类

通常,Action 和 Category 属性结合使用。定义这两个属性都是在主配置文件的 <intent-filter>节点中。Intent 通过定义 Action 属性(其实就是定义一段自定义的字符串),这样就可以把Intent 与具体的某个Activity 分离,实现了解耦

例如 我们在 AndroidManifest.xml 中配置如下

<activityandroid:name=".Main2Activity"android:label="标题" ><intent-filter><category android:name="android.intent.category.DEFAULT" /><action android:name="com.test.Main2Activity" /></intent-filter></activity>

然后就可以这样打开 Main2Activity 了

	Intent intent = new Intent("com.test.Main2Activity");startActivity(intent);

通过Intent类的构造方法可以设置 Intent(String) 对象的Action属性,也可以通过 Intent 对象的 setAction(String) 进行设置,所以也可以写成

				Intent intent = new Intent();intent.setAction("com.test.Main2Activity");startActivity(intent);

Action 需要注意的是
1、当我们有多个 Activity 配置了相同的 action 的时候,那么系统会弹出来一个选择框,让我们自己选择要启动那个 Activity
2、如果某个 Intent 对象,既指定了 ComponentName,又指定了 Action,则激活 ComponentName 指定的组件
3、通过 Intent 对象的getAction()方法可以获取 Action 属性值

action 我们只能添加一个,但是 category 却可以添加多个(至少有一个,没有就要设置为DEFAULT),Category用于与 IntentFilter 匹配,Intent 对象中的 Category 属性可以通过 Intent 对象的 addCategory()方法增加。每个 Intent 对象用于激活系统组件时,会默认添加值为android.intent.category.DEFAULT这样的 category

所以刚才的栗子中,默认的代码是

				Intent intent = new Intent();intent.setAction("com.test.Main2Activity");intent.addCategory("android.intent.category.DEFAULT");startActivity(intent);

Data

Data 属性的值是 Uri 类型的,这种类型的数据可以通过 Uri.parse(String) 将字符串转换得到

Data 属性通常伴随着 Action 属性一起出现,即使用了 Action 属性后,可能就需要用到 Data 属性

通过设置 data,我们可以执行打电话,发短信,开发网页等等操作(看上面的栗子1、2)。究竟做哪种操作,要看我们的数据格式:当我们的 data 是一个 http 协议的时候,系统会自动去查找可以打开 http 协议的 Activity,这个时候如果手机安装了多个浏览器,那么系统会弹出多个浏览器供我们选择

同时,我们也可以通过设置一个 Data 属性来将我们的Activity发布出去供别人调用,怎么发布呢?


AndroidManifest.xml 中<activityandroid:name=".Main2Activity"android:label="标题" ><intent-filter><category android:name="android.intent.category.DEFAULT" /><action android:name="com.test.Main2Activity" /><data android:scheme="tel" /></intent-filter></activity>代码中Intent intent = new Intent();intent.setData(Uri.parse("tel:10086"));startActivity(intent);

在 data 节点中我们设置我们这个 Activity 可以打开的协议,我们这里设置为 tel 协议,那么以后要打开一个 tel 请求的时候,系统都会让我们选择是否用这个 Activity 打开

当然,我们也可以自己定义一个协议(自己定义的协议,由于别人不知道,所以只能由我们自己的程序打开)

Type

type 的存在,主要是为了对 data 的类型做进一步的说明,但是一般情况下,只有 data 属性为 null 的时候,type 属性才有效,如果 data 属性不为 null,系统会自动根据 data 中的协议来分析data的数据类型,而不会去管 type

我们经常遇到需要选择指定类型的文件,这时我们一般是使用 setType 来实现过滤,例如:

				Intent intent = new Intent();intent.setAction(Intent.ACTION_PICK);intent.setType("image/*");startActivity(intent);

如果我们既想要设置 data 又想要设置 type,那么可以使用

setDataAndType(Uri data, String type)

Extras

附加数据
Extras 属性用于在组件之间传递数据

通过 Intent 对象的putExtra()或相关方法可以封装数据,并通过匹配getXXX()方法可以获得封装的数据

Intent 的 Extras 属性是 Bundle 类型的数据

进程之间的数据不能共享,我们发送数据的 intent 和接受数据的 intent 数据相同,但不是同一个 intent,这是克隆一份数据

栗子可以看最后的 Intent和Bundle传值的区别

Flag:标识

flag 属性用于在激活组件时,指定一定的特性

通过Intent对象的 setFlags()addFlags() 方法可以配置该属性,这里不再细说,可以查看 【达内课程】Activity 这篇文章的 Activity的启动模式

IntentFilter 意图过滤器

IntentFilter 用于对 Intent 进行过滤,即实现允许一部分 Intent 对象匹配,而另一部分不匹配,从而拦截一部分 Intent

IntentFilter 在判断 Intent 对象的匹配关系时,主要验证 Intent 对象中的 Action 属性与 Category 属性是否匹配

IntentFilter 中可以存在若干个 Action 属性和若干个 Category 属性,而 Intent 对象中可以存在1个 Action 属性和多个 Category 属性

IntentFilter 与 Intent 的过滤/匹配原则可以简单理解为:Intent 对象中的每一个 Action 和Category,在 IntentFilter 中已经配置过的,即 IntentFilter 中的 Action 和 Category 不会比Intent 对象中的少

拿刚才代码的栗子举例,也就是说 Intent 对象中有 1 个 Action 和1个 Category

				Intent intent = new Intent();intent.setAction("com.test.Main2Activity");intent.addCategory("android.intent.category.DEFAULT");startActivity(intent);

IntentFilter 中只可以比刚才的 Intent 对象多,都能找到,这样是匹配成功的

<activityandroid:name=".Main2Activity"android:label="标题" ><intent-filter><category android:name="android.intent.category.DEFAULT" /><action android:name="com.test.Main2Activity" /><category android:name="category_2"/></intent-filter></activity>

但是如果 Intent 对象中继续 addCategory,增加intent.addCategory("category_2");是可以的,但是增加intent.addCategory("category_1");是不可以的,因为IntentFilter中找不到,匹配失败

IntentFilter 与 Intent的过滤/匹配还可能会验证 Intent 的 Data和Type属性。

由于配置了隐式的激活方式以后,对应的组件可以被当前设备上的任何一个应用程序激活,所以为了保证配置的属性不发生冲突,IntentFilter 中的 Action 属性和 Category 属性的值都应该使用公司的域名、个人主页的域名倒序排列作为前缀,例如: cn.tedu.intent.action.DEFAULT,或者 cn.tedu.intent.category.DEFAULT

Intent和Bundle传值的区别

课前预习
Android中的Bundle

假设需要将数据从页面A传递到B,然后再传递到C

Intent传值:

A页面中

		Intent intent = new Intent(this,SecondActivity.class);intent.putExtra("_username",username);intent.putExtra("_gender",gender);intent.putExtra("_age",age);startActivity(intent);

B页面中

        //接收数据Intent intent = getIntent();String u = intent.getStringExtra("_username");String g = intent.getStringExtra("_gender");int a = intent.getIntExtra("_age",0);//发送数据Intent intent2 = new Intent(this,ThirdActivity.class);intent2.putExtra("_username",u);intent2.putExtra("_gender",g);intent2.putExtra("_age",a);startActivity(intent2);

C页面中

		Intent intent = getIntent();String u = intent.getStringExtra("_username");String g = intent.getStringExtra("_gender");int a = intent.getIntExtra("_age",0);Log.d("Intent","姓名:"+u+",性别:"+g+",年龄:"+a);

可以看到,使用Intent传值需要在B页面将数据一条条取出来然后再一条条传输给C页面。

而使用Bundle的话,在B页面可以直接取出传输的Bundle对象然后传输给C页面

Bundle方式:

A页面中

		Intent intent = new Intent(this, SecondActivity.class);Bundle bundle = new Bundle();bundle.putString("_username", username);bundle.putString("_gender", gender);bundle.putInt("_age", age);intent.putExtra("bundle", bundle);startActivity(intent);

B页面中

		//接收数据Intent intent = getIntent();Bundle bundle=intent.getBundleExtra("bundle");//发送数据Intent intent2 =new Intent(this,ThirdActivity.class);intent2.putExtras(bundle);startActivity(intent2);

C页面中

		Intent intent = getIntent();Bundle bundle = intent.getExtras();String u = bundle.getString("_username");String g = bundle.getString("_gender");int a = bundle.getInt("_age");Log.d("Intent", "姓名:" + u + ",性别:" + g + ",年龄:" + a);

总结:

Bundle可对对象进行操作,而Intent是不可以。Bundle相对于Intent拥有更多的接口,用起来比较灵活,但是使用Bundle也还是需要借助Intent才可以完成数据传递。总之,Bundle旨在存储数据,而Intent旨在传值

更多推荐

【达内课程】Android中Intent使用详解

本文发布于:2024-02-13 18:30:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1759784.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:详解   课程   达内   Android   Intent

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!