您的位置:首页 > 其它

Intents and Intent Filters

2015-03-06 15:33 295 查看

Android API Guides

1. Intents 和Intent Filters

to start an Activity

startActivity or startActivityForResults


to start a service

startService or bindService


to deliever a broadcast

sendBroadcast, sendOrderedBroadcast or sendStickyBroadcast


1.1 Intent Types

Explicit intents

指定请求组件的全限定名,就包名+类名。

Implicit intents

申明通用的动作去执行,允许其他App处理该动作。

1.2 Building Intent

Component name

是决定该Intent是否为Explicit Intent,可通过
set Component(), setClass(), setClassName()
, 或者是作为Intent()的构造器的参数。若没指定该参数,则系统使用一下item进行匹配。其中Service必须指定Component Name。

Action

是一个String字符串,指定通用动作去执行,如View or Pick。该字段通常能够决定Intent的其他字段如何构造,尤其是在data域和extras域。可自定义Action,但更推荐使用系统提供的。以下为常用的Action, ACTION_VIEW(使用地图显示地址或使用相册显示图片),ACTION_SEND(使用其他App共享数据,诸如电子邮件或者社交网络共享).

可以通过setAction(),或者Intent的构造器进行指定。定义自己的ACTION,请加上包名,如下

static final String ACTION_TIMETR***EL = "com.example.action.TIMETR***EL";


Data

使用URI指定MIME类型的数据,通常需要指定数据类型。但是使用
content: URI
的URI数据,可不指定类型,因为系统可识别出该数据位于设备上,并且受到ContentProvider控制,因此MIME类型就变为可见。

指定方式为
setData(), setType() or setDataAndType()
,其中setData和setType不可同时使用,若需要,请使用setDataAndType()。

Category

一个String,包含可处理该Intent的组件种类。每个Intent可包含任意数量的Category,但大部分的Intent都不需要,通常设置为
android.intent.category.DEFAULT
。常见的Category:
CATEGORY_BROWSABLE
CATEGORY_LAUNCHER
。前者表示该数据可为浏览器打开,后者表示该Activity是一个任务的初始Activity,并且将会被显示在Launcher里。可用’addCategory()’来指定该项。

Tip 以上介绍的component name, action, data, 和category限定了一个intent的特性,Android系统可知道如何决定一个组件来处理或启动。

Extras

携带键值对信息,KV来完成特定的Action。可通过putExtras(K, V),或者创建一个Bundle携带所有的KVP,然后putExtras到Intent。指定自己的Extras Key,务必加上包名,如
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";


FLAG

定义Intent的元素据metadata,可指导Android系统如何启动一个Activity(task所属),或者启动后如何对待(是否属于其他已经启动的Activity)




1.2 Examples

Explicit Intent

[code]// 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);


Implicit Intent

模糊的Intent,可能会没有App响应,导致App Crash。因此可通过resolveActitvity()来验证是否有Activity响应,然后再决定是否启动Activity。

[code]// 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选择器

如分享文件或者数据到各种App,ACTION_SEND。可使用Intent的creatChooser来操作,如下:

[code]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);
}


1.3 Receiving an Implicit Intent

在Manifest文件中申明< intent-filters >标签,通过action, data, and category等字段制定Intent可接受的类型。

一个Explicit Intent无视组件所申明的接受Intent类型,直接传递过去。

不同job应申明不同的< intent-filters >,可包括action, data, and category3个字段。

-action, 指定可接受的intetn action。

-data,可接受的数据类型,URI (scheme, host, port, path, etc.) and MIME type。

-category,必须是一个Action的string值。

Tip: 为了收到Implicit Intents,必须设定
CATEGORY_DEFAULT
。这样, startActivity() and startActivityForResult() 才可调用,否则没有任何Implicit可启动该Activity。

举例:

[code]<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>


只有三个item都通过验证,Android才会传递Intent给该Activity。对于Broadcast Receiver,可通过
registerReceiver()
or
unregisterReceiver()
动态绑定。

- Example Filters

[code]<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>


1.4 Using a Pending Intent

它是对Intent的包装器,主要用途是给予其他App权限获取本进程的数据。主要用途如下:

Notification Manager

AppWidget

AlarmManager

由于每个Intent都是为特定的组件设计的,因此PendingIntent也同样。

PendingIntent.getActivity(),启动Activtiy

PendingIntent.getService(),启动Service

PendingIntent.getBroadcast(), 启动BroadcastReceiver()。

1.5 Intent Resolution

Android 系统匹配最优的组件的算法,基于以下三方面的匹配测试:

The intent action

The intent data (both URI and data type)

The intent category

其中data的URI 结构和MIME 类型。

URI:
<scheme>://<host>:<port>/<path>


ex:
content://com.example.project:200/folder/subfolder/etc


这4个元素是线性依赖的:

If a scheme is not specified, the host is ignored.

If a host is not specified, the port is ignored.

If both the scheme and host are not specified, the path is ignored.



PackageManager 可以调用以下几个方法列出可接受该Intent的组件

queryIntentActivities(), 返回所有相似的Activity

queryIntentServices(),返回相似的所有Service

queryIntentBroadcastReceivers(), 返回所有

1.6 Common Intents

1 AlarmClock

Action: ACTION_SET_ALARM

Extras:….

ex:

[code]public void createAlarm(String message, int hour, int minutes) {
    Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_HOUR, hour)
            .putExtra(AlarmClock.EXTRA_MINUTES, minutes);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


并其需要使用权限:

<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />


相应的Intent-Filter

[code]<activity ...>
    <intent-filter>
        <action android:name="android.intent.action.SET_ALARM" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>


2 Timer

Action:ACTION_SET_TIMER

Extras:。。。

e.g.

[code]public void startTimer(String message, int seconds) {
    Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


Permission:

<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />


Intent-Filter:

[code]<activity ...>
    <intent-filter>
        <action android:name="android.intent.action.SET_TIMER" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>


3 显示所有Alarms

Action:ACTION_SHOW_ALARMS

4 添加Calendar Event

Action:ACTION_INSERT

Data URI:Events.CONTENT_URI

MIME Type: “vnd.android.cursor.dir/event”

Extras: 。。。

4 拍摄照片或摄制录像

Action:ACTION_IMAGE_CAPTURE or ACTION_VIDEO_CAPTURE

Extras:EXTRA_OUTPUT

使用
onActivityResult()
接收返回数据:

[code]static final int REQUEST_IMAGE_CAPTURE = 1;
static final Uri mLocationForPhotos;

public void capturePhoto(String targetFilename) {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT,
            Uri.withAppendedPath(mLocationForPhotos, targetFilename);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        Bitmap thumbnail = data.getParcelable("data");
        // Do other work with full size photo saved in mLocationForPhotos
        ...
    }
}


相应的Intent-Filter

[code]<activity ...>
    <intent-filter>
        <action android:name="android.media.action.IMAGE_CAPTURE" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>


5 Start a camera app in still image mode

Action: INTENT_ACTION_STILL_IMAGE_CAMERA

6 Start a camera app in video mode

Action: INTENT_ACTION_VIDEO_CAMERA

7 选择一个联系人

Action:ACTION_PICK

MIME Type:Contacts.CONTENT_TYPE

e.g.:

[code]static final int REQUEST_SELECT_CONTACT = 1;

public void selectContact() {
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_SELECT_CONTACT);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_SELECT_CONTACT && resultCode == RESULT_OK) {
        Uri contactUri = data.getData();
        // Do something with the selected contact at contactUri
        ...
    }
}


8 选择特定的联系人

Action: ACTION_PICK

MIME Type:

CommonDataKinds.Phone.CONTENT_TYPE。Pick from contacts with a phone number.

CommonDataKinds.Email.CONTENT_TYPE,Pick from contacts with an email address.

CommonDataKinds.StructuredPostal.CONTENT_TYPE,Pick from contacts with a postal address.

[code]static final int REQUEST_SELECT_PHONE_NUMBER = 1;

public void selectContact() {
    // Start an activity for the user to pick a phone number from contacts
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType(CommonDataKinds.Phone.CONTENT_TYPE);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == RESULT_OK) {
        // Get the URI and query the content provider for the phone number
        Uri contactUri = data.getData();
        String[] projection = new String[]{CommonDataKinds.Phone.NUMBER};
        Cursor cursor = getContentResolver().query(contactUri, projection,
                null, null, null);
        // If the cursor returned is valid, get the phone number
        if (cursor != null && cursor.moveToFirst()) {
            int numberIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER);
            String number = cursor.getString(numberIndex);
            // Do something with the phone number
            ...
        }
    }
}


9 显示一个联系人

ACTION_PICK返回的contactURI,然后使用ACTION_VIEW查看。

直接访问联系人列表,需要READ_CONTACTS权限

[code]public void viewContact(Uri contactUri) {
    Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


10 编辑一个联系人

Action:ACTION_EDIT

URI: 之前ACTION_PICK返回的contactURI。

Extras:ContactsContract.Intents.Insert中定义的条目都可编辑

[code]public void editContact(Uri contactUri, String email) {
    Intent intent = new Intent(Intent.ACTION_EDIT);
    intent.setData(contactUri);
    intent.putExtra(Intents.Insert.EMAIL, email);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


11 插入一个联系人

Action:ACTION_INSERT

MIME Type:Contacts.CONTENT_TYPE

Extras:One or more of the extras defined in ContactsContract.Intents.Insert.

e.g.:

[code]public void insertContact(String name, String email) {
    Intent intent = new Intent(Intent.ACTION_INSERT);
    intent.setType(Contacts.CONTENT_TYPE);
    intent.putExtra(Intents.Insert.NAME, name);
    intent.putExtra(Intents.Insert.EMAIL, email);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


12 Email

13 File Storage

14 Fitness

15 Local Actions

16 Maps, show a location on a map

Action: ACTION_VIEW

URI: geo:latitude,longtitude

e.g.:

[code]public void showMap(Uri geoLocation) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setData(geoLocation);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


intent filter:

[code]<activity ...>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="geo" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>


17 MUSIC or VIDEO

Action: ACTION_VIEW

Data URI Scheme:

file:

content:

http:

MIME Type:

“audio/*”

“application/ogg”

“application/x-ogg”

“application/itunes” Or any other that your app may require.

example intent filter:

[code]<activity ...>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <data android:type="audio/*" />
        <data android:type="application/ogg" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>


18 Phone

Action: ACTION_DIAL , ACTION_CALL

其中ACTION_DIAL,需要传输一个号码,然后跳转到拨打界面,需要点击拨打按钮。

而ACTION_CALL,需要传输一个号码,然后直接开始拨打,但是需要权限

<uses-permission android:name="android.permission.CALL_PHONE" />


Data URI Scheme:’tel:< phone-number>,voicemail:< phone-number>’

e.g.:

[code]public void dialPhoneNumber(String phoneNumber) {
    Intent intent = new Intent(Intent.ACTION_DIAL);
    intent.setData(Uri.parse("tel:" + phoneNumber));
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


19 Settings

Action:

ACTION_SETTINGS ACTION_WIRELESS_SETTINGS

ACTION_AIRPLANE_MODE_SETTINGS ACTION_WIFI_SETTINGS

ACTION_APN_SETTINGS ACTION_BLUETOOTH_SETTINGS ACTION_DATE_SETTINGS

ACTION_LOCALE_SETTINGS ACTION_INPUT_METHOD_SETTINGS

ACTION_DISPLAY_SETTINGS ACTION_SECURITY_SETTINGS

ACTION_LOCATION_SOURCE_SETTINGS ACTION_INTERNAL_STORAGE_SETTINGS

ACTION_MEMORY_CARD_SETTINGS

20 Text Messaging

Action: ACTION_SENDTO, ACTION_SEND, ACTION_SEND_MULTIPLE

Data URI Scheme:

[code]sms:<phone_number>
smsto:<phone_number>
mms:<phone_number>
mmsto:<phone_number>


MIME Type:

PLAIN_TEXT_TYPE (“text/plain”)

“image/*”

“video/*”

Extras:

“subject”,’sms_body’,’EXTRA_STREAM’

e.g.:

[code]public void composeMmsMessage(String message, Uri attachment) {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setType(HTTP.PLAIN_TEXT_TYPE);
    intent.putExtra("sms_body", message);
    intent.putExtra(Intent.EXTRA_STREAM, attachment);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


若想要确保intent被短信应用处理,使用 ACTION_SENDTO,并且设置data schmem为‘smsto:’.

相应的Intent-filter

[code]<activity ...>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <data android:type="text/plain" />
        <data android:type="image/*" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>


21. WebBrowser

加载网址

- Action: ACTION_VIEW

- Data URI Scheme:

http:< URL>

https:< URL>

- MIME Type:

PLAIN_TEXT_TYPE (“text/plain”)

“text/html”

“application/xhtml+xml”

“application/vnd.wap.xhtml+xml”

Web查询

Action: ACTION_WEB_SEARCH

Extras:SearchManager.QUERY The search string.

[code]public void searchWeb(String query) {
    Intent intent = new Intent(Intent.ACTION_SEARCH);
    intent.putExtra(SearchManager.QUERY, query);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}


22 Verify Intents with the Android Debug Bridge

Set up an Android device for development, or use a virtual device.

Install a version of your app that handles the intents you want to support.

Fire an intent using adb:

adb shell am start -a <ACTION> -t <MIME_TYPE> -d <DATA> \ 

-e <EXTRA_NAME> <EXTRA_VALUE> -n <ACTIVITY>


For example:

adb shell am start -a android.intent.action.DIAL \ 

-d tel:555-5555 -n org.example.MyApp/.MyActivity


If you defined the required intent filters, your app should handle the intent.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: