源码地址:https://github.com/ldy1993/ToolforAS.git
这一节,我们尽量理解activity_intent、intent-filter、Context的原理。如果是初学者可以了解一下AndroidManifest.xml中activity标签下intent-filter对启动activity的意义。
1.1、activity的启动方式和意图
意图对象 :Intent是一个将要执行的动作的抽象的描述,由Intent来协助完成android各个组件之间的通讯,具有激活组件和携带数据的功能。
显式意图:明确指定组件名的Intent为显式意图,指定了Intent应该传递给那个组件。
隐式意图:没有明确指定组件名的Intent为隐式意图,系统会根据隐式意图中设置的 动作(action)、类别(category)、数据URI等来匹配最合适的组件。
意图激活组件和携带数据的功能列表
1.1.1、动作(Action)
intent.setAction(Intent.ACTION_CALL);
1.1.2、数据(Data)
intent.setData(Uri.parse("tel:" + 123456));
1.1.3、类别
1.1.4、附加数据
这是传递给需要处理意图的组件的以键值对描述的附加信息。通过 putExtras() 方法设置,getExtras() 方法读取
1.1.5、标记
这些标记是意图的可选部分,说明Android系统如何来启动活动,启动后如何处理等。如下
1 FLAG_ACTIVITY_CLEAR_TASK :如果在意图中设置,并通过 Context.startActivity 传递,这个标记将导致与该活动相关联的所有已存在的任务在活动启动前被清空。活动将成为一个空任务的根,所有旧的活动被结束。该标记可以与 FLAG_ACTIVITY_NEW_TASK 结合使用。
2 FLAG_ACTIVITY_CLEAR_TOP :如果设置该标记,活动将在当前运行的任务中被启动。这病不会启动一个新的活动实例,所有的在它之上的活动被关闭,这个意图作为一个新的意图被传递到已有的(目前在顶部的)活动。
3 FLAG_ACTIVITY_NEW_TASK :这个标记一般用于使得活动用于"启动器"风格的行为:为用户提供一个可以独立完成运行的数据,并启动完整儿独立的活动。
1.1.6、组件名称
组件名称对象是一个可选的域,代表活动、服务或者广播接收器类。如果设置,则意图对象被传递到实现设计好的类的实例,否则,Android 使用其他意图中的其他信息来定位一个合适的目标。组件名称通过 setComponent(),setClass()或者 setClassName() 来设置,通过 getComponent() 获取。
ComponentName compName = new ComponentName(SysParams.PACKAGE_NAME, SysParams.MAIN_ACTIVITY);
intent.setComponent(compName);
意图过滤器:intent-filter
<!--Android 系统拨号器的清单文件-->
<activity android:name="OutgoingCallBroadcaster"
android:permission="android.permission.CALL_PHONE"
android:theme="@android:style/Theme.NoDisplay"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.CALL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
<intent-filter android:icon="@drawable/ic_launcher_sip_call">
<action android:name="android.intent.action.CALL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sip" />
</intent-filter>
</activity>
1.1.7、Action
一个Intent只能是一个动作,但是一个Intent-Filter可以有一个或者多个action进行过滤。Intent只需要匹配一个就可了。
1.1.8、Data
[0] scheme 属性设置参数过滤
[1] Data可以有零个或者多个;
[2] 如果Intent-Filter 没有设置Data 那么Intent也必须没有Data才行
[3] 如果Internet-Filter 没有设置 mimeType 那么只需要对应 Data 即可
[4] 如果设置了mimeType那么必须Data和Type都对应才行
1.1.9、Category
指定在什么样子的环境下动作才会被响应,
app第一次启动时响应
<category android:name="android.intent.category.LAUNCHER"/>
按下home键时响应
<category android:name="android.intent.category.HOME" />
备注:一些系统例子
parse方法返回的是一个URI类型,通过这个URI可以访问一个网络上或者是本地的资源
1,调web浏览器
Uri myBlogUri = Uri.parse("http://www.baidu.com");
returnIt = new Intent(Intent.ACTION_VIEW, myBlogUri);
2,地图
Uri mapUri = Uri.parse("geo:38.899533,-77.036476");
returnIt = new Intent(Intent.ACTION_VIEW, mapUri);
3,调拨打电话界面
Uri telUri = Uri.parse("tel:100861");
returnIt = new Intent(Intent.ACTION_DIAL, telUri);
4,直接拨打电话
Uri callUri = Uri.parse("tel:100861");
returnIt = new Intent(Intent.ACTION_CALL, callUri);
5,卸载
Uri uninstallUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);
6,安装
Uri installUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);
7,播放
Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");
returnIt = new Intent(Intent.ACTION_VIEW, playUri);
8,调用发邮件
Uri emailUri = Uri.parse("mailto:xxxx@gmail.com");
returnIt = new Intent(Intent.ACTION_SENDTO, emailUri);
9,发邮件
returnIt = new Intent(Intent.ACTION_SEND);
String[] tos = { "xxxx@gmail.com" };
String[] ccs = { "xxxx@gmail.com" };
returnIt.putExtra(Intent.EXTRA_EMAIL, tos);
returnIt.putExtra(Intent.EXTRA_CC, ccs);
returnIt.putExtra(Intent.EXTRA_TEXT, "body");
returnIt.putExtra(Intent.EXTRA_SUBJECT, "subject");
returnIt.setType("message/rfc882");
Intent.createChooser(returnIt, "Choose Email Client");
10,发短信
Uri smsUri = Uri.parse("tel:100861");
returnIt = new Intent(Intent.ACTION_VIEW, smsUri);
returnIt.putExtra("sms_body", "yyyy");
returnIt.setType("vnd.android-dir/mms-sms");
11,直接发邮件
Uri smsToUri = Uri.parse("smsto://100861");
returnIt = new Intent(Intent.ACTION_SENDTO, smsToUri);
returnIt.putExtra("sms_body", "yyyy");
12,发彩信
Uri mmsUri = Uri.parse("content://media/external/images/media/23");
returnIt = new Intent(Intent.ACTION_SEND);
returnIt.putExtra("sms_body", "yyyy");
returnIt.putExtra(Intent.EXTRA_STREAM, mmsUri);
returnIt.setType("image/png");
13,与market相关:
1 //寻找某个应用
Uri uri = Uri.parse("market://search?q=pname:pkg_name");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
//where pkg_name is the full package path for an application
2 //显示某个应用的相关信息
Uri uri = Uri.parse("market://details?id=app_id");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
//where app_id is the application ID, find the ID
//by clicking on your application on Market home
//page, and notice the ID from the address bar
14,路径规划
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);
//where startLat, startLng, endLat, endLng are a long with 6 decimals like: 50.123456
15,安装指定apk
public void setupAPK(String apkname){
String fileName = Environment.getExternalStorageDirectory() + "/" + apkname;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(fileName)),"application/vnd.android.package-archive");
mService.startActivity(intent);
}
16,进入联系人界面
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(People.CONTENT_URI);
startActivity(intent);
17,查看指定联系人
Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);// info.id联系人ID
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(personUri);
startActivity(intent);
18,调用相册
public static final String MIME_TYPE_IMAGE_JPEG = "image/*";
public static final int ACTIVITY_GET_IMAGE = 0;
Intent getImage = new Intent(Intent.ACTION_GET_CONTENT);
getImage.addCategory(Intent.CATEGORY_OPENABLE);
getImage.setType(MIME_TYPE_IMAGE_JPEG);
startActivityForResult(getImage, ACTIVITY_GET_IMAGE);
19,调用系统相机程序,并存储照片
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
time = Calendar.getInstance().getTimeInMillis();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment
.getExternalStorageDirectory().getAbsolutePath()+"/tucue", time + ".jpg")));
startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE);
1.2、activity的上下文
Context提供了一个应用的运行环境,在Context的大环境里,应用 才以访问资源,才能完成和其他组件、服务的交互,Context定义了 一套基本的功能接口。
1.2.1、content的继承关系
Context ---> ContextImx
---> ContextWrpper ---> ContextThemeWrpper ---> Acitivity
---> Service
---> Application
通过图上我们可以看出:Activity类 、Service类 、Application类本质上都是Context子类。
1.2.2、不同组件的不同
首先看它们的继承关系,通过对比可以清晰地发现,Service和Application的类继承关系比较像,
而Activity还多了一层继承ContextThemeWrapper,这是因为Activity有主题的概念,而Service是没有界面的服务
`
,Application更是一个抽象的东西,它也是通过Activity类呈现的。Context的真正实现都在ContextImpl中,
也就是说Context的大部分方法调用都会转到ContextImpl中,而三者的创建均在ActivityThread中完成,Activity
启动的核心过程是在ActivityThread中完成的,这里要说明的是,Application和Service的创建也是在ActivityThread中完成的。