一. 关于 Intent 1.介绍
Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。
Intent是一个将要执行的动作的抽象的描述,一般来说是作为参数来使用,由 Intent来协助完成 Android各个组件之间的通讯。
2.作用 ① 启动 Activity
1 2 3 Context.startActvity() Activity.startActivityForResult()
② 启动Service
1 2 Context.startService() Context.bindService()
③ 发送Broadcast
1 2 3 4 Context.sendBroadcasts() Context.sendOrderedBroadcast() Context.sendStickyBroadcast()
二.Intent种类 1.显式Intent 显式,即直接指定需要打开的activity对应的类。
① 构造方法传入Component
1 2 Intent intent = new Intent(this , SecondActivity.class); startActivity(intent);
② set Component方式
1 2 3 4 5 Intent intent = new Intent(); intent.setClass(this , SecondActivity.class); startActivity(intent);
说明:
2.隐式Intent 隐式,不明确指定启动哪个Activity,而是设置Action、Data、Category,让系统来筛选出合适的Activity。筛选是根据所有的intent-filter
来筛选。
以 Action 为例子,创建一个Activity,在AndroidManifest.xml对应的<activity></activity>
里面的intent-filter
添加 action,一般命名方式是包名+Action名,category设置为android.intent.category.DEFAULT
。
1 2 3 4 5 6 <activity android:name=".SecondActivity" > <intent-filter> <action android:name="android.intent.action.SECOND" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
通过这个action name找到上面的Activity,启动这个Activity。
1 2 Intent intent = new Intent("android.intent.action.SECOND" ); startActivity(intent);
1 2 3 Intent intent = new Intent(); intent.setAction("android.intent.action.SECOND" ); startActivity(intent);
三.Intent属性 Intent对象大致包括7大属性:Action(动作) 、Data(数据) 、Category(类别) 、Type(数据类型) 、Component(组件) 、Extra(扩展信息) 、Flag(标志位) 。其中最常用的是Action属性和Data属性。
1.Action:用来表现意图的行动 一个字符串变量,可以用来指定Intent要执行的动作类别。
常见的Action:
类型(Activity)
作用
ACTION_MAIN
表示程序入口
ACTION_VIEW
自动以最合适的方式显示Data
ACTION_EDIT
提供可以编辑的
ACTION_PICK
选择一个一条Data,并且返回它
ACTION_DAIL
显示Data指向的号码在拨号界面Dailer上
ACTION_CALL
拨打Data指向的号码
ACTION_SEND
发送Data到指定的地方
ACTION_SENDTO
发送多组Data到指定的地方
ACTION_RUN
运行Data,不管Data是什么
ACTION_SEARCH
执行搜索
ACTION_WEB_SEARCH
执行网上搜索
ACRION_SYNC
执同步一个Data
ACTION_INSERT
添加一个空的项到容器中
类型(Broadcast)
作用
ACTION_TIME_TICK
当前时间改变,并即时发送时间,只能通过系统发送。调用格式"android.intent.action.TIME_TICK"
ACTION_TIME_CHENGED
设置时间。调用格式"android.intent.action.TIME_SET"
2.Data: 表示与动作要操纵的数据 一个URI对象是一个引用的data的表现形式,或是data的MIME类型;data的类型由Intent的action决定。
3.Category: 用来表现动作的类别 一个包含Intent额外信息的字符串,表示哪种类型的组件来处理这个Intent。任何数量的Category 描述都可以添加到Intent中,但是很多intent不需要category,下面列举一些常用的category:
类型
作用
CATEGORY_DEFAULT
把一个组件Component设为可被implicit启动的
CATEGORY_LAUNCHER
把一个action设置为在顶级执行。并且包含这个属性的Activity所定义的icon将取代application中定义的icon
CATEGORY_BROWSABLE
当Intent指向网络相关时,必须要添加这个类别
CATEGORY_HOME
使Intent指向Home界面
CATEGORY_PREFERENCE
定义的Activity是一个偏好面板Preference Panel
4.Type: 指定数据类型 一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。
5.Component: 目的组件 指定Intent的目标组件名称,当指定了这个属性后,系统将跳过匹配其他属性,而直接匹配这个属性来启动对应的组件。
Intent可以携带的额外 key-value 数据,你可以通过调用putExtra()
方法设置数据,每一个 key对应一个 value数据。你也可以通过创建 Bundle对象来存储所有数据,然后通过调用putExtras()
方法来设置数据。
类型
作用
EXTRA_BCC
存放邮件密送人地址的字符串数组
EXTRA_CC
存放邮件抄送人地址的字符串数组
EXTRA_EMAIL
存放邮件地址的字符串数组
EXTRA_SUBJECT
存放邮件主题字符串
EXTRA_TEXT
存放邮件内容
EXTRA_KEY_EVENT
以KeyEvent对象方式存放触发Intent 的按键
EXTRA_PHONE_ NUMBER
存放调用ACTION_CALL 时的电话号码
7.Flag: 期望这个意图的运行模式 用来指示系统如何启动一个Activity,可以通过setFlags()
或者addFlags()
可以把标签flag用在Intent中。
类型
作用
FLAG_ACTIVITY_CLEAR_TOP
相当于SingleTask
FLAGE_ACTIVITY_SINGLE_TOP
相当于SingleTop
FLAG_ACTIVITY_NEW_TASK
类似于SingleInstance
FLAG_ACTIVITY_NO_HISTORY
当离开该Activity后,该Activity将被从任务栈中移除
四.Intent的用法 1.调用拨号程序 1 2 3 4 5 6 7 8 Uri uri = Uri.parse("tel:10010" ); Intent intent = new Intent(Intent.ACTION_DIAL, uri); startActivity(intent); Uri callUri = Uri.parse("tel:10010" ); Intent intent = new Intent(Intent.ACTION_CALL, callUri);
2.发送短信或者彩信 1 2 3 4 5 6 7 8 9 10 11 12 13 Uri uri = Uri.parse("smsto:10010" ); Intent intent = new Intent(Intent.ACTION_SENDTO, uri); intent.putExtra("sms_body" , "Hello" ); startActivity(intent); Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra("sms_body" , "Hello" ); Uri uri = Uri.parse("content://media/external/images/media/23" ); intent.putExtra(Intent.EXTRA_STREAM, uri); intent.setType("image/png" ); startActivity(intent);
3.通过浏览器打开网页 1 2 3 4 Uri uri = Uri.parse("https://www.baidu.com" ); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent);
4.发送电子邮件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Uri uri = Uri.parse("mailto:someone@domain.com" ); Intent intent = new Intent(Intent.ACTION_SENDTO, uri); startActivity(intent); Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, "someone@domain.com" ); intent.putExtra(Intent.EXTRA_SUBJECT, "Subject" ); intent.putExtra(Intent.EXTRA_TEXT, "Hello" ); intent.setType("text/plain" ); startActivity(intent); Intent intent=new Intent(Intent.ACTION_SEND); String[] tos = {"1@abc.com" , "2@abc.com" }; String[] ccs = {"3@abc.com" , "4@abc.com" }; String[] bccs = {"5@abc.com" , "6@abc.com" }; intent.putExtra(Intent.EXTRA_EMAIL, tos); intent.putExtra(Intent.EXTRA_CC, ccs); intent.putExtra(Intent.EXTRA_BCC, bccs); intent.putExtra(Intent.EXTRA_SUBJECT, "Subject" ); intent.putExtra(Intent.EXTRA_TEXT, "Hello" ); intent.setType("message/rfc822" ); startActivity(intent);
5.显示地图与路径规划 1 2 3 4 5 6 7 8 9 Uri uri = Uri.parse("geo:39.9,116.3" ); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=39.9 116.3&daddr=31.2 121.4" ); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent);
6.播放多媒体 1 2 3 4 5 6 7 8 Intent intent = new Intent(Intent.ACTION_VIEW); Uri uri = Uri.parse("file:///sdcard/foo.mp3" ); intent.setDataAndType(uri, "audio/mp3" ); startActivity(intent); Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1" ); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent);
7.选择图片 1 2 3 Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*" ); startActivityForResult(intent, 2 );
8.拍照 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, 1 ); Bundle extras = intent.getExtras(); Bitmap bitmap = (Bitmap) extras.get("data" ); Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*" ); intent.putExtra("crop" , "true" ); intent.putExtra("aspectX" , 1 ); intent.putExtra("aspectY" , 2 ); intent.putExtra("outputX" , 20 ); intent.putExtra("outputY" , 40 ); intent.putExtra("output" , Uri.fromFile(new File("/mnt/sdcard/temp" ))); intent.putExtra("outputFormat" , "JPEG" ); startActivityForResult(intent, 0 ); Intent intent = new Intent("com.android.camera.action.CROP" ); intent.setClassName("com.android.camera" , "com.android.camera.CropImage" ); intent.setData(Uri.fromFile(new File("/mnt/sdcard/temp" ))); intent.putExtra("outputX" , 1 ); intent.putExtra("outputY" , 2 ); intent.putExtra("aspectX" , 20 ); intent.putExtra("aspectY" , 40 ); intent.putExtra("scale" , true ); intent.putExtra("noFaceDetection" , true ); intent.putExtra("output" , Uri.parse("file:///mnt/sdcard/temp" )); startActivityForResult(intent, 0 );
9.打开手机应用市场 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Uri uri = Uri.parse("market://details?id=" + packageName); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); String fileName = Environment.getExternalStorageDirectory() + "/myApp.apk" ; Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive" ); startActivity(intent); Uri uri = Uri.parse("package:" + packageName); Intent intent = new Intent(Intent.ACTION_DELETE, uri); startActivity(intent);
10.进入设置界面 1 2 3 Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS); startActivity(intent);
五.数据传递与回调 1.数据传递
发送数据的Activity,有两种发送数据的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Intent intent = new Intent(this ,SecondActivity.class); intent.putExtra("account" ,account_edit.getText().toString()); intent.putExtra("password" ,password_edit.getText().toString()); startActivity(intent); Bundle bundle = new Bundle(); bundle.putString("account" ,account_edit.getText().toString()); bundle.putString("password" ,password_edit.getText().toString()); intent.putExtras(bundle); startActivity(intent);
接受数据的Activity,也有两种接受数据的方法。但是任何一种接受方法都可以接受两种数据发送方法传来的数据。
1 2 3 4 5 6 7 8 Intent intent = this .getIntent(); String account = intent.getStringExtra("account" ); Bundle bundle = intent.getExtras(); String account = bundle.getString("account" );
2.数据回调 跳转后前一个Activity已经被destroy了。如若要返回并显示数据,就必须将前一个Activity再次唤醒,同时调用某个方法来获取并显示数据。
从A页面跳转到B页面时不可使用startActivity()方法,而要使用startActivityForResult()方法。
在A页面的Activity中,需要重写onActivityResult(int requestCode, int resultCode, Intent data)方法。
例子:
① A页面的Xml文件和Java代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <?xml version="1.0" encoding="utf-8"?> <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" tools:context =".MainActivity" android:orientation ="vertical" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="center" android:layout_marginTop="150dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="学号:" android:textSize="20sp" /> <EditText android:id="@+id/edit_account" android:layout_width="200dp" android:layout_height="wrap_content" android:inputType="number" /> </LinearLayout > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="center" android:layout_marginTop="20dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密码:" android:textSize="20sp" /> <EditText android:id="@+id/edit_password" android:layout_width="200dp" android:layout_height="wrap_content" android:inputType="numberPassword" /> </LinearLayout > <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="login" android:layout_marginTop="20dp" /> <TextView android:id="@+id/textView" android:layout_gravity="center" android:layout_marginTop="60dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="接受回来的消息" android:textSize="20sp" /> </LinearLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public class MainActivity extends AppCompatActivity { EditText account_edit; EditText password_edit; TextView show_text; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); account_edit = findViewById(R.id.edit_account); password_edit = findViewById(R.id.edit_password); show_text = findViewById(R.id.textView); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick (View v) { jump(); } }); } private void jump () { Intent intent = new Intent(this ,SecondActivity.class); intent.putExtra("account" ,account_edit.getText().toString()); intent.putExtra("password" ,password_edit.getText().toString()); startActivityForResult(intent,1 ); } @Override protected void onActivityResult (int requestCode, int resultCode, @Nullable Intent data) { if (requestCode == 1 && resultCode == RESULT_OK){ show_text.setText("学生昵称:" +data.getStringExtra("name" ) + " " +"专业代码:" + data.getStringExtra("major" )); } super .onActivityResult(requestCode, resultCode, data); } }
② B页面的Xml文件和Java代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 <?xml version="1.0" encoding="utf-8"?> <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" tools:context =".MainActivity" android:orientation ="vertical" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="100dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="学号:" android:textSize="20sp" /> <TextView android:id="@+id/account_text" android:layout_width="200dp" android:layout_height="wrap_content" android:textSize="20sp" android:textAlignment="center"/> </LinearLayout > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="center" android:layout_marginTop="20dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="姓名:" android:textSize="20sp" /> <EditText android:id="@+id/edit_name" android:layout_width="200dp" android:layout_height="wrap_content" /> </LinearLayout > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="center" android:layout_marginTop="20dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="专业:" android:textSize="20sp" /> <EditText android:id="@+id/edit_major" android:layout_width="200dp" android:layout_height="wrap_content" /> </LinearLayout > <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="返回" android:layout_marginTop="20dp" /> </LinearLayout >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class SecondActivity extends AppCompatActivity { EditText name_edit; EditText major_edit; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_second); name_edit = findViewById(R.id.edit_name); major_edit = findViewById(R.id.edit_major); Intent intent = this .getIntent(); String account = intent.getStringExtra("account" ); TextView accountText = findViewById(R.id.account_text); accountText.setText(account); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick (View v) { close(); } }); } private void close () { Intent intent = new Intent(); intent.putExtra("name" , name_edit.getText().toString()); intent.putExtra("major" , major_edit.getText().toString()); this .setResult(RESULT_OK, intent); this .finish(); } }
③ 代码很简单,我们直接看运行效果就好。
源码:https://github.com/xiaoshitounen/Intent
六. 传递自定义数据 1. 实现Serializable接口 implements Serializable接口的的作用就是给对象打了一个标记,系统会自动将其序列化。不需要实现方法。
弊端:
Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable类。
2.实现Parcelable接口 参考:Intent传递对象——Serializable和Parcelable区别
参考:Activity之间传递参数(使用Parcelable和Serializable接口传递复杂类型)
参考:Android开发之使用Intent进行自定义类型数据传输
3. 实现Parcelable接口例子 ① 传递的自定义类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 package swu.xl.linkgame.Model;import android.os.Parcel;import android.os.Parcelable;import org.litepal.crud.LitePalSupport;public class XLLevel extends LitePalSupport implements Parcelable { private int l_id; private int l_time; private char l_mode; private char l_new; private int l_money; public int getL_id () { return l_id; } public void setL_id (int l_id) { this .l_id = l_id; } public int getL_time () { return l_time; } public void setL_time (int l_time) { this .l_time = l_time; } public char getL_mode () { return l_mode; } public void setL_mode (char l_mode) { this .l_mode = l_mode; } public char getL_new () { return l_new; } public void setL_new (char l_new) { this .l_new = l_new; } public int getL_money () { return l_money; } public void setL_money (int l_money) { this .l_money = l_money; } @Override public String toString () { return "XLLevel{" + "l_id=" + l_id + ", l_time=" + l_time + ", l_mode=" + l_mode + ", l_new=" + l_new + ", l_money=" + l_money + '}' ; } @Override public int describeContents () { return 0 ; } @Override public void writeToParcel (Parcel dest, int flags) { dest.writeInt(l_id); dest.writeInt(l_time); dest.writeCharArray(new char []{l_mode,l_new}); dest.writeInt(l_money); } public static final Creator<XLLevel> CREATOR = new Creator<XLLevel>() { @Override public XLLevel createFromParcel (Parcel in) { XLLevel xlLevel = new XLLevel(); xlLevel.l_id = in.readInt(); xlLevel.l_time = in.readInt(); char [] temp = new char [2 ]; in.readCharArray(temp); xlLevel.l_mode = temp[0 ]; xlLevel.l_new = temp[1 ]; xlLevel.l_money = in.readInt(); return xlLevel; } @Override public XLLevel[] newArray(int size) { return new XLLevel[size]; } }; }
② 数据开始界面
1 2 3 4 5 6 7 8 9 10 11 Intent intent_easy = new Intent(this , LevelActivity.class); Bundle bundle = new Bundle(); bundle.putString("mode" ,"简单" ); bundle.putParcelableArrayList("levels" , (ArrayList<? extends Parcelable>) XLLevels1); intent_easy.putExtras(bundle); startActivity(intent_easy);
③ 数据跳转到的界面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Intent intent = this .getIntent(); Bundle bundle = intent.getExtras(); assert bundle != null ;mode = bundle.getString("mode" ); levels = bundle.getParcelableArrayList("levels" ); Log.d(Constant.TAG,"--------" ); Log.d(Constant.TAG,mode); assert levels != null ;Log.d(Constant.TAG,levels.size()+"" ); for (XLLevel xlLevel : levels) { Log.d(Constant.TAG,xlLevel.toString()); }
参考文章 Android Intent用法总结 - 简书
Intent界面跳转与传递数据