Intent&IntentFilter

Intent 是一个消息传递对象,你可以使用它进行组件之间的消息传递。Intent一般应用于以下三个方面:

start Activity:通过startActivity或者startAcivityForResult启动Activity并在Intent中附带数据;

start Service:通过startService或者bindService启动Serivce并在Intent中后附带数据;

send Broadcast:通过sendBroadcast、sendOrderedBroadcast或者sendStickyBroadcast发送广播并在Intent附带数据。

Intent分为显示意图和隐式意图两种:

显示意图:在启动其他组件时直接指定相关组件的名字。你只能在自己app中启动其他Activity或者Serivce等使用显示意图,因为这样才可以知道相关组件的名字(类名)。

// 采用显示意图的方式启动Activity
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent demoIntent = new Intent(MainActivity.this, Main2Activity.class);
        startActivity(demoIntent);
    }
}

隐式意图:隐式意图是另一种方式Intent,它通过声明一个通用的action来执行,一般用于不同app之间的组件之间的交互,或者对多个响应指定action的应用程序进行选择。当你创建隐式意图的时候,Android系统通过将意图的内容与在设备上其他应用程序的清单文件中声明的意图过滤器进行比较来找到合适的组件,如果Intent与Intent-Filter相匹配,系统将启动该组件并交付其意图对象。如果多个Intent-Filter是兼容的,系统会显示一个对话框,这样用户就可以选择使用哪个应用。


// 隐式意图启动Activity
public class Main2Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        Intent demoIntent = new Intent();
        demoIntent.setAction("com.example.action.STARTACTIVITY"); //AndroidManifest.xml中指定启动组件Intent-Filter中的action
        startActivity(demoIntent);
    }
}

// 清单文件中的定义:
<activity android:name=".Main3Activity">
    <intent-filter>
    <action android:name="com.example.action.STARTACTIVITY"/>
</intent-filter>
</activity>

如果你定义自己的action,一定要把你的应用程序的包名作为前缀。例如com.example.action. STARTACTIVITY。




隐式意图的传递方式

Intent的创建:Intent主要包括component name 、action、data、minetype、category、extras以及flags数据。Intent通过这些数据来确定那个组件响应此Intent,以及传递数据到该响应的组件上进行处理。
component name:被启动的组件名称,被用于显示意图启动组件,组件名称可以使用目标组件的完全限定类名指定,包括应用程序的包名。如com.example.ExampleActivity.Class,或者如上显示意图启动组件示例代码,你可以设置组件名称通过setComponent、setClass、setClassName以及在Intent构造函数中。
action:指定要执行的通用action的字符串。被用于隐式意图启动组件。在广播意图中,action是一种正在发生的action,并被广播出去,广播接受者可以根据action相应该次广播。并且通过action的构造可以大致知道它包含的data和extras数据的含义。你可以定义自己的action在app中(其他组件可以通过此action启动你的app),也可以使用Intent类或其他框架类定义的action常量:如:ACTION_VIEW、ACTION_SEND等。
Data:data是一种URI类型(Uri对象)并且还包括data的minetype类型。Data的类型和action有很大关系。例如:action是ACTION_EDIT,则data应该包含一个可以编辑的文档。可以通过setData设置数据,该数据可以通过getData得到。可以通过setType设置mineType。既设置data又设置mineType需要通过setDataAndType方法进行设置。
    Category:包含组件类型的附加信息的字符串,任何Category的类别描述都可以放在一个意图中,但是大多数意图不需要一个Category。它可以通过addCategory进行设置。
CATEGORY_LAUNCHER:标示该Activity是一个任务的初始Activity,并在系统的应用程序启动中列出。
Extras:Intent携带的附加数据,不会影响Intent和组件的IntentFilter的匹配。它可以通过putExtras和getExtras方法进行存取,携带的数据是Bundle类型,该类型的数据相当于HashMap中的键值对。
Flags:意图类中定义的Flags,作为意图的元数据,标志可指示 Android 系统如何启动activity,以及该activity所在的任务栈。它可以通过setFlags方法进行设置。
显示意图:
一个显式的意图是你用来启动一个特定的应用组件,比如你的应用中的某个活动或服务。为了创建一个明确的意图,定义意图对象的组件名称——所有其他意图属性都是可选的。例如,如果您在您的应用程序中创建了一个名为DownloadService的服务,该服务旨在从web上下载一个文件,那么您可以使用以下代码来启动它:


// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

Intent(Context, Class)构造器提供应用程序上下文和组件一个类对象。因此,这个意图在应用程序中显式地启动了下载服务类。
隐式意图:隐式意图指定可以调用设备上的任何应用程序执行该action的操作。当你的应用无法执行action时,,但其他应用可能可以,因此使用隐式意图是很有用的。
例如,如果你有内容你想与其他人分享,用ACTION_SEND动作创建一个意图,并且增加你想要分享饿内容到extras中。当你采用该Intent意图startActivity时,用户可以选择一个应用程序来共享内容。
注意:如果你的隐式意图没有任何的应用程序匹配响应,那你的程序就会崩溃,因此需要爱调用resolveActivity方法如下示例代码:

// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); // "text/plain" MIME type

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

如果你的隐式意图被一个app响应那就直接打开此app,如果被多个app响应,那就需要用户手动选择打开。(系统已经实现此种选择对话框)。

Forcing an app chooser:
如果多个应用程序能够响应意图,用户可能希望每次使用不同的应用程序,那么您应该显式地显示一个选择器对话框,选择器对话框要求用户每次选择要使用的应用程序,例如,当您的应用程序用ACTION_SEND action执行“共享”时,用户可能想要根据他们当前的情况共享一个不同的应用程序,因此您应该始终使用选择器对话框,如图2所示。



一个选择器对话框

要显示选择器,请使用createChoser()创建一个意图,并将其传递给startActivity()。例如:

Intent intent = new Intent(Intent.ACTION_SEND);
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);

// Verify the intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

这将显示一个对话框,其中有一个应用程序列表,这些应用程序响应将传递给createChooser()方法的意图,并使用所提供的文本作为对话框标题。
为了通知你的应用可以接收到的隐式意图,在你的清单文件中,为每个应用组件声明一个或多个意图过滤器。每个意图过滤器根据意图的action、data和category指定它接受的意图的类型。只有当意图可以通过你的一个意图过滤器时,系统才会向你的应用程序组件传递一个隐式的意图。
备注:一个显式的意图总是被交付给它的目标组件,不管组件声明的任何意图过滤器。
应用程序组件应该为每个独立的任务声明单独的过滤器。例如,图像库应用程序中的一个activity可能有两个过滤器:一个用于查看图像的过滤器,另一个用于编辑图像的过滤器。当activity开始时,它检查意图并根据意图中的信息决定何种行为(例如显示或者编辑)。
每个意图过滤器都是在应用程序的清单文件中定义的元素,嵌套在相应的应用程序组件中(例如: activity元素)。在每个意图过滤器中,您可以指定使用这三个元素中的一个或多个来接受意图的类型。
action:声明了在name属性中接受的意图操作。值必须是操作的文字字符串值,而不是类常量。
data:声明所接受的数据类型,使用一个或多个属性,这些属性指定数据URI的各个方面scheme, host, port, path等)和MIME类型
category:在name属性中声明了意图类别。值必须是操作的文字字符串值,而不是类常量。
注意:在使用startActivity和startActivityForResult方法启动Activity时,Intent-Filter中的category属性必须包含CATEGORY_DEFAULT值,不然该组件接收不到,隐式意图。
例如,这里有一个Activity声明,其中有一个意图过滤器,当数据类型为文本时,它将接收ACTION_SEND意图。

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

当您想要处理多个类型的意图时,但是只在action,data和 category的特定组合中,那么您需要创建多个意图过滤器。其中一个意图过滤器可以包含多个action,data和 category。
通过将意图过滤器与意图的action,data和 category这三个元素进行比较,可以对过滤器进行测试。要交付给组件,意图必须通过所有三个测试。如果连其中一个都无法匹配,Android系统就无法实现组件的意图。然而,由于一个组件可能有多个意图过滤器,一个不通过一个组件的过滤器的意图可能会通过另一个过滤器。
对于所有的Activity,您必须在manifest文件中声明您的意图过滤器。而对于广播接受者你可以在代码中动态注册和取消注册意图过滤器。registerReceiver()和unregisterReceiver()。这样的话,只有执行到注册代码时,过滤器才会生效。
为了更好地理解一些意图过滤行为,请从社交共享应用程序的清单文件中查看下面的代码片段。

<activity android:name="MainActivity">
    <!-- This activity is the main entry, should appear in app launcher -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- This activity handles "SEND" actions with text data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="application/vnd.google.panorama360+jpg"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>

第一个Activity是MainActivity,它是应用的主要入口点,当用户开始使用启动器图标启动应用时,它会打开。 
ACTION_MAIN表明这是主入口点,并且不期望任何意图数据;
CATEGORY_LAUNCHER表示该Activity的图标应该放置在系统的应用启动器中,以便被系统启动。
如果<Activity>元素中是没有指定Activity的图标,那它就使用<application>中的图标。
为了让MainActivity在系统的app launcher中,当点击应用程序图标就被启动,这两个必须结合在一起。
第二个Activity,ShareActivity,旨在促进文本和媒体内容的共享。它可以直接从MainActivity中直接启动也可以通过其他app采用隐式意图的方式,间接启动。
当系统收到一个隐式意图来启动一个Activity时,它会根据三个方面来比较意图和意图过滤器来搜索意图的最佳Activity。Intent的action、data(URI和data type)以及category。


<intent-filter>
<action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
<data android:mimeType="video/mpeg" android:scheme="http" ... />
    <data android:mimeType="audio/mpeg" android:scheme="http" ... />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" /> 
</intent-filter>

在Intent中,对于action、data以及category都只需要匹配其中之一。Android会自动将CATEGORY_DEFAULT应用到所有的隐式意图中,并将其传递给startActivity()和startActivityForResult(),如果你想让你的Activity得到隐式意图,它必须包括一个category为“android.intent.category.DEFAULT”其意图过滤器(如前面的<intent-filter>所示的例子。Data中包括mimeType和URI两种,URI包括<scheme>://<host>:<port>/<path>如:

content://com.example.project:200/folder/subfolder/etc,在URI中,scheme是content,host是com.example.project,port是200,path是/folder/subfolder/etc。

注意:如果它的过滤器只列出MIME类型,那么就可以假定它支持content:和file:数据。

PendingIntent延迟的Intent

它是把Intent包裹在PendingIntent对象中,当某个事件出现再执行Intent。

它获得的方式主要分为以下三种:

PendingIntent.getActivity() Inent启动一个 Activity。

PendingIntent.getService() Intent启动一个Service。

PendingIntent.getBroadcast() Intent发送一个广播 BroadcastReceiver。

常用于Notification、App Widget以及Alarm中。具体怎么用见这三个的相关文档。

下面列出一些系统通用的Intent:Create an alarm、Create a timer、Show all alarms、Add a calendar event、Camera:Capture a picture orvideo and return it、Contacts/PeopleApp:Selecta contact、Selectspecific contact data、Viewa contact、Editan existing contact、Inserta contact、Email:Compose an email withoptional attachments、FileStorage:Retrievea specific type of file、Opena specific type of file、Maps:Show a location on amap、Musicor Video:Playa media file、Playmusic based on a search query、Phone:Initiate a phone call、Open a specificsection of Settings、TextMessaging:Composean SMS/MMS message with attachment、Web Browser:Load a web URL、Perform a web search、

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值