Intent详解
·在Android操作系统中,Intent(意图)主要用于激活系统组件,在组件之间传递数据。
·Intent与系统组件有密切的关系,但Intent不是系统组件,它由开发人员创建并维护。
1.Intent也可以实现调用Android系统内置的功能,例如拨打电话等。
2.Intent可以理解为组件之间的“连接器”,可以用于激活Activity,Service,BroadcastReceiver,但不用于激活ContentProvider。
·在Activity中,激活另一个Activity时可以在Intent对象中封装数据:
MainActivity
Intent intent = new Intent(getApplicationContext(),SceondActivity.Class);
intent.putExtra(“name”,”Bacham”);//在Intent中封装数据
startActivity(intent);
SceondActivity
Intent intent = getIntent();//获取Intent对象
String name = intent.getStringExtra(“name”);
·Intent的核心属性包括:
-ComponentName:组件名称;
-Action:动作;
-Data:数据;
-Category:分类;
-Extra:附加信息;
-Flag:标志。
·Component Name表示组件名称,使用Intent激活系统组件时,通过设置该属性的值来确定被激活的组件。
·Component Name属性的数据类型是ComponentName.
·通过Intent的构造方法,setComponent()方法,setClass()方法,setClassName()方法均可以设置ComponentName属性的值。
·以下代码可以设置ComponentName属性:
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.yulipeng.demo.SecondActivity.class”);
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://4008270010”));
startActivity(intent);
//Data的字符数据为:tel://10086
Intent intent = new
Intent(Intent.ACTION_DIAL,Uri.parse("tel://4008270010"));
stareActivity(intent);
-注意:不要使用Data属性封装与Action无关的数据。
·Data属性实际上包括Uri和Type这2个部分,分别表示“通过资源标识符”和数据的“MIME类型”。
·通过setType()方法,setDataAndType()方法可以设置Type属性的值。
Intent intent = new Intent();
intent.setDataAndType(Uri.pare(“file://mnt//sdcard/demo.mp3”),”audio/mp3”);
·在大多数应用场景中,可以不指定Type属性,如果不指定,系统会根据Uri的内容添加Type.
Category
·Category表示分类,用于表示组件的类别,在Intent对象中,可以添加多个Category.
·Category属性的数据类型是String类型。
·涉及Category时,通常应用于隐身意图,且存在Intent Filter(意图过滤器)。Intent与Intent Filter存在匹配关系时,才可以隐身激活组件。
·Android系统定义了一些以CATEGORY_为前缀的常量:
-CATEGORY_DEFULT:默认的;
-CATEGORY_LAUNCHER:入口Activity的分类;
-CATEGORY_BROWSABLE:可以被浏览器触发的分类;
-CATEGORY_HOME:显示HOME界面的分类;
Extra
·Extra表示附加信息,用于封装在组件之间传递的数据。
·Extra属性的数据类型是Bundle类型,其本质是操作一个Key的类型固定为String的HashMap。
·通过putExtras()方法可将Bundle类型的数据设置为Extra属性的值。
·Intent类重载了多次putExtra()方法,用于附加不同类型的数据,并定义了匹配的get方法,例如getStringExtra(),getIntExtra()等。
·对于获取基本值的get类型方法,都有第2个参数表示默认值,例如getIntExtra(String name,int defaultValue),第2个参数仅当根据name参数获取失败时作为该方法的返回值。
·使用Extra属性在组件之间传递数据:
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”,9527);
intent.putExtra(“name”,”BeckHam”);
获取数据方:
Intent intent = getIntent();
int id = intent.getInteExtra(“id”,-1);
String name = intent.getStringExtra(“name”);
Flag
·Flag表示标志,通常用于指定Intent对象的一些特殊意义,例如在Activity的Back Stack的处理中,通过设置Flag属性确定Activity归属于某个Task,或在广播中,设置是否仅动态注册的接收者才可以接收等。
·Flag属性的数据类型是Integer类型。
·通过setFlags()方法可以设置Flag属性的值。
Intent与IntentFilter
IntentFilter表示“Intent过滤器”。
IntentFilter用于使用隐士意图过滤Intent,即对匹配的Intent“放行”,对不匹配的Intent“阻止”。
配置IntentFilter
-通常在AndroidManifest.xml文件中,系统组件的节点下配置IntentFilter。
-在一些应用场景中,也可能使用程序代码配置IntentFilter,例如在广播接受者在应用中
IntentFilter过滤规则
IntentFilter对Intent的以下属性是有效的:
-Action:
表示动作,通常用于隐身激活组件,即不指定组件的名称。这样的Intent被称之为“隐身意图”
-Catetory:
表示分类,用于表示组件的类别,在Intent对象中,可以添加多个Category.
-Data:Data:
表示数据,通常与Action属性匹配使用,用于指定某个动作所需要的,或被操作的数据。
过滤Action
·每个IntentFilter可以添加多个Action。
例如:
<intent - filter>
<action android:name = "cn.com.yulipeng.progect.action.STUDY"/>
<action android:name = "cn.com.yulipeng.progect.action.CODING"/>
<action android:name = "cn.com.yulipeng.progect.action.EXERCISE"/>
</intent - filter>
·每个action节点中name属性的值可以由开发人员自行定义,在同一个Android设备中,action的值应该是不冲突的,因此,该值通常以项目包名作为前缀。
·每一个IntentFilter都应该指定至少一个Action,否则它将阻止所有Intent。
·如果Intent对象本身没有指定Action属性,将不参与匹配校验。
·如果Intent对象指定的Action属性与IntentFilter中任意一个Action匹配,则放行。
过滤Category
·每个IntentFilter可以添加多个Category。
例如:
<intent-filter>
<category android:name = "android.intent.category.DEFAULT"/>
<category android:name = "android.intent.category.BROWSABLE"/>
</intent-filter>
·与Action节点相同,category节点中name属性的值也可以由开发人员自行指定,且应该是不会发生冲突的。
·开发人员可以不为Intent对象指定Category,也可以指定多个Category。
·Android系统必然会为每个Intent对象添加默认的Category,即:
-android.intent.category.DEFAULT
·在过滤规则中,Intent中的每个Category在IntentFilter中都被找到,则放行,否则将阻止,即,放行的条件为:
-IntentFilter中有默认的Category;
-IntentFilter中的Category,对比Intent中的Category,只能多,不能少。
过滤Data
·每个IntentFilter可以添加多个Data.
例如:
<intent-filter>
<data
android:mineType="video/mpeg"
android:scheme="http"
android:host="www.baidu.com"
/>
<data
android:mineType="text/html"
android:scheme="http"
/>
</intent-filter
·在android:minType属性中指定MIME类型时,可以使用通配符,例如:text/*、video/*等。
·每个Uri的完整格式为:
-scheme://host:port/path
·在IntentFilter中配置Data时,以上属性都是可选的,但它们相互并不独立。
·关于Uri是否匹配:
-如果在IntentFilter中仅指定scheme,则任意相同scheme的Uri均匹配,无视host,port,path部分。
-如果在IntentFilter中指定了scheme和host,则任意相同scheme和host的Uri均匹配,无视port,path部分。
-如果在IntentFilter中指定了scheme,host,port,则任意相同scheme,host,port的Uri均匹配,无视path部分;
-如果IntentFilter中指定了完整的Uri各部分,则要求被验证的Uri也完全匹配。
过滤Data
·Data的过滤规则:
-如果Intent没有指定Uri和MIME,仅当IntentFilter也没有指定Uri和MIME时放行;
-如果Intent中指定了Uri,但没有指定MIME,且根据Uri无法推断MIME,仅当IntentFilter指定了相同的Uri且没有指定MIME时放行。
-如果Intent没有指定Uri,但指定了MIME,仅当IntentFilter也没有指定Uri且指定了相同的MIME时放行;
-如果Intent中同时指定了Uri和MIME,仅当IntentFilter中也指定了相同的Uri和MIME时放行,或IntentFilter中没有指定MIME但根据Uri可以推断出MIME时放行。
总结
·IntentFilter可以指定Action,Category,Data来校验是否匹配,匹配的Intent将放行,否则将阻止。
·大致放行规则如下(通常设置的配置规则):
-关于Action:Intent对象中的Action(最多1个)在IntentFilter中可以找到;
-关于Category:Intent对象中所有的Category在IntentFilter中都可以找到,且Intent对象中必然有android.intent.category.DEFAULT这个Category.
Permission(权限)
·在Android系统中,敏感操作(涉及隐私的,安全的,可能产生费用的都需要申请权限,且当应用程序被安装到设备上之前,会列举当前应用程序所申请的权限,用户可以选择继续安装应用程序,或不安装。)
·在开发过程中,每次部署应用程序时不会出现安装向导界面,亦不会提示应用程序所申请的权限。
·所有权限通过在AndroidManifest.xml文件中添加节点是根节点的直接节点,且可以存在若干个。
·通话权限为:
“uses-permission android=”android.permission.CALL_PHONE”/”
示例:
使用显示/隐式意图实现跳转并传递数据
MainActivity:
package com.example.intentactivity;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
private EditText etNumber,edName,edSalary,edContent;
private Button dail,call;
private void setupView(){
etNumber = (EditText) findViewById(R.id.et_nameId);
edName = (EditText) findViewById(R.id.et_name);
edSalary = (EditText) findViewById(R.id.et_salary);
findViewById(R.id.btn_submit).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//显示激活
//Intent intent = new Intent(getApplicationContext(), DetailsActivity.class);
//隐式激活
Intent intent = new Intent("com.example.detailAactivity.INTENT");
intent.addCategory("com.example.detailActivity.CATAGORY");
int number =Integer.valueOf(etNumber.getText().toString()) ;
String name = edName.getText().toString();
int salary =Integer.valueOf(edSalary.getText().toString()) ;
//第一种封装数据方法
Bundle bundle = new Bundle();
bundle.putInt("edNumber", number);
bundle.putString("edName", name);
bundle.putFloat("edSalary", salary);
intent.putExtras(bundle);
//第二种封装数据方法
/*intent.putExtra("edNumber", number);
intent.putExtra("edName", name);
intent.putExtra("edSalary", salary);
*/
startActivity(intent);
finish();
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//setupView();
//使用隐式意图实现呼叫和拨打电话
}
}
DetailsActivity:
package com.example.intentactivity;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.widget.TextView;
public class DetailsActivity extends Activity {
private TextView tvNumber,tvName,tvSalary;
private void setupView(){
tvNumber = (TextView) findViewById(R.id.tv_nameId);
tvName = (TextView) findViewById(R.id.tv_name);
tvSalary = (TextView) findViewById(R.id.tv_salary);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
setupView();
Intent intent = getIntent();
int number = intent.getIntExtra("edNumber", -1);
String name = intent.getStringExtra("edName");
float salary = intent.getFloatExtra("edSalary", -1f);
tvNumber.setText("编号:"+ number);
tvName.setText("姓名:"+name);
tvSalary.setText("薪资:"+salary +"元 / 月");
}
}
XML:
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="请输入员工信息:"
android:textSize="35sp" />
<EditText
android:id="@+id/et_nameId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/tv_content"
android:hint="请输入员工编号"
android:inputType="number" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/et_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/et_nameId"
android:layout_alignRight="@+id/et_nameId"
android:layout_below="@+id/et_nameId"
android:layout_marginTop="16dp"
android:hint="请输入员工姓名"
android:inputType="text" />
<EditText
android:id="@+id/et_salary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/et_name"
android:layout_below="@+id/et_name"
android:layout_marginTop="24dp"
android:hint="请输入员工薪资"
android:inputType="number" />
<TextView
android:id="@+id/tv_salary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/et_salary"
android:layout_alignBottom="@+id/et_salary"
android:layout_toRightOf="@+id/et_salary"
android:text="元/月" />
<Button
android:id="@+id/btn_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/et_salary"
android:layout_below="@+id/tv_salary"
android:layout_centerVertical="true"
android:text="提交" />
<RelativeLayout
android:id="@+id/relativeLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/btn_submit"
android:layout_below="@+id/btn_submit"
android:layout_marginRight="29dp"
android:layout_marginTop="90dp" >
</RelativeLayout>
</RelativeLayout>
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".DetailsActivity" >
<TextView
android:id="@+id/tv_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="14dp"
android:textSize="35sp"
android:text="员工信息:" />
<TextView
android:id="@+id/tv_nameId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/tv_details"
android:layout_alignParentRight="true"
android:layout_below="@+id/tv_details"
android:layout_marginTop="14dp"
android:text="编号:***"
android:textSize="30sp" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/tv_nameId"
android:layout_alignParentRight="true"
android:layout_below="@+id/tv_nameId"
android:layout_marginTop="18dp"
android:text="姓名:***"
android:textSize="30sp" />
<TextView
android:id="@+id/tv_salary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/tv_name"
android:layout_alignRight="@+id/tv_name"
android:layout_below="@+id/tv_name"
android:layout_marginTop="18dp"
android:text="薪资:***"
android:textSize="30sp" />
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentactivity"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.intentactivity.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="com.example.intentactivity.DetailsActivity"
android:label="@string/title_activity_details" >
<intent-filter >
<action android:name="com.example.detailAactivity.INTENT"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.example.detailActivity.CATAGORY"/>
</intent-filter>
</activity>
</application>
</manifest>
示例二:
使用隐式意图实现拨号和呼叫
代码:
package com.example.intent.dial.call;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText edContent;
private Button dail,call;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dail = (Button) findViewById(R.id.btn_dai_id);
call = (Button) findViewById(R.id.btn_call_id);
edContent = (EditText) findViewById(R.id.ed_phone);
btnOnClickListener listener = new btnOnClickListener();
dail.setOnClickListener(listener);
call.setOnClickListener(listener);
}
private class btnOnClickListener implements View.OnClickListener{
@Override
public void onClick(View v) {
Intent intent = new Intent();
String phone = edContent.getText().toString();
//Data的字符数据为:tel://10086
intent.setData(Uri.parse("tel://"+phone));
switch (v.getId()) {
case R.id.btn_dai_id:
intent.setAction(Intent.ACTION_DIAL);
break;
case R.id.btn_call_id:
intent.setAction(Intent.ACTION_CALL);
break;
}
startActivity(intent);
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intent.dial.call"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="17" />
<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="com.example.intent.dial.call.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>
</application>
</manifest>