【android学习】重要组件-intent

时间:2023-02-10 15:30:32

1,概念

意图,意向。
在android中用Intent机制来协助应用间的交互与通讯。
Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。
Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。

1)优点

减少组件间的耦合。
使用Intent可以激活Android应用的三个核心组件:活动、服务和广播接收器。

2)Intent可传递数据类型

①8种基本数据类型及其数组

②String/CharSequence实例类型的数据及数组

String实现了Serializable。

③实现了Serializable的对象及数组

如:File。

④实现了Parcelable的对象及数组

3)分类

①显式意图

调用Intent.setComponent()或Intent.setClass()方法明确指定了组件名的Intent为显式意图,显式意图明确指定了Intent应该传递给哪个组件。

指明明确的activity路径:

Intent intent=new Intent(this,TestActivity.class);
intent.setData(Uri.parse(fileUrl));
startActivity(intent);
Intent intent=new Intent();
intent.setClassName(context.getPackageName(),
com.google.sample.TestActivity”);
startActivity(intent);
Intent intent=new Intetn();
intent.setComponent(new ComponentName(context.getPackageName(),
"com.google.sample.TestActivity"));
startActivity(intent);

②隐式意图

没有明确指定组件名的Intent为隐式意图。 Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。

通过这种方式来启动发送短信的activity:

Intent intent=new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT,textMessage);
intent.setType("text/plain");
startActivity(intent);

2,场景

1)启动一个Activity

①切换当前界面到NcActivity.class

Intent intent = new Intent(mContext, NcActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

②读取APK存储路径并自动安装

Intent intent = new Intent(Intent.ACTION_VIEW);
// 设置intent的data和Type属性。
intent.setDataAndType(
FileUtils.getUriFromFile(Url.apkPath + Url.apkName),
"application/vnd.android.package-archive");
startActivity(intent);

2)启动一个Service

①startService方法

serviceIntent = new Intent(this, HttpService.class);
startService(serviceIntent);
stopService(serviceIntent);

②bindService方法

3)发起一个广播Broadcasts

①sendBroadcasts方法

            Intent intent = new Intent();
intent.setAction("cn.login");

Bundle bundle = new Bundle();
bundle.putString("username", userName);
bundle.putString("password",Password);
bundle.putString("server", Server);
bundle.putInt("port", Port);
intent.putExtras(bundle);

sendBroadcast(intent);

②sendOrderedBroadcasts方法

③sendStickyBroadcasts方法

4)传递数据

①数据跳转

Intent intent = new Intent(this, BActivity.class);
intent.putExtra("Intent_msg","传送数据的信息");//字符串
intent.putExtra("mInt",4);//int
intent.putExtra("person_data", person); //传递对象 Person implements Serializable
intent.startActivity(intent);

BActivity接收数据:

Intent intent = getIntent();
String msg = intent.getStringExtra("Intent_msg");
int i = intent.getIntExtra("mInt", 0);
Person person = (Person) getIntent().getSerializableExtra("person_data");

②Bundle绑定数据跳转

Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("username","小明");
bundle.putString("userpsw","123456");
intent.putExtras(bundle);
intent.setClass(this, BActivity.class);
startActivity(intent);

获取Intent对象,取得Bundle中的数据:

Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String username = bundle.getString("username");
intent.setClass(this, BActivity.class);

③数据返回跳转

使用startActivityForResult,AActivity跳转至BActivity,BActivity返回信息给AActivity。
注意:
所有需要传递或接收的 Activity 不允许设置launchmode="SingleTask"属性,或只能设为标准模式,否则系统将在 startActivityForResult() 后,还没等到被调用的 Activity 返回,就直接调用 onActivityResult()。

i>AActivity:

Intent intent = new Intent();
intent.setClass(this, BActivity.class);
startActivityForResult(intent,reqest_code);//reqest_code为请求码

在onActivityResult方法中接收并处理返回的信息。其中,参数:
–requestCode 请求码,即调用startActivityForResult() 传递过去的值
–resultCode 结果码,结果码用于标识返回数据来自哪个新Activity

protected void onActivityResult(int requestCode,int resultCode,Intent data){

switch(requestCode){//requestCode为回传的标记
case OK:
Bundle b = data.getExtras();//data为BActivity中回传的Intent
String msg = b.getString("responeMsg");
break;
default:break;
}
}

如果是在Fragment中接收数据,则为:

public class b extends Fragment{ 

***
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (resultCode != Activity.RESULT_OK) {
return;
}
break;

default:
break;
}

}
***
}

ii>BActivity:

        Intent mIntent = new Intent();  
mIntent.putExtra("change01", "1000");
// 设置结果,并进行传送
this.setResult(resultCode, mIntent);

5)显示用户数据

详细见下文action讲解。

用于在浏览器浏览这个网址:

Intent intent = new Intent(Intent.ACTION.VIEW,Uri.parse("http://mail.google.com"))

打开系统拍照


/**
* 拍照
*/

public void takePhoto() {
Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

File vFile = FileUtil.getImageFile();

Uri cameraUri = Uri.fromFile(vFile);
openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraUri);
((Activity) context).startActivityForResult(openCameraIntent, Variable.TAKE_PICTURE);
}
package com.luo.util;

import java.io.File;

import android.os.Environment;

public class FileUtil {

public static String ImagePath = "";
public static File getImageFile(){
File vFile = new File(Environment.getExternalStorageDirectory() + "/myimage/",
String.valueOf(System.currentTimeMillis()) + ".jpg");
if (!vFile.exists()) {
File vDirPath = vFile.getParentFile();
vDirPath.mkdirs();
} else {
if (vFile.exists()) {
vFile.delete();
}
}
ImagePath = vFile.getPath();

return vFile;
}
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Variable.TAKE_PICTURE:
String path = FileUtil.ImagePath;
List<ImageBean> mData = new ArrayList<ImageBean>();

if (mData.size() < Variable.MAX_IMAGE_SIZE && resultCode == -1 && !TextUtils.isEmpty(path)) {
ImageBean item = new ImageBean();
item.sourcePath = path;
mData.add(item);
}


initData(mData);
initview();
break;
}
}

默认情况下,即不需要指定intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);照相机有自己默认的存储路径,拍摄的照片将返回一个缩略图。如果想访问原始图片,可以通过dat extra能够得到原始图片位置。
如果指定了目标uri,data就没有数据,如果没有指定uri,则data就返回有数据!

3,属性:

1)动作(Action)

指Intent要完成的动作,是一个字符串常量。

①Intent.ACTION_MAIN

标识Activity为一个程序的开始。

<activity android:name=".Main" android:label="@string/app_name">  
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

②Intent.ACTION_VIEW

用于显示用户的数据。根据用户的数据类型打开相应的Activity。

//浏览器 
Uri uri = Uri.parse("http://www.google.com");
//拨号程序
Uri uri =Uri.parse("tel:1232333");
//打开地图定位
Uri uri=Uri.parse("geo:39.899533,116.036476");
//路径规划
Uri uri = Uri.parse("http://maps.google.com/maps?f=dsaddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");


Intent intent = new Intent(Intent.ACTION_VIEW,uri);
startActivity(intent );

播放视频:

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/media.mp4");
intent.setDataAndType(uri, "video/*");
startActivity(intent);

调用发送短信的程序:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra("sms_body", "信息内容...");
intent.setType("vnd.android-dir/mms-sms");
startActivity(intent );

显示应用详细列表 :

Uri uri = Uri.parse("market://details?id=app_id");         
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);

③Intent.ACTION_BUG_REPORT

显示Dug报告。

④Intent.Action_CALL_BUTTON

相当于用户按下“拨号”键。显示为“通话记录”。

Intent intent = new Intent(Intent.ACTION_CALL_BUTTON);
startActivity(intent);

⑤Intent.ACTION_CHOOSER

显示一个activity选择器,允许用户在进程之前选择他们想要的。

⑥Intent.ACTION_GET_CONTENT

允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音)
输入:Type
输出:URI

int requestCode = 1001;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*"); // 查看类型,如果是其他类型,比如视频则替换成 video/*,或 */*
Intent wrapperIntent = Intent.createChooser(intent, null);
startActivityForResult(wrapperIntent, requestCode);
//选择图片 requestCode 返回的标识
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(contentType);//查看类型 String IMAGE_UNSPECIFIED = "image/*";
Intent wrapperIntent = Intent.createChooser(intent, null);
((Activity) context).startActivityForResult(wrapperIntent, requestCode);
//添加音频
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(contentType);//String VIDEO_UNSPECIFIED = "video/*";
Intent wrapperIntent = Intent.createChooser(intent, null);
((Activity) context).startActivityForResult(wrapperIntent, requestCode);
//拍摄视频 
int durationLimit = getVideoCaptureDurationLimit(); //SystemProperties.getInt("ro.media.enc.lprof.duration", 60);
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, sizeLimit);
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationLimit);
startActivityForResult(intent, REQUEST_CODE_TAKE_VIDEO);
//视频
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(contentType); //String VIDEO_UNSPECIFIED = "video/*";
Intent wrapperIntent = Intent.createChooser(intent, null);
((Activity) context).startActivityForResult(wrapperIntent, requestCode);
//录音
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(ContentType.AUDIO_AMR); //String AUDIO_AMR = "audio/amr";
intent.setClassName("com.android.soundrecorder","com.android.soundrecorder.SoundRecorder");
((Activity) context).startActivityForResult(intent, requestCode);
//拍照 REQUEST_CODE_TAKE_PICTURE 为返回的标识
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //"android.media.action.IMAGE_CAPTURE";
intent.putExtra(MediaStore.EXTRA_OUTPUT, Mms.ScrapSpace.CONTENT_URI); // output,Uri.parse("content://mms/scrapSpace");
startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE);

⑦Intent.Action.DIAL

调用拨号面板,添加指定的电话号码。

打开Android的拨号UI。如果没有设置数据,则打开一个空的UI,如果设置数据,action.DIAL则通过调用getData()获取电话号码。
输入:电话号码,数据格式为:tel:+phone number

Intent intent=new Intent(); 
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:1800010001");
startActivity(intent);

⑧Intent.Action_CALL

呼叫指定的电话号码。
输入:电话号码,数据格式为:tel:+phone number

Intent intent=new Intent(); 
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:1800010001");
startActivity(intent);

⑨Intent.ACTION_SENDTO、Intent.ACTION_SEND

ACTION_SEND 传递数据,被传送的数据没有指定,接收的action请求用户发数据
ACTION_SENDTO 发送一跳信息到指定的某人

//发送短信息 
Uri uri = Uri.parse("smsto:13200100001");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
intent .putExtra("sms_body", "信息内容...");
startActivity(intent );
//发送彩信,设备会提示选择合适的程序发送 Uri uri = Uri.parse("content://media/external/images/media/23");
//设备中的资源(图像或其他资源)
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra("sms_body", "内容");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("image/png");
startActivity(it);
//Email Intent intent=new Intent(Intent.ACTION_SEND); 
String[] tos={"android1@163.com"};
String[] ccs={"you@yahoo.com"};
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_TEXT, "The email body text");
intent.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
intent.setType("message/rfc822");
startActivity(Intent.createChooser(intent, "Choose Email Client"));

⑩Intent.ACTION_ANSWER

处理呼入的电话。

⑪ Intent.Action.ALL_APPS

列出所有的应用

⑫Intent.ACTION_ATTACH_DATA

用于指定一些数据应该附属于一些其他的地方,例如,图片数据应该附属于联系人

⑬Intent.ACTION_WEB_SEARCH

从google搜索内容 :

Intent intent = new Intent(); 
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,"searchString")
startActivity(intent);

⑭Intent.ACTION_DELETE

卸载。

Uri uri = Uri.fromParts("package", strPackageName, null);    
Intent it = new Intent(Intent.ACTION_DELETE, uri);
startActivity(it);

⑮Intent.ACTION_PACKAGE_ADDED

安装。

Uri installUri = Uri.fromParts("package", "xxx", null); 
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

⑯ Intent.ACTION_INSERT_OR_EDIT

调用系统编辑添加联系人:

Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); 
intent.setType(People.CONTENT_ITEM_TYPE);
intent.putExtra(Contacts.Intents.Insert.NAME, "My Name");
intent.putExtra(Contacts.Intents.Insert.PHONE, "+1234567890");
intent.putExtra(Contacts.Intents.Insert.PHONE_TYPE, Contacts.PhonesColumns.TYPE_MOBILE);
intent.putExtra(Contacts.Intents.Insert.EMAIL, "com@com.com");
intent.putExtra(Contacts.Intents.Insert.EMAIL_TYPE, Contacts.ContactMethodsColumns.TYPE_WORK);
startActivity(intent);

ACTION_INSERT:插入一条空项目到已给的容器 。
ACTION_EDIT:访问已给的数据,提供明确的可编辑

⑰其他

ACTION_RUN 运行数据
ACTION_SYNC 同步执行一个数据
ACTION_PICK_ACTIVITY 为已知的Intent选择一个Activity,返回选中的类
ACTION_PICK 从数据中选择一个子项目,并返回你所选中的项目
ACTION_FACTORY_TEST 工场测试的主要进入点

2)数据(Data)

执行动作的URI和MIME(或mimeType)类型,不同的Action又不同的Data数据指定。

MIME(或mimeType)指媒体类型,如:image/jpeg、audio/mpeg4-generic和video/*等,可以表示图片、文本、视频等。

3)类别(Category)

执行动作Action的附加信息。

4)数据类型(Type)

指定Intent的数据类型(MIME)。
一般的Intent的数据类型根据数据本身判定,通过设置这个属性,强制采用显示指定类型。

5)组件(Compent)

指定Intent的目标组件的类名称。
通常android会根据Intent中包含的其它属性的信息进行查找,最终找到一个与之相配的目标组件。通过设置这个属性,将直接使用它指定的组件。

6)扩展信(Extras)

添加一些组件的附加信息。
比如用Activity发送Email,可以通过此属性来添加subject和body。

举例:传递参数(用于2个activity)
i>在发送Intent的activity中,添加键值对:

intent.putExtra("NAME","luo");

ii>在接受Intent的activity中,取值:

Intent intent = getIntent();
String Str_name = intent.getStringExtra("NAME");

iii>传递列表

intent.putExtra(
VariableUtil.EXTRA_IMAGE_LIST,
(Serializable) new ArrayList<ImageItem>selectedImgs.values()));
intent.getSerializableExtra(VariableUtil.EXTRA_IMAGE_LIST);

4,Intent解析机制

通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。
在这个解析过程中,Android是通过Intent的action、type和category三个属性来进行判断的。
1)如果Intent指定了action,则目标组件的IntentFilter的action列表中就必须包含这个action,否则不能匹配。
2)如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。
3)如果Intent中的数据不是content类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme 如 http: 或者mailto:进行匹配。(Intent的scheme必须出现在目标组件的scheme列表中)
4)如果Intent指定了一个或多个category,这些类别必须全部出现在组件的类别列表中。如Intent中包含了两个类别:LAUNCHER_CATEGORY和ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。