1page.title=將使用者傳送至其他應用程式
2page.tags=意圖
3helpoutsWidget=true
4
5trainingnavtop=true
6
7@jd:body
8
9
10<div id="tb-wrapper">
11  <div id="tb">
12
13<h2>本課程示範</h2>
14<ol>
15  <li><a href="#Build">建置隱含意圖</a></li>
16  <li><a href="#Verify">驗證存在接收意圖的應用程式</a></li>
17  <li><a href="#StartActivity">使用意圖啟動應用行為顯示</a></li>
18  <li><a href="#AppChooser">顯示應用程式選擇器</a></li>
19</ol>
20
21<h2>您也應該閱讀</h2>
22<ul>
23    <li><a href="{@docRoot}training/sharing/index.html">共用簡單資料</a></li>
24</ul>
25
26  </div>
27</div>
28
29<p>應用程式可以根據將要執行的「行為」,將使用者傳送至其他應用程式
30,這是 Android 最重要的功能之一。例如,若您希望在地圖上顯示應用程式中的企業地址,不必在應用程式中建置顯示地圖的應用行為顯示。
31
32您可以改為使用 {@link android.content.Intent} 建立檢視地址的要求。
33隨後,Android 系統會啟動能在地圖上顯示地址的應用程式。
34</p>
35
36<p>正如第一課<a href="{@docRoot}training/basics/firstapp/index.html">建置您的第一個應用程式</a>中所述,您必須使用意圖在您應用程式中的應用行為顯示之間進行導覽。您執行此作業時通常具有<em>明確意圖</em>,該意圖可定義您希望啟動的元件的確切類別名稱。
37
38
39但是,若您希望使用單獨的應用程式執行諸如「檢視地圖」等行為,則必須使用<em>隱含意圖</em>。
40</p>
41
42<p>本課程將為您展示如何針對特定行為建立隱含意圖,以及如何使用該意圖啟動在其他應用程式中執行該行為的應用行為顯示。
43</p>
44
45
46
47<h2 id="Build">建置隱含意圖</h2>
48
49<p>隱含意圖不會宣告要啟動元件的類別名稱,而是宣告要執行的行為。
50該行為將指定您希望執行的動作,例如<em>檢視</em>、<em>編輯</em>、<em>傳送</em>或<em>取得</em>項目。
51意圖通常還包括與行為關聯的資料,例如您希望檢視的地址或希望傳送的電子郵件。視您希望建立的意圖而定,該資料可能是 {@link android.net.Uri} 或其他多種資料類型的其中之一,意圖也可能完全不需要資料。
52
53
54</p>
55
56<p>若您的資料是 {@link android.net.Uri},可以使用簡單的 {@link
57android.content.Intent#Intent(String,Uri) Intent()} 建構函式來定義行為與資料。
58</p>
59
60<p>例如,以下範例將展示如何建立啟動電話的意圖 (使用 {@link
61android.net.Uri} 資料指定電話號碼):</p>
62
63<pre>
64Uri number = Uri.parse("tel:5551234");
65Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
66</pre>
67
68<p>您的應用程式透過呼叫 {@link android.app.Activity#startActivity
69startActivity()} 來呼叫該意圖時,電話應用程式會啟動對指定電話號碼的撥號。</p>
70
71<p>以下將展示其他一些意圖及其行為與 {@link android.net.Uri} 資料配對:
72</p>
73
74<ul>
75  <li>檢視地圖:
76<pre>
77// Map point based on address
78Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
79// Or map point based on latitude/longitude
80// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
81Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
82</pre>
83  </li>
84  <li>檢視網頁:
85<pre>
86Uri webpage = Uri.parse("http://www.android.com");
87Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
88</pre>
89  </li>
90</ul>
91
92<p>其他類型的隱含意圖需要「額外」資料提供其他資料類型 (例如字串)。
93您可以使用各種 {@link
94android.content.Intent#putExtra(String,String) putExtra()} 方法新增一或多項額外資料。</p>
95
96<p>依預設,系統會根據包括的 {@link android.net.Uri} 資料,判斷意圖所需的相應 MIME 類型。
97若您未將 {@link android.net.Uri} 包括在意圖中,通常應使用 {@link android.content.Intent#setType setType()} 指定意圖所關聯資料的類型。
98
99設定 MIME 類型會進一步指定哪些類型的應用行為顯示應接收意圖。
100</p>
101
102<p>以下展示的一些意圖將新增額外資料以指定所需行為:</p>
103
104<ul>
105  <li>傳送具有附件的電子郵件:
106<pre>
107Intent emailIntent = new Intent(Intent.ACTION_SEND);
108// The intent does not have a URI, so declare the "text/plain" MIME type
109emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
110emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
111emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
112emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
113emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
114// You can also attach multiple items by passing an ArrayList of Uris
115</pre>
116  </li>
117  <li>建立行事曆事件:
118<pre>
119Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
120Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
121Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
122calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
123calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
124calendarIntent.putExtra(Events.TITLE, "Ninja class");
125calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
126</pre>
127<p class="note"><strong>注意:</strong>針對行事曆事件的這一意圖僅支援至少為 14 的 API 級別。
128</p>
129  </li>
130</ul>
131
132<p class="note"><strong>注意:</strong>請儘可能具體地定義 {@link
133android.content.Intent},這一點非常重要。例如,若您希望使用 {@link android.content.Intent#ACTION_VIEW} 意圖顯示影像,應將 MIME 類型指定為 {@code image/*}。
134
135如此可防止意圖觸發能「檢視」其他類型資料的應用程式 (例如地圖應用程式)。
136</p>
137
138
139
140<h2 id="Verify">驗證存在接收意圖的應用程式</h2>
141
142<p>雖然 Android 平台保證特定意圖將解析為內建應用程式 (例如電話、電子郵件或日曆應用程式) 的其中之一,但您應一律先納入驗證步驟,然後再呼叫意圖。
143
144</p>
145
146<p class="caution"><strong>注意:</strong>若您呼叫意圖,而裝置上不提供能處理該意圖的任何應用程式,
147則您的應用程式將當機。</p>
148
149<p>若要驗證存在可回應意圖的應用行為顯示,請呼叫 {@link
150android.content.pm.PackageManager#queryIntentActivities queryIntentActivities()} 以取得能處理 {@link android.content.Intent} 的應用行為顯示清單。
151若傳回的 {@link
152java.util.List} 非空,您可以安全使用意圖。例如:</p>
153
154<pre>
155PackageManager packageManager = {@link android.content.Context#getPackageManager()};
156List<ResolveInfo> activities = packageManager.queryIntentActivities(intent,
157        PackageManager.MATCH_DEFAULT_ONLY);
158boolean isIntentSafe = activities.size() > 0;
159</pre>
160
161<p>若 <code>isIntentSafe</code> 為 <code>true</code>,則至少有一個應用程式將回應意圖。
162若其為 <code>false</code>,則沒有任何應用程式能處理該意圖。</p>
163
164<p class="note"><strong>注意:</strong>對於使用該意圖的功能,若您需要在使用者嘗試使用該功能之前停用該功能,應在您的應用行為顯示第一次啟動時,執行這項檢查。
165
166若您知道能處理該意圖的特定應用程式,還可為使用者提供應用程式下載連結 (請參閱如何<a href="{@docRoot}distribute/tools/promote/linking.html">在 Google
167Play 上連結您的產品</a>)。
168</p>
169
170
171<h2 id="StartActivity">使用意圖啟動應用行為顯示</h2>
172
173<div class="figure" style="width:200px;margin-top:-10px">
174  <img src="{@docRoot}images/training/basics/intents-choice.png" alt="" />
175  <p class="img-caption"><strong>圖 1.</strong>選取對話方塊 (在多個應用程式可處理意圖時顯示) 的範例。
176</p>
177</div>
178
179<p>在您建立 {@link android.content.Intent} 並設定額外資訊後,請呼叫 {@link
180android.app.Activity#startActivity startActivity()} 將其傳送至系統。若系統識別出有多個應用行為顯示可以處理意圖,會顯示對話方塊,供使用者選取要使用的應用程式,如圖 1 所示。
181
182若只有一個應用行為顯示可以處理該意圖,系統會立即啟動該應用行為顯示。
183</p>
184
185<pre>
186startActivity(intent);
187</pre>
188
189<p>以下所示的完整範例將展示如何建立檢視地圖的意圖、驗證存在處理該意圖的應用程式,然後啟動該應用程式:
190</p>
191
192<pre>
193// Build the intent
194Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
195Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
196
197// Verify it resolves
198PackageManager packageManager = {@link android.content.Context#getPackageManager()};
199List&lt;ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
200boolean isIntentSafe = activities.size() > 0;
201
202// Start an activity if it's safe
203if (isIntentSafe) {
204    startActivity(mapIntent);
205}
206</pre>
207
208
209
210<h2 id="AppChooser">顯示應用程式選擇器</h2>
211
212<div class="figure" style="width:200px;margin-top:-10px">
213  <img src="{@docRoot}images/training/basics/intent-chooser.png" alt="" />
214  <p class="img-caption"><strong>圖 2.</strong>選擇器對話方塊。</p>
215</div>
216
217<p>請注意,若您將 {@link android.content.Intent} 傳遞至 {@link
218android.app.Activity#startActivity startActivity()} 以啟動應用行為顯示,且有多個應用程式回應該意圖,則使用者可以選取依預設要使用的應用程式 (透過選取對話方塊底部的核取方塊,請參閱圖 1)。
219
220若在執行行為時使用者通常希望每次使用同一應用程式,例如開啟網頁 (使用者可能只使用一個網頁瀏覽器) 或拍攝相片 (使用者可能更喜歡使用一個相機),則此功能非常有用。
221
222</p>
223
224<p>但是,若有多個應用程式可以處理要執行的行為,且使用者可能更希望每次使用不同的應用程式 (例如對於「共用」行為,使用者可能會透過多個應用程式來共用項目),您應明確顯示選擇器對話方塊,如圖 2 所示。
225
226
227選擇器對話方塊會強制使用者選取行為每次使用的應用程式 (使用者無法選取行為的預設應用程式)。
228
229</p>
230
231<p>若要顯示選擇器,請使用 {@link
232android.content.Intent#createChooser createChooser()} 建立 {@link android.content.Intent},並將其傳遞至 {@link
233android.app.Activity#startActivity startActivity()}。例如:</p>
234
235<pre>
236Intent intent = new Intent(Intent.ACTION_SEND);
237...
238
239// Always use string resources for UI text.
240// This says something like "Share this photo with"
241String title = getResources().getString(R.string.chooser_title);
242// Create intent to show chooser
243Intent chooser = Intent.createChooser(intent, title);
244
245// Verify the intent will resolve to at least one activity
246if (intent.resolveActivity(getPackageManager()) != null) {
247    startActivity(chooser);
248}
249</pre>
250
251<p>以上範例會顯示對話方塊 (將回應意圖的應用程式清單傳遞至 {@link
252android.content.Intent#createChooser createChooser()} 方法),並使用提供的文字作為對話方塊的標題。
253</p>
254
255
256
257