前言
每个应用程序都有若干个Activity组成,每一个Activity都是一个应用程序与用户进行交互的窗口,呈现不同的交互界面。因为每一个Acticity的任务不一样,所以经常互在各个Activity之间进行跳转,在Android中这个动作是靠Intent来完成的。你通过startActivity()方法发送一个Intent给系统,系统会根据这个Intent帮助你找到对应的Activity,即使这个Activity在其他的应用中,也可以用这种方法启动它。
Intent的定义
Intent意图可以是明确的指定组件(四大组件)的名称,这样你可以精确的启动某个系统组件,比如启动一个Activity。它也可以是模糊的,没有指定组件名称,只要是能够匹配到这个Intent的应用都可以接收到,比如发送一个拍照Intent,所有的拍照应用都会响应。
显式Intent和隐式Intent
-
显式的Intent就是你已经知道要启动的组件名称,比如某个Activity的包名和类名,在Intent中明确的指定了这个组件(Activity),一般来说这种Intent经常用在一个应用中,因为你已经明确的知道要启动的组件名称。
当你创建一个显式Intent来启动一个Activity或者Service时,系统会立刻通过你的Intent对象启动那个组件。
-
隐式的Intent就是你不知道要启动的组件名称,只知道一个Intent动作要执行,比如:拍照,录像,查看地图。一般来说这种Intent用在不同的应用之间传递信息。
当你创建一个隐式Intent,系统会根据manifest file中的intent filter找匹配的组件,如果你发送的Intent匹配到一个intent filter,系统会把你的Intent传递给该filter对应的组件(Activity、Service等),并且启动它。如果找到多个匹配的intent filter对应的应用程序,则会弹出一个对话框让你选择哪个应用程序接受你的Intent。
注:
- intent filter是一种应用程序manifest文件中的语法表达,就像是html的标签,它是一个系统组件标签(比如:Activity)的组成部分,可以说是子标签吧,这个系统组件接受什么样的intent就是用它来指定的,如果一个系统组件不写intent filter,那么它只能通过显式的intent来启动。
- 出于安全的角度,你的Service组件务必不要用隐式的intent filter来进行说明,因为用隐式的intent启动一个Service往往不能保证Service会被启动,并且用户也不知道哪个Service会响应你的Intent。从Android5.0(API 21),系统会抛出异常当你用隐式的Intent去调用bindService()方法。
Intent七大属性
Intent对象大致包括7大属性:ComponentName、 Action 、 Category 、 Data 、Type、 Extra 、Flag。
-
Component Name(目标组件): 目标组件
要启动的组件名称,在创建Intent的时候是可选的,但是它是显式Intent的重要标志,有它就意味着只有Component name匹配上的那个组件才能接收你发送出来的显示intent。如果不写那么你创建的Intent就是隐式的,系统会根据这个intent的其他信息(比如:action、data、category)来确定哪些组件来接收这个intent,所以如果你想明确的启动哪个组件,就通过component name来指定。Intent的ComponentName属性是一个类的全称,包括包名,比如:com.example.ExampleActivity,你可以通过Intent的setComponent(),setClass(),setClassName()方法来设定,也可以通过Intent的构造方法来设定。
-
Action(动作): 用来表示意图的动作,如:查看,发邮件,打电话
是一个可以指明目标组件行为的字符串。action很大程度上决定了category和data中应传入的信息;您也可以在自己的应用程序组件中指定action,以便让其他应用程序启动自己的组件。对应action中字符串,不建议使用硬编码的形式,而应在所属组件的类中设置为常量。如需在自己的组件中定义action,应以应用的包名作为前缀,比如:
public static final String ACTION_TIMETRAVEL="com.example.action.TIMETRAVEL";
常用动作
最常用的是Action_MAIN(作为初始的Activity启动,没有数据的输入输出)ACTION_MAIN:(android.intent.action.MAIN)Android程序入口。 每个Android应用必须且只能包含一个此类型的Action声明。【如果设置多个,则哪个在前,执行哪个。】 ACTION_VIEW: (android.intent.action.VIEW) 显示指定数据。 ACTION_EDIT: (android.intent.action.EDIT) 编辑指定数据。 ACTION_DIAL: (android.intent.action.DIAL) 显示拨号面板。 ACTION_CALL: (android.intent.action.CALL) 直接呼叫Data中所带的号码。 ACTION_ANSWER: (android.intent.action.ANSWER) 接听来电。 ACTION_SEND: (android.intent.action.SEND) 向其他人发送数据(例如:彩信/email)。 ACTION_SENDTO: (android.intent.action.SENDTO) 向其他人发送短信。 ACTION_SEARCH: (android.intent.action.SEARCH) 执行搜索。 ACTION_GET_CONTENT: (android.intent.action.GET_CONTENT) 让用户选择数据,并返回所选数据。
setAction(String action) 用来设置Intent的动作,参数可以为常量
getAction() 方法用来获取Intent动作名称
上面的Action都是系统定义好的,具有一定意义的动作指向的动作。
Intent的Action对象其实就是一个字符串常量,系统的Action对象是系统定义好的字符串常量,我们也可以自己定义自己的Action作为字符串常量。就像上面的例子使用到了自定义的Action字符串对象。 -
category(类别): 用来表示动作的类别。
Intent的action、category属性都是普通的字符串,其中action表示Intent需要完成的一个抽象”动作”,而category则为action添加额外的类别信息,通常action和category一块使用。
需要指出的是,一个Intent中只能包含一个action属性,但可以包含多个category属性。当程序创建Intent时,该Intent默认启动常量值为andorid.intent.category.DEFAULT的组件。这里的一个Intent中只能包含一个action属性,并不是Activity中xml的设置规范,而是你要跳转到的页面去,你只能设置一个Action的值。
常用的Category:CATEGORY_DEFAULT:Android系统中默认的执行方式,按照普通Activity的执行方式执行。
CATEGORY_HOME:设置该组件为Home Activity。
CATEGORY_PREFERENCE:设置该组件为Preference。
CATEGORY_LAUNCHER:设置为当前应用程序优先级最高的Activity,通常与ACTION_MAIN配合使 用。
CATEGORY_BROWSABLE:设置该组件可以使用浏览器启动。
CATEGORY_GADGET:设置该组件可以内嵌到另外的Activity中。
-
data(数据): 表示与动作要操作的数据。如:查看指定的联系人
Data数据用来向Action属性提供动作的数据。这里的Data不是Intent里面的数据,而是指明动作的具体数据,比如说动作是打电话,那么打给具体的某一个人,就用到了date里面的数据来指定。同样发邮件、或打开具体的某一个网址也是通过Data数据。
Data属性只接受Uri对象,Uri对象是统一资源标识符。对应概念不用太多理解,只需知道里面某些具体值的表现形式就可以了。
Uri其实就是相当于一个网址,如图所示:
网址只是Uri其中一种格式的字符串,要使用它还要把它解析后转化为Uri类型。
为Intent对象添加Data数据,代码:
intent.setData(Uri.parse(“http://www.baidu.com“));系统内置的几个Data属性常量:
tel://:号码数据格式,后跟电话号码。 mailto://:邮件数据格式,后跟邮件收件人地址。 smsto://:短息数据格式,后跟短信接收号码。 content://:内容数据格式,后跟需要读取的内容。 file://:文件数据格式,后跟文件路径。 market://search?q=pname:pkgname:市场数据格式,在Google Market里搜索包名为pkgname的应用。 geo://latitude, longitude:经纬数据格式,在地图上显示经纬度所指定的位置。
-
type(数据类型): 对data类型的描述。
与Data有关的,这个不是Intent的数据类型,是Intent的Action的Data数据的类型。intent.setAction(android.content.Intent.ACTION_VIEW); Uri uri = Uri.parse("file:///storage/emulated/0/Pictures/Screenshots/qqq.mp4"); String type = "video/mp4"; intent.setDataAndType(uri,type); startActivity(intent)
-
extras(附件信息): 附件信息。如:详细资料,一个文件,某事。
extras属性主要用于传递目标组件所需要的额外的数据。
通过putExtras()方法设置。保存数据;
通过getExtras()方法设置。获取数据通常我们使用Intent来直接传递Bundle对象,但也可以传递其他系统内置的一些参数。
如果要传递是是对象,那么对象必须实现序列化。Intent intent = new Intent(); intent.setClass(this, SubActivity.class); // 直接添加 //intent.putExtra("MyData", new ParcelableData()); // 通过Bundle Bundle bundle = new Bundle(); bundle.putString("MyString", "test bundle"); bundle.putParcelable("MyData", new ParcelableData()); intent.putExtras(bundle); startActivity(intent);
//ParcelableData parcelableData = getIntent().getParcelableExtra("MyData"); Bundle bundle = getIntent().getExtras(); ParcelableData parcelableData = bundle.getParcelable("MyData"); String testBundleString = bundle.getString("MyString"); Log.v("string=", testBundleString); Log.v("name=", parcelableData.getName()); Log.v("age=", ""+parcelableData.getAge());
-
flags属性:Intent可调用addFlags()方法来为Intent添加控制标记。
1、FLAG_ACTIVITY_CLEAR_TOP:(效果同Activity LaunchMode的singleTask)
2、FLAG_ACTIVITY_SINGLE_TOP:(效果同Activity LaunchMode的singleTop)
3、FLAG_ACTIVITY_NEW_TASK: (效果类似Activity LaunchMode的singleInstance)
捉到一只Sample↓↓↓↓↓
MianActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//从Android 7.0开始,一个应用提供自身文件给其它应用使用时,如果给出一个file://格式的URI的话,应用会抛出FileUriExposedException。
//解决方法置入一个不设防的VmPolicy,但是要确保目标应用有本地读写权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
}
public void clickButton(View view) {
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
switch (view.getId()) {
case R.id.button_main_call:
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
break;
case R.id.button_main_dial:
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
break;
case R.id.button_main_dialer:
intent.setAction("com.android.phone.action.TOUCH_DIALER");
break;
case R.id.button_main_sms:
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("smsto:10086"));
intent.putExtra("sms_body", "该吃饭了,下课吧!");
break;
case R.id.button_main_setting:
intent.setAction("android.settings.SETTINGS");
break;
case R.id.button_main_datesetting:
intent.setAction("android.settings.DATE_SETTINGS");
break;
case R.id.button_main_soundsetting:
intent.setAction("android.settings.SOUND_SETTINGS");
break;
case R.id.button_main_wifisetting:
intent.setAction("android.settings.WIFI_SETTINGS");
break;
case R.id.button_main_contacts:
intent.setAction("com.android.contacts.action.LIST_CONTACTS");
break;
case R.id.button_main_web:
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
break;
case R.id.button_main_showimage:
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(new File("mnt/sdcard/Download/landscape.jpg")),
"image/*");
break;
case R.id.button_main_showtext:
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(new File("mnt/sdcard/Download/info.txt")),
"text/*");
break;
case R.id.button_main_playaudio:
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(
"mnt/sdcard/Download/heavencity.mp3")), "audio/*");
break;
case R.id.button_main_playvideo:
intent.setAction(android.content.Intent.ACTION_VIEW);
String type = "video/mp4";
Uri uri = Uri.parse("file:///storage/emulated/0/Pictures/Screenshots/qqq.mp4");
intent.setDataAndType(uri,type);
break;
case R.id.button_main_home:
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
break;
default:
break;
}
startActivity(intent);
}
}
AndroidManifest.xml中需要打电话的权限
<uses-permission android:name="android.permission.CALL_PHONE"/>
layout文件
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button_main_call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="直接拨号" />
<Button
android:id="@+id/button_main_dial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="启动拨号面板" />
<Button
android:id="@+id/button_main_dialer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="显示拨号面板" />
<Button
android:id="@+id/button_main_sms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="发送短信" />
<Button
android:id="@+id/button_main_setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="系统设置" />
<Button
android:id="@+id/button_main_datesetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="日期设置" />
<Button
android:id="@+id/button_main_soundsetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="声音设置" />
<Button
android:id="@+id/button_main_wifisetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="WIFI设置" />
<Button
android:id="@+id/button_main_web"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="浏览网页" />
<Button
android:id="@+id/button_main_contacts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="查看联系人" />
<Button
android:id="@+id/button_main_showimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="查看图片" />
<Button
android:id="@+id/button_main_showtext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="查看文本" />
<Button
android:id="@+id/button_main_playvideo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="播放视频" />
<Button
android:id="@+id/button_main_playaudio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="播放音频" />
<Button
android:id="@+id/button_main_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="HOME" />
</LinearLayout>
</ScrollView>