安卓中Intent
Intent学习
Intent属性的详解
在android操作系统中,Intent(意图)主要用于激活系统组件、在组件之间传递数据。
Intent也可以实现调用Android系统内置的功能,例如拨打电话等。
Intent可以理解为组件之间的“连接器”,可以用于激活Activity、Service、BroadcastReceiver,但不用于激活Content Provider;
Intent与系统组件有密切的关系,但Intent不是系统组件,它由开发人员创建并维护。
Intent intent = new Intent(getApplicationContext(),SecondActivity.class);
startActivity(intent);
在Activity中,激活另一个Activity时可以在Intent对象中封装数据:
Intent intent = new Intent(getApplicationContext(),SecondActivity.class);
intent.putExtra("name","Beckham");
startActivity(intent);
SecondActivity
Intent intent = getIntent();
String name = intent.getStringExtra("name");
Intent的六个核心属性包括:
Component Name:组件名称;
Action:动作;
Data:数据;
Category:分类;
Extra:附加信息;
Flag:标志。
Component Name表示组建名称,使用Intent激活系统组件时,通过设置该属性的值来确定被激活的组件。
Component Name 属性的数据类型是ComponentName;
通过Intent的构造方法、setComponent()方法、setClass()方法、setClassName()方法均可以设置Component Name属性的值。
以下代码可以设置Component Name属性:
Intent intent = new Intent(getApplicationContext(),SecondActivity.class);
Intent intent = new Intent();
intent.setClass(getApplicationContext(),SecondActivity.class);
Intent intent = new Intent();
intent.setClassName(getApplicationContext(),"cn.com.tarena.demo.SecondActivity");
Intent intent = new Intent();
ComponentName component =
new ComponentName(getApplicationContext(),SecondActivity.class);
intent.setComponent(component);
显示意图:再激活系统组件时,明确的指定了被激活的组件时,该Intent被称之为“显示意图”。
Action
Action表示动作,通常用于隐式激活组件,即不指定组建的名称。这样的Intent被称之为“隐式意图”;
Action属性的数据类型是String类型。
Android系统在Intent类中定义了一系列以ACTION_为前缀的常量,例如ACTION_DIAL,可用于激活系统的拨号程序。
通过setAction()方法可以设置Action属性的值。
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL);
startActivity(intent);
Data
Data表示数据,通常与Action属性匹配使用,用于指定某个动作所需要的,或被操作的数据。
Data属性的数据类型是Uri类型,该类型的数据可以通过Uri.parse()将字符串转换得到。
通过Intent的构造方法,setData()方法可以设置Data属性的值。
以下代码可以设置Data属性:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel://4956579367"));
startActivity(intent);
Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse("tel://567458675487654"));
startActivity(intent);
注意:不要使用Data属性封装与Action无关的数据。
Data属性实际上包括Uri和Type这2部分,分别表示“通用资源标识符”和数据的“MIME类型”。
通过setType()方法、setDataAndType()方法可以设置Type属性的值。
Intent intent = new Intent();
intent.setDataAndType(Uri.parse("file://mnt/scdard/demo.mp3"),"audio/mp3");
Intent intent = new Intent();
intent.setDataAndType(Uri.parse("file:///mnt/sdcard/demo.mp3"),"audio/mp3");
Category
Category表示分类,用于表示组件的类别,在Intent对象中,可以添加多个Category。
Category的数据类型是String类型。
涉及Category时,通常应用于隐式意图,且存在Intent Filter(意图过滤器),Intent与IntentFilter存在匹配关系时,才可以隐式激活组件。
Android系统定义了一些以CATEGORY_为前缀的常量:
CATEGORY_DEFAULT:默认的;
CATEGORY_LAUNCHER:入口Activity的分类;
CATEGORY_BROWSABLE:可被浏览器触发的分类;
CATEGORY_HOME:显示HOME界面的分类;
Extra
Extra表示附加信息,用于封装在组件之间传递的数据。
Extra属性的数据类型是Bundle类型,其本质是操作一个key的类型固定为String和HashMap;
通过putExtra()方法可将Bundle类型的数据设置为Extra属性的值。
Intent类重载了多次putExtra()方法,用于附加不同类型的数据,并定义了匹配的get()方法,例如getStringExtra(),getIntExtra()等。
对于获取基本值的get类型方法,都有第2个参数表示默认值,例如getIntExtra(String name,intdefaultValue),第2个参数仅当根据name参数获取值失败时
作为该方法的返回值。
使用Intent属性在组件之间传递数据:
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putInt("id",9527);
bundle.putString("name","Beckham");
intent.putExtras(bundle);
Intent intent = new Intent();
intent.putExtra("id",9627);
intent.putExtra("name","Beckham");
数据接收方:
Intent intent = new Intent();
int id = intent.getIntExtra("id",-1);
String name = intent.getStringExtra("name");
Flag
Flag表示标志,通常用于指定Intent对象的一些特殊意义,例如在Activity的Back Stack的处理中,通过设置Flag属性确定Activity归属于某个Task,或在广播中,设置是否仅动态注册的接收者才可以接收等。
Flag属性的数据类型是Integer类型;
通过setFlag()方法可以设置Flag属性的值。
Intent实现的小案例:
package com.example.intent;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
private EditText editText1;
private EditText editText2;
private EditText editText3;
private Button button_submit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = (EditText)findViewById(R.id.editText1);
editText2 = (EditText)findViewById(R.id.editText2);
editText3 = (EditText)findViewById(R.id.editText3);
button_submit = (Button)findViewById(R.id.button1);
button_submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id;
String name;
float salary;
id = Integer.valueOf(editText1.getText().toString());
name = editText2.getText().toString();
salary = Float.valueOf(editText3.getText().toString());
Intent intent = new Intent(getApplicationContext(),EmfoActivity.class);
intent.putExtra("id", id);
intent.putExtra("name", name);
intent.putExtra("salary", salary);
startActivity(intent);
}
});
}
}
布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入员工信息:"
android:textSize="23sp" />
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_marginTop="25dp"
android:ems="10"
android:hint="请输入员工编号:" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/editText1"
android:layout_below="@+id/editText1"
android:layout_marginTop="40dp"
android:ems="10"
android:hint="请输入员姓名:" />
<RelativeLayout
android:id="@+id/relativeLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@+id/editText2"
android:gravity="center_horizontal" >
</RelativeLayout>
<EditText
android:id="@+id/editText3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:ems="10"
android:hint="请输入员工薪资:" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/editText3"
android:layout_alignParentRight="true"
android:text="元/月"
android:textSize="18sp" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/editText3"
android:layout_marginLeft="47dp"
android:layout_marginTop="76dp"
android:text="提交" />
</RelativeLayout>
跳转到另一个界面:
package com.example.intent;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class EmfoActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_emfo);
Intent intent = getIntent();
int id = intent.getIntExtra("id", -1);
String name = intent.getStringExtra("name");
float salary = intent.getFloatExtra("salary", -1f);
((TextView)findViewById(R.id.tv_id)).setText("编号:"+ id);
((TextView)findViewById(R.id.tv_name)).setText("姓名:"+ name);
((TextView)findViewById(R.id.tv_salary)).setText("薪资:"+ salary + "元/月");
}
}
界面的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="员工的信息:"
android:textSize="23sp" />
<TextView
android:id="@+id/tv_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:ems="10" >
</TextView>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="38dp"
android:ems="10" />
<TextView
android:id="@+id/tv_salary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="38dp"
android:ems="10" />
</LinearLayout>
Intent与IntentFilter
IntentFilter表示“意图过滤器”;
IntentFilter用于使用隐式意图时过滤Intent,即对匹配的Intent“放行”,对不匹配的Intent“阻止”;
通常在AndroidMainfest.xml文件中,系统组件的节点下配置IntentFilter,例如:
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
在一些应用场景中,也可能使用程序代码配置IntentFilter,例如在广播接收者在应用中。
IntentFilter对Intent的以下属性是有效的:
Action;
Category;
Data;
过滤Action:每个IntentFilter可以添加多个Action。
例如:
<intent-filter>
<action android:name="cn.com.edu.hpu.action.STUDY"/>
<action android:name="cn.com.edu.hpu.action.CODING"/>
<action android:name="cn.com.edu.hpu.action.EXERCISE"/>
<intent-filter>
每个action节点中name属性的值可以由开发人员自行指定,在同一个Android设备中,action的值应该是不冲突的,
因此,该值通常以项目包名作为前缀。
每个IntentFilter都应该指定至少一个Action,否则它将阻止所有的Intent。
如果Intent对象本身没有指定Action属性,将不参与匹配校验。
如果Intent对象指定的Action属性与IntentFilter中任意一个Action匹配,则放行。
每个IntentFilter可以添加多个Category。
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BRWSABLE"/>
</intent-filter>
与action节点相同,category节点中name属性的值也可以由开发人员自行指定,且应该是不会发生冲突的。
开发人员可以不为Intent对象指定Category,也可以指定多个Category。
android系统必然会为每个Intent对象添加默认的Category,即:
android.intent.category.dEFAULT
再过滤规则中,Intent中的每个Category在IntentFilter中都能被找到,则放行,否则将阻止,
即方形的条件为:
IntentFilter中有默认的Category,对比Intent中的Category,只能多,不能少。
每个IntentFilter可以添加多个Data。
<intent-filter>
<data
android:mimeType="video/mpeg"
android:scheme="http"
android:host="www.cn.edu.hpu.cn"/>
<data
android:mimeType="text/html"
android:scheme="http"/>
</intent-filter>
在android:mimeType属性中指定MIME类型时,可以使用通配符,例如:text/*、video/*等。
每个Uri的完整格式为:
scheme://host:port/path
在IntentFilter中配置Data时,以上属性都是可选的,但他们相互并不独立。
关于Uri是否匹配:
如果在IntentFilter中仅指定了scheme,则任意相同scheme的Uri均匹配,无视host、port、path部分;
如果在IntentFilter中指定了完整的Uri各部分,则被要求被验证的Uri也完全匹配。
如果Intent没有指定Uri和MIME,仅当IntentFilter也没有指定Uri和MIME时放行;
如果Intent中指定了Uri,但没有指定MIME,且根据Uri无法推断MIME,仅当IntentFilter指定了相同的Uri且没有指定MIME时放行;
IntentFilter可以指定Action、Category、Data来检验是否匹配,匹配的Intent将放行,否则将阻止;
大致放行规则如下(通常设置的配置规则):
关于Action:Intent对象中的Action(最多一个)在IntentFilter中可以被找到;
关于Category:Intent对象中所有的Category在IntentFilter中都可以找到,且Intent对象中必然有android.intent.category.DEFAULT这个Category。
自定义隐式意图激活Activity:
使用隐式意图调用系统的拨号、呼叫程序。
Action
拨号Action:Intent.ACTION_DIAL
呼号Action:Intent。ACTION_CALL
Permission
在Android系统中,敏感操作(涉及隐私的、安全的、可能产生费用的)都需要申请权限,且当应用程序被安装到设备上之前,会列举当前应用程序所申请的权限,
用户可以继续选择安装该应用程序,或不安装。
在开发过程中,每次部署应用程序时不会出现安装向导界面,亦不会提示应用程序所申请的权限。
所有权限通过在AndroidMainfest.xml文件中添加<uses-permission android:name="权限名称"/>节点实现申请,
该节点是根节点的直接子节点,且可以存在若干个。
通话权限为:
<uses-permission android:name="android.permission.CALL_PHONE"/>
案例:
package com.example.intent;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
private EditText phone;
private Button call,tell;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
phone = (EditText)findViewById(R.id.editText1);
call=(Button)findViewById(R.id.call);
tell = (Button)findViewById(R.id.tell);
InnerOnClickListener listener = new InnerOnClickListener();
tell.setOnClickListener(listener);
call.setOnClickListener(listener);
}
private class InnerOnClickListener implements View.OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
String phoneNumber = phone.getText().toString();
intent.setData(Uri.parse("tel://" + phoneNumber));
switch (v.getId()) {
case R.id.tell:
intent.setAction(Intent.ACTION_DIAL);
break;
case R.id.call:
intent.setAction(Intent.ACTION_CALL);
break;
}
startActivity(intent);
}
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<EditText
android:id="@+id/editText1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_marginTop="25dp"
android:hint="请输入电话号码" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>
<Button
android:id="@+id/tell"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="拨号" />
<Button
android:id="@+id/call"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="呼叫" />
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intent"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.CALL_PHONE"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".EmfoActivity"
android:label="@string/title_activity_emfo" >
</activity>
</application>
</manifest>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理