一.Intent的介绍
Intent的中文意思是“意图,意向”,在Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,可以将Intent理解为不同组件之间通信的“媒介”专门提供组件互相调用的相关信息。
简单来说,Intent是系统各组件之间进行数据传递的数据负载者。当我们需要做一个调用动作,我们就可以通过Intent告诉Android系统来完成这个过程,Intent就是调用通知的一种操作。
二.Inten启动组件的方法
Intent可以启动一个Activity,也可以启动一个Service,还可以发起一个广播Broadcasts。
//启动一个Activity:
Context.startActivity(Intent intent);
//启动一个Service:
Context.startService(Intent service);
//绑定一个Service:
Context.bindService(Intent service, ServiceConnection conn, int flags);
//发送一个Broadcast:
Context.sendBroadcast(Intent intent);
Context.sendOrderedBroadcasts()
Context.sendStickyBroadcasts()
三.Intent的属性
Intent有以下几个属性:
动作(Action),数据(Data),分类(Category),类型(Type),组件(Compent)以及扩展信(Extra)。其中最常用的是Action属性和Data属性。
1.Intent的Action属性
Action是指Intent要完成的动作,是一个字符串常量。SDK中定义了一些标准的Action常量如下表所示。
Constant | Target component | Action |
---|---|---|
ACTION_CALL | activity | Initiate a phone call. |
ACTION_EDIT | activity | Display data for the user to edit. |
ACTION_MAIN | activity | Start up as the initial activity of a task, with no data input and no returned output. |
ACTION_SYNC | activity | Synchronize data on a server with data on the mobile device. |
ACTION_BATTERY_LOW | broadcast receiver | A warning that the battery is low. |
ACTION_HEADSET_PLUG | broadcast receiver | A headset has been plugged into the device, or unplugged from it. |
ACTION_SCREEN_ON | broadcast receiver | The screen has been turned on. |
ACTION_TIMEZONE_CHANGED | broadcast receiver | The setting for the time zone has changed. |
测试action:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
// 设置Intent Action属性
intent.setType("vnd.android.cursor.item/phone");
// 设置Intent Type 属性
//主要是获取通讯录的内容
startActivity(intent); // 启动Activity
2.Intent的Data属性
Intent的Data属性是执行动作的URI和MIME类型,不同的Action有不同的Data数据指定。比如:ACTION_EDIT Action应该和要编辑的文档URI Data匹配,ACTION_VIEW应用应该和要显示的URI匹配。
打开指定网页
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.google.com.hk"));
startActivity(intent);
3.Intent的Category属性
Intent中的Category属性是一个执行动作Action的附加信息。比如:CATEGORY_HOME则表示放回到Home界面,ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个。下表是SDK文档中关于Category的信息。
几个常见的category如下:
Intent.CATEGORY_DEFAULT(android.intent.category.DEFAULT)
//默认的category
Intent.CATEGORY_PREFERENCE(android.intent.category.PREFERENCE) //表示该目标Activity是一个首选项界面;
Intent.CATEGORY_BROWSABLE(android.intent.category.BROWSABLE)
//指定了此category后,在网页上点击图片或链接时,
//系统会考虑将此目标Activity列入可选列表,供用户选择以打开图片或链接。
在为Intent设置category时,应使用addCategory(String category)方法向Intent中添加指定的类别信息,来匹配声明了此类别的目标Activity。
Constant | Meaning |
---|---|
CATEGORY_BROWSABLE | The target activity can be safely invoked by the browser to display data referenced by a link — for example, an image or an e-mail message. |
CATEGORY_GADGET | The activity can be embedded inside of another activity that hosts gadgets. |
CATEGORY_HOME | The activity displays the home screen, the first screen the user sees when the device is turned on or when the HOME key is pressed. |
CATEGORY_LAUNCHER | The activity can be the initial activity of a task and is listed in the top-level application launcher. |
CATEGORY_PREFERENCE | The target activity is a preference panel. |
返回home:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);// 添加Action属性
intent.addCategory(Intent.CATEGORY_HOME);// 添加Category属性
startActivity(intent);// 启动Activity
4.Intent的Type属性
Intent的Type属性显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。在使用Intent进行匹配时,我们可以使用setType(String type)或者setDataAndType(Uri data, String type)来设置mimeType。
常见的MIME类型(通用型):
名称 | 格式 | MIME类型 |
---|---|---|
超文本标记语言文本 | .html | text/html |
xml文档 | .xml | text/xml |
XHTML文档 | .xhtml | application/xhtml+xml |
普通文本 | .txt | text/plain |
RTF文本 | .rtf | application/rtf |
PDF文档 | application/pdf | |
Microsoft Word文件 | .word | application/msword |
PNG图像 | .png | image/png |
GIF图形 | .gif | image/gif |
JPEG图形 | .jpeg,.jpg | image/jpeg |
au声音文件 | .au | audio/basic |
MIDI音乐文件 | mid,.midi | audio/midi,audio/x-midi |
RealAudio音乐文件 | .ra, .ram | audio/x-pn-realaudio |
MPEG文件 | .mpg,.mpeg | video/mpeg |
AVI文件 | .avi | video/x-msvideo |
GZIP文件 | .gz | application/x-gzip |
TAR文件 | .tar | application/x-tar |
任意的二进制数据 | application/octet-stream |
5.Intent的Compent属性
Intent的Compent属性指定Intent的的目标组件的类名称。通常 Android会根据Intent 中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。
发送activity:
Intent intent = new Intent();
// ComponentName com = new ComponentName(MainActivity.this,MyActivity.class);//方法一
ComponentName com = new ComponentName(
"com.example.testcomponent",
"com.example.testcomponent.MyActivity");//方法二
//第二个参数为activity,但包名需要写全
intent.setComponent(com);
String s = "This is a Test.";
intent.putExtra("id", s);
startActivity(intent);
接收activity:
text = (TextView)findViewById(R.id.text);
Intent intent = getIntent();
String str = intent.getStringExtra("id");
ComponentName com = intent.getComponent();
String pkgName = com.getPackageName();
String className = com.getClassName();
text.setText(str + "\n" + pkgName + "\n" + className);
效果:
6.Intent的Extra属性
Intent的Extra属性是添加一些组件的附加信息。比如,如果我们要通过一个Activity来发送一个Email,就可以通过Extra属性来添加subject和body。
进行关键字搜索
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, "android"); //关键字
startActivity(intent);
四.常见跳转:
打开相册:
void choosePhoto(){
/**
* 打开选择图片的界面
*/
Intent intent = new Intent(Intent.ACTION_PICK);
//或
//Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");//相片类型
//或
//Intent albumIntent = new Intent(Intent.ACTION_PICK, null);
//albumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
}
打开相机:
void takePhoto(){
/**
* 最后一个参数是文件夹的名称,可以随便起
*/
File file=new File(Environment.getExternalStorageDirectory(),"拍照");
if(!file.exists()){
file.mkdir();
}
/**
* 这里将时间作为不同照片的名称
*/
output=new File(file,System.currentTimeMillis()+".jpg");
/**
* 如果该文件夹已经存在,则删除它,否则创建一个
*/
try {
if (output.exists()) {
output.delete();
}
output.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
/**
* 隐式打开拍照的Activity,并且传入CROP_PHOTO常量作为拍照结束后回调的标志
* 将文件转化为uri
*/
imageUri = Uri.fromFile(output);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CROP_PHOTO);
}
返回结果:
public void onActivityResult(int req, int res, Intent data) {
switch (req) {
/**
* 拍照的请求标志
*/
case CROP_PHOTO:
if (res==RESULT_OK) {
try {
/**
* 该uri就是照片文件夹对应的uri
*/
Bitmap bit = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
imageView.setImageBitmap(bit);
} catch (Exception e) {
Toast.makeText(this,"程序崩溃",Toast.LENGTH_SHORT).show();
}
}
else{
Log.i("tag", "失败");
}
break;
/**
* 从相册中选取图片的请求标志
*/
case REQUEST_CODE_PICK_IMAGE:
if (res == RESULT_OK) {
try {
/**
* 该uri是上一个Activity返回的
*/
Uri uri = data.getData();
Bitmap bit = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
imageView.setImageBitmap(bit);
} catch (Exception e) {
e.printStackTrace();
Log.d("tag",e.getMessage());
Toast.makeText(this,"程序崩溃",Toast.LENGTH_SHORT).show();
}
}
else{
Log.i("liang", "失败");
}
break;
default:
break;
}
}
裁剪图片:
public void clipPhoto(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例,这里设置的是正方形(长宽比为1:1)
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 300);
intent.putExtra("outputY", 300);
intent.putExtra("return-data", true);
startActivityForResult(intent, CUT_OK);
}
五.显式意图与隐式意图
Intent的相关属性:
Intent由以下各个组成部分:
- component(组件):目的组件
- action(动作):用来表现意图的行动
- category(类别):用来表现动作的类别
- data(数据):表示与动作要操纵的数据
- type(数据类型):对于data范例的描写
- extras(扩展信息):扩展信息
- Flags(标志位):期望这个意图的运行模式
Intent类型分为显式Intent(直接类型)、隐式Intent(间接类型)。官方建议使用隐式Intent。
上述属性中,component属性为直接类型,其他均为间接类型。
相比与显式Intent,隐式Intnet则含蓄了许多,它并不明确指出我们想要启动哪一个活动,而是指定一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动。
Intent寻找目标组件的两种方式:
显式Intent:通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,一般是在相同的应用程序内部实现的。
隐式Intent:通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间。
显式Intent
一般情况下,一个Android应用程序中需要多个屏幕,即是多个Activity类,并且在这些Activity之间进行切换通过Intent机制来实现的。在同一个应用程序中切换Activity时,我们通常都知道要启动的Activity具体是哪一个,因此常用显式的Intent来实现的。
//显示方式声明Intent,直接启动SecondActivity
Intent it = new Intent(MainActivity.this,SecondActivity.class);
//启动Activity
startActivity(it);
隐式Intent
同一应用程序中的Activity切换,需要AndroidManifest.xml中增加Activity的声明,并设置对应的Intent Filter和Action,才能被Android的应用程序框架所匹配。
// 实例化Intent
Intent it = new Intent();
//设置Intent的Action属性
it.setAction("com.android.activity.MY_ACTION");
// 启动Activity
startActivity(it);
Manifest.xml文件
<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=".SecondActivity" >
<intent-filter>
<action android:name = "com.android.activity.MY_ACTION" />
<category android:name = "android.intent.category.DEFAULT" />
</intent-filter>
</activity>
对于显示Intent,Android不需要再去做解析,因为目标组件很明确。Android需要解析的是隐式Intent,通过解析,将Intent映射给可以处理该Intent的Activity,Service等。Intent的解析机制主要是通过查找已经注册在AndroidManifest.xml中的所有IntentFilter以及其中定义的Intent,最终找到匹配的Intent。
Intent常用调用代码
显示Web网页:
Uri uri = Uri.parse("http://www.android123.com.cn");
Intent it =new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);
显示Google地图:
Uri uri = Uri.parse("geo:38.899533,-77.036476");
Intent it =new Intent(Intent.Action_VIEW,uri);
startActivity(it);
Maps路径规划:
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");
Intent it =new Intent(Intent.ACTION_VIEW,URI);
startActivity(it);
拨打电话:
Uri uri = Uri.parse("tel:xxxxxx");
Intent it =new Intent(Intent.ACTION_DIAL, uri);
startActivity(it);
Uri uri = Uri.parse("tel.xxxxxx");
Intent it =new Intent(Intent.ACTION_CALL,uri);
注意需要权限
<uses-permission id="android.permission.CALL_PHONE"/>
发送SMS/MMS
Intent it =new Intent(Intent.ACTION_VIEW);
it.putExtra("sms_body", "android开发网欢迎您");
it.setType("vnd.android-dir/mms-sms");
startActivity(it);
发送短信
Uri uri = Uri.parse("smsto:10086");
Intent it =new Intent(Intent.ACTION_SENDTO, uri);
it.putExtra("sms_body", "10086"); //正文为10086
startActivity(it);
发送彩信
Uri uri = Uri.parse("content://media/external/images/media/10"); //该Uri根据实际情况修改,external代表外部存储即sdcard
Intent it =new Intent(Intent.ACTION_SEND);
it.putExtra("sms_body", "android123.com.cn");
it.putExtra(Intent.EXTRA_STREAM, uri);
it.setType("image/png");
startActivity(it);
发送Email
Uri uri = Uri.parse("mailto:android123@163.com");
Intent it =new Intent(Intent.ACTION_SENDTO, uri);
startActivity(it);
Intent it =new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_EMAIL, "android123@163.com");
it.putExtra(Intent.EXTRA_TEXT, "android开发网测试");
it.setType("text/plain");
startActivity(Intent.createChooser(it, "选择一个Email客户端"));
Intent it=new Intent(Intent.ACTION_SEND);
String[] tos={"android123@163.com"}; //发送到
String[] ccs={"ophone123@163.com"}; //抄送
it.putExtra(Intent.EXTRA_EMAIL, tos);
it.putExtra(Intent.EXTRA_CC, ccs);
it.putExtra(Intent.EXTRA_TEXT, "正文");
it.putExtra(Intent.EXTRA_SUBJECT, "标题");
it.setType("message/rfc822"); //编码类型
startActivity(Intent.createChooser(it, "选择一个Email客户端"));
Email添加附件
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_SUBJECT, "正文");
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/nobody.mp3"); //附件为sd卡上的nobody MP3文件
sendIntent.setType("audio/mp3");
startActivity(Intent.createChooser(it, "选择一个Email客户端"));
播放多媒体
Intent it = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/nobody.mp3");
it.setDataAndType(uri, "audio/mp3");
startActivity(it);
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1"); //从系统内部的MediaProvider索引中调用播放
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
Uninstall卸载程序
Uri uri = Uri.fromParts("package", packageName, null); //packageName为包名,比如com.android123.apkInstaller
Intent it = new Intent(Intent.ACTION_DELETE, uri);
startActivity(it);
进入联系人界面
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(People.CONTENT_URI);
startActivity(intent);
查看某个联系人,当然这里是 ACTION_VIEW ,如果为选择并返回 action 改为 ACTION_PICK ,当然处理intent 时返回需要用到 startActivityforResult
Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, ID);//最后的ID参数为联系人Provider中的数据库BaseID,即哪一行
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(personUri);
startActivity(intent);
选择一个图片
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, 0);
参考:
Android开发学习笔记:Intent的简介以及属性的详解
Android拍照,相册选择图片以及Android6.0权限管理
Android开发学习笔记:浅谈显示Intent和隐式Intent
使用Camera有两种方式:通过Intent使用已有的app和通过Camera构建自己的app。
Android Camera系列开发 (一): 通过Intent拍照
Android Camera系列开发 (二)通过Intent录制视频
Android Camera系列开发 (三): 通过CameraAPI拍照
Android 分享功能代码