Intent
เป็นออบเจ็กต์การรับส่งข้อความที่คุณใช้เพื่อขอการดำเนินการได้
จากคอมโพเนนต์ของแอปอื่น
แม้ว่า Intent จะอำนวยความสะดวกในการสื่อสารระหว่างองค์ประกอบต่างๆ หลายวิธี แต่มีสามวิธี
กรณีการใช้งานพื้นฐาน
- การเริ่มกิจกรรม
Activity
หมายถึงหน้าจอเดียวในแอป คุณสามารถเริ่ม ของActivity
โดยการส่งIntent
ไปยังstartActivity()
Intent
อธิบายกิจกรรมที่จะเริ่มต้นและเก็บข้อมูลที่จำเป็นหากต้องการรับผลลัพธ์จากกิจกรรมเมื่อดำเนินการเสร็จแล้ว ให้โทรหา
startActivityForResult()
กิจกรรมของคุณจะได้รับผลลัพธ์เป็นออบเจ็กต์Intent
แยกต่างหากในonActivityResult()
Callback ของกิจกรรม ดูข้อมูลเพิ่มเติมได้ที่คู่มือกิจกรรม - การเริ่มบริการ
Service
เป็นคอมโพเนนต์ที่ทำงานอยู่เบื้องหลัง โดยไม่ต้องมีอินเทอร์เฟซผู้ใช้ คุณเริ่มบริการด้วยJobScheduler
ได้หากใช้ Android 5.0 (API ระดับ 21) ขึ้นไป หากต้องการดูข้อมูลเพิ่มเติม เกี่ยวกับJobScheduler
โปรดดูAPI-reference documentation
สำหรับเวอร์ชันที่เก่ากว่า Android 5.0 (API ระดับ 21) คุณจะเริ่มต้นบริการได้โดยใช้เมธอดของคลาส
Service
คุณสามารถเริ่มบริการเพื่อดําเนินการแบบครั้งเดียว (เช่น การดาวน์โหลดไฟล์) ได้โดยส่งIntent
ให้กับstartService()
Intent
จะอธิบายบริการที่จะเริ่มต้นและนําข้อมูลที่จําเป็นหากบริการออกแบบให้มีอินเทอร์เฟซแบบไคลเอ็นต์-เซิร์ฟเวอร์ คุณจะเชื่อมโยงกับบริการจากคอมโพเนนต์อื่นได้โดยส่ง
Intent
ไปยังbindService()
ดูข้อมูลเพิ่มเติมได้ในคู่มือบริการ - การส่งออกการออกอากาศ
การประกาศคือข้อความที่แอปใดก็ตามสามารถรับได้ ระบบจะออกอากาศต่างๆ สําหรับเหตุการณ์ของระบบ เช่น เมื่อระบบบูตขึ้นหรืออุปกรณ์เริ่มชาร์จ คุณสามารถส่งการออกอากาศไปยังแอปอื่นๆ ได้โดยส่ง
Intent
ไปยังsendBroadcast()
หรือsendOrderedBroadcast()
ส่วนที่เหลือของหน้านี้จะอธิบายวิธีการทํางานและวิธีใช้ Intent สำหรับข้อมูลที่เกี่ยวข้อง โปรดดู การโต้ตอบกับแอปอื่นๆ และการแชร์เนื้อหา
ประเภท Intent
Intent มี 2 ประเภท ได้แก่
- Intent แบบเจาะจงปลายทางระบุว่าคอมโพเนนต์ใดของแอปพลิเคชันที่จะตอบสนองต่อ Intent นั้น โดยระบุ
ComponentName
แบบเต็ม โดยทั่วไป คุณจะใช้ Intent ที่ชัดเจนเพื่อเริ่มคอมโพเนนต์ในแอปของคุณเอง เนื่องจากคุณทราบชื่อคลาสของกิจกรรมหรือบริการที่ต้องการเริ่ม ตัวอย่างเช่น คุณอาจเริ่มกิจกรรมใหม่ภายในแอปเพื่อตอบสนองต่อการกระทำของผู้ใช้ หรือเริ่มบริการเพื่อดาวน์โหลดไฟล์ในเบื้องหลัง - Intent แบบไม่เจาะจงปลายทางจะไม่ตั้งชื่อคอมโพเนนต์ที่เฉพาะเจาะจง แต่ประกาศการดำเนินการทั่วไปที่จะทำแทน ซึ่งช่วยให้คอมโพเนนต์จากแอปอื่นจัดการได้ ตัวอย่างเช่น หากต้องการแสดงตำแหน่งบนแผนที่ให้ผู้ใช้เห็น คุณสามารถใช้ Intent ที่ไม่ชัดแจ้งเพื่อขอให้แอปอื่นที่สามารถทำได้แสดงตำแหน่งที่ระบุบนแผนที่
รูปที่ 1 แสดงวิธีการใช้ Intent เมื่อเริ่มกิจกรรม เมื่อ
ออบเจ็กต์ Intent
ตั้งชื่อคอมโพเนนต์กิจกรรมที่เจาะจงอย่างชัดเจน ระบบ
คอมโพเนนต์ดังกล่าวจะเริ่มทำงานทันที

รูปที่ 1 เจตนาโดยนัย
ที่ส่งผ่านระบบเพื่อเริ่มกิจกรรมอื่น: [1] กิจกรรม A จะสร้าง
Intent
พร้อมคำอธิบายการดำเนินการและส่งไปยัง startActivity()
[2] ระบบ Android ค้นหาทั้งหมด
แอปสำหรับตัวกรอง Intent ที่ตรงกับ Intent เมื่อพบรายการที่ตรงกัน [3] ระบบจะเริ่มกิจกรรมที่ตรงกัน (กิจกรรม ข) โดยการเรียกใช้เมธอด onCreate()
และส่ง Intent
ไปให้
เมื่อคุณใช้ Intent ที่ไม่ชัด ระบบ Android จะค้นหาคอมโพเนนต์ที่เหมาะสมเพื่อเริ่มต้นโดยเปรียบเทียบเนื้อหาของ Intent กับตัวกรอง Intent ที่ประกาศไว้ในไฟล์ Manifest ของแอปอื่นๆ ในอุปกรณ์ หาก Intent ตรงกับตัวกรอง Intent ระบบจะเริ่มคอมโพเนนต์นั้นและส่งออบเจ็กต์ Intent
หากตัวกรอง Intent หลายรายการใช้งานร่วมกันได้ ระบบจะ
แสดงกล่องโต้ตอบเพื่อให้ผู้ใช้เลือกแอปที่จะใช้
ตัวกรอง Intent คือนิพจน์ในไฟล์ Manifest ของแอปที่ ระบุประเภทของ Intent ที่คอมโพเนนต์ ต้องการได้รับ เช่น ด้วยการประกาศตัวกรอง Intent สำหรับกิจกรรม ทำให้แอปอื่นๆ สามารถเริ่มกิจกรรมได้โดยตรงด้วยความตั้งใจบางอย่าง ในทำนองเดียวกัน หากคุณไม่ได้ประกาศตัวกรอง Intent สำหรับกิจกรรม ตัวกรองดังกล่าวก็เริ่มต้นใช้งานได้ ด้วยเจตนาที่ชัดแจ้งเท่านั้น
ข้อควรระวัง: ใช้ Intent แบบชัดแจ้งเสมอเมื่อเริ่ม Service
และอย่าประกาศตัวกรอง Intent สําหรับบริการของคุณ เพื่อให้แอปปลอดภัย การใช้ Intent แบบไม่เจาะจงปลายทางเพื่อเริ่มบริการเป็น
เนื่องจากคุณไม่สามารถแน่ใจได้ว่าบริการใดจะตอบสนองต่อจุดประสงค์นั้น
และผู้ใช้ไม่สามารถเห็นได้ว่าบริการใดเริ่มทำงานบ้าง ใน Android 5.0 (API ระดับ 21) ระบบจะเลือกใช้
จะมีข้อยกเว้นหากคุณโทรหา bindService()
โดยมีเจตนาโดยนัย
การสร้าง Intent
ออบเจ็กต์ Intent
ประกอบด้วยข้อมูลที่ระบบ Android ใช้เพื่อพิจารณาว่าควรเริ่มคอมโพเนนต์ใด (เช่น ชื่อคอมโพเนนต์ที่แน่นอนหรือหมวดหมู่คอมโพเนนต์ที่ควรได้รับ Intent) รวมถึงข้อมูลที่คอมโพเนนต์ฝั่งที่รับใช้เพื่อดําเนินการอย่างถูกต้อง (เช่น การดำเนินการที่จะทำและข้อมูลที่จะดำเนินการ)
ข้อมูลหลักที่อยู่ใน Intent
มีดังนี้
- ชื่อคอมโพเนนต์
- ชื่อของคอมโพเนนต์ที่จะเริ่มต้น
ขั้นตอนนี้เป็นขั้นตอนที่ไม่บังคับ แต่เป็นข้อมูลสำคัญที่ช่วยสร้างความตั้งใจ Explicit ซึ่งหมายความว่าควรแสดง Intent ไปยังคอมโพเนนต์ของแอปเท่านั้น กำหนดโดยชื่อคอมโพเนนต์ หากไม่มีชื่อคอมโพเนนต์ Intent จะเป็น implicit และ ระบบจะพิจารณาว่าคอมโพเนนต์ใดควรได้รับ Intent โดยพิจารณาจากข้อมูล Intent อื่นๆ (เช่น การกระทำ ข้อมูล และหมวดหมู่ตามที่อธิบายไว้ด้านล่าง) หากคุณต้องการเริ่มต้น คอมโพเนนต์ในแอป คุณควรระบุชื่อคอมโพเนนต์
หมายเหตุ: เมื่อเริ่ม
Service
ให้ระบุชื่อคอมโพเนนต์เสมอ ไม่เช่นนั้นคุณจะไม่สามารถมั่นใจได้ว่าบริการใดจะตอบสนองต่อ Intent และผู้ใช้จะไม่เห็นบริการใดเริ่มทำงานช่องนี้ของ
Intent
จะเป็นออบเจ็กต์ComponentName
ซึ่งคุณระบุได้โดยใช้ชื่อคลาสแบบเต็มของคอมโพเนนต์เป้าหมาย รวมถึงชื่อแพ็กเกจของแอป เช่นcom.example.ExampleActivity
คุณสามารถตั้งชื่อคอมโพเนนต์ด้วยsetComponent()
,setClass()
,setClassName()
หรือใช้คอนสตรคเตอร์Intent
- การดำเนินการ
- สตริงที่ระบุการดำเนินการทั่วไปที่จะดำเนินการ (เช่น ดูหรือเลือก)
ในกรณีของ Intent การออกอากาศ ข้อมูลนี้คือการดำเนินการที่เกิดขึ้นและกำลังได้รับการรายงาน การดำเนินการเป็นตัวกำหนดโครงสร้างของ Intent ที่เหลือส่วนใหญ่ โดยเฉพาะข้อมูลที่อยู่ในข้อมูลและส่วนเสริม
คุณสามารถระบุการดำเนินการของคุณเองเพื่อใช้กับ Intent ภายในแอป (หรือเพื่อใช้โดยแอปอื่นๆ เพื่อเรียกใช้คอมโพเนนต์ในแอป) แต่โดยปกติแล้วคุณจะระบุค่าคงที่การดำเนินการที่กําหนดโดยคลาส
Intent
หรือคลาสเฟรมเวิร์กอื่นๆ การดำเนินการทั่วไปสำหรับการเริ่มกิจกรรมมีดังนี้ACTION_VIEW
- ใช้การดำเนินการนี้ใน Intent กับ
startActivity()
เมื่อคุณมีข้อมูลบางอย่างที่ กิจกรรมสามารถแสดงต่อผู้ใช้ เช่น รูปภาพที่จะดูในแอปแกลเลอรี หรือที่อยู่ที่จะ ดูในแอปแผนที่ ACTION_SEND
- หรือที่เรียกว่า Intent share คุณควรใช้ Intent นี้ใน Intent ที่มี
startActivity()
เมื่อคุณมีข้อมูลบางอย่างที่ผู้ใช้แชร์ผ่านแอปอื่นได้ เช่น แอปอีเมลหรือแอปการแชร์โซเชียล
ดูรายการค่าคงที่เพิ่มเติมที่กําหนดการดําเนินการทั่วไปได้ในข้อมูลอ้างอิงคลาส
Intent
มีการกำหนดการดำเนินการอื่นๆ ที่อื่นๆ ในเฟรมเวิร์ก Android เช่น ในSettings
สำหรับการดำเนินการ ที่เปิดหน้าจอที่เจาะจงในแอปการตั้งค่าของระบบคุณระบุการดำเนินการสำหรับ Intent ได้ด้วย
setAction()
หรือด้วยตัวสร้างIntent
หากคุณกำหนดการดำเนินการของคุณเอง อย่าลืมใส่ชื่อแพ็กเกจของแอปเป็นคำนำหน้า ดังตัวอย่างต่อไปนี้
- ข้อมูล
- URL (ออบเจ็กต์
Uri
) ที่อ้างอิงข้อมูล ดำเนินการและ/หรือ ประเภท MIME ของข้อมูลนั้น โดยทั่วไป ประเภทข้อมูลที่ระบุจะกำหนดโดยการดำเนินการของ Intent สำหรับ เช่น หากการดำเนินการคือACTION_EDIT
ข้อมูลควรมี URI ของเอกสารที่จะแก้ไขเมื่อสร้าง Intent สิ่งสำคัญคือต้องระบุประเภทข้อมูล (ประเภท MIME) นอกเหนือจาก URI ตัวอย่างเช่น กิจกรรมที่สามารถแสดงภาพได้คงไม่สามารถ เพื่อเล่นไฟล์เสียง แม้ว่ารูปแบบ URI อาจคล้ายกันก็ตาม การระบุประเภท MIME ของข้อมูลจะช่วยให้ระบบ Android ค้นหาคอมโพเนนต์ที่เหมาะสมที่สุดเพื่อรับ Intent ของคุณ อย่างไรก็ตาม บางครั้งประเภท MIME สามารถอนุมานได้จาก URI โดยเฉพาะอย่างยิ่งเมื่อข้อมูลเป็น URI
content:
URIcontent:
บ่งบอกว่าข้อมูลอยู่ในอุปกรณ์ และควบคุมโดยContentProvider
ซึ่งทำให้ระบบมองเห็นประเภท MIME ของข้อมูลหากต้องการตั้งค่าเฉพาะ URI ข้อมูล ให้เรียก
setData()
หากต้องการตั้งค่าเฉพาะประเภท MIME ให้เรียกใช้setType()
หากจำเป็น คุณสามารถตั้งค่าทั้ง 2 รายการอย่างชัดเจนด้วยsetDataAndType()
ข้อควรระวัง: หากต้องการตั้งค่าทั้ง URI และประเภท MIME ให้อย่าเรียกใช้
setData()
และsetType()
เนื่องจากค่าของกันและกันจะลบล้างกัน ใช้setDataAndType()
เสมอเพื่อตั้งค่าทั้ง 2 แบบ URI และ ประเภท MIME - หมวดหมู่
- สตริงที่มีข้อมูลเพิ่มเติมเกี่ยวกับประเภทคอมโพเนนต์ที่ควรจัดการ Intent คำอธิบายหมวดหมู่กี่รายการก็ได้
อยู่ใน Intent แต่ Intent ส่วนใหญ่ไม่จำเป็นต้องมีหมวดหมู่
ต่อไปนี้คือหมวดหมู่ทั่วไปบางส่วน
CATEGORY_BROWSABLE
- กิจกรรมเป้าหมายอนุญาตให้เว็บเบราว์เซอร์เริ่มดำเนินการเองเพื่อแสดงข้อมูล อ้างอิงโดยลิงก์ เช่น รูปภาพหรือข้อความอีเมล
CATEGORY_LAUNCHER
- กิจกรรมนี้เป็นกิจกรรมเริ่มต้นของงานและแสดงอยู่ในตัวเปิดแอปพลิเคชันของระบบ
ดูรายการทั้งหมดของคำอธิบายชั้นเรียน
Intent
หมวดหมู่ต่างๆคุณระบุหมวดหมู่ได้ด้วย
addCategory()
พร็อพเพอร์ตี้ที่แสดงด้านบน (ชื่อคอมโพเนนต์ การทำงาน ข้อมูล และหมวดหมู่) แสดง ซึ่งเป็นการกำหนดลักษณะของเจตนา การอ่านพร็อพเพอร์ตี้เหล่านี้ช่วยให้ระบบ Android แก้ปัญหาว่าควรเริ่มคอมโพเนนต์แอปใด อย่างไรก็ตาม ความตั้งใจสามารถ ข้อมูลเพิ่มเติมที่ไม่ส่งผลกระทบต่อ วิธีแก้ไขในคอมโพเนนต์ของแอป Intent ยังจะให้ข้อมูลต่อไปนี้ได้ด้วย
- พิเศษ
- คู่คีย์-ค่าที่มีข้อมูลเพิ่มเติมที่จำเป็นในการบรรลุ
การทำงานที่ขอ
เช่นเดียวกับการทำงานบางอย่างใช้ URI ข้อมูลบางประเภท การทำงานบางอย่างจะใช้ส่วนเพิ่มเติมบางอย่างด้วย
คุณสามารถเพิ่มข้อมูลเพิ่มเติมด้วยเมธอด
putExtra()
ต่างๆ ซึ่งแต่ละเมธอดจะยอมรับพารามิเตอร์ 2 รายการ ได้แก่ ชื่อคีย์และค่า นอกจากนี้ คุณยังสร้างออบเจ็กต์Bundle
ที่มีข้อมูลเพิ่มเติมทั้งหมด แล้วแทรกBundle
ในIntent
ด้วยputExtras()
ได้ด้วยตัวอย่างเช่น เมื่อสร้างความตั้งใจที่จะส่งอีเมลด้วย
ACTION_SEND
คุณสามารถระบุผู้รับถึงด้วยแอตทริบิวต์EXTRA_EMAIL
และระบุหัวเรื่องด้วยแอตทริบิวต์ คีย์EXTRA_SUBJECT
คลาส
Intent
ระบุค่าคงที่EXTRA_*
จำนวนมาก สำหรับประเภทข้อมูลมาตรฐาน หากจำเป็นต้องประกาศคีย์เพิ่มเติมของคุณเอง (สำหรับ Intent ที่ ที่แอปของคุณได้รับ) อย่าลืมระบุชื่อแพ็กเกจของแอป นำหน้า ดังที่ปรากฏในตัวอย่างต่อไปนี้const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
ข้อควรระวัง: อย่าใช้
Parcelable
หรือSerializable
เมื่อส่ง Intent ที่คุณคาดหวัง อีกแอปหนึ่งที่จะรับ หากแอปพยายามเข้าถึงข้อมูลในออบเจ็กต์Bundle
แต่ไม่มีสิทธิ์เข้าถึงคลาสที่มีการแยกส่วนหรือแปลงเป็นอนุกรม ระบบจะแสดงRuntimeException
- Flag
- Flag จะกำหนดไว้ในคลาส
Intent
ที่ทำหน้าที่เป็นข้อมูลเมตาสำหรับ Intent การรายงานปัญหาอาจสั่งให้ระบบ Android เปิดใช้งานกิจกรรม (ตัวอย่างเช่น งาน กิจกรรมควรเป็น กับ) และวิธีจัดการกับผลิตภัณฑ์หลังเปิดตัว (เช่น ระบุว่าอยู่ในรายการล่าสุดของ กิจกรรม)ดูข้อมูลเพิ่มเติมได้ที่เมธอด
setFlags()
ตัวอย่าง Intent แบบเจาะจง
Intent แบบชัดแจ้งคือ Intent ที่คุณใช้เพื่อเปิดใช้งานคอมโพเนนต์แอปที่เฉพาะเจาะจง เช่น กิจกรรมหรือบริการหนึ่งๆ ในแอป หากต้องการสร้าง Intent แบบชัดแจ้ง ให้กําหนดชื่อคอมโพเนนต์สําหรับออบเจ็กต์ Intent
โดยคุณเลือกที่จะใช้พร็อพเพอร์ตี้ Intent อื่นๆ ทั้งหมดหรือไม่ก็ได้
ตัวอย่างเช่น หากคุณสร้างบริการชื่อ DownloadService
ในแอปเพื่อดาวน์โหลดไฟล์จากเว็บ คุณสามารถเริ่มต้นบริการด้วยโค้ดต่อไปนี้
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" val downloadIntent = Intent(this, DownloadService::class.java).apply { data =Uri.parse
(fileUrl) } startService(downloadIntent)
// Executed in an Activity, so 'this' is theContext
// 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)
เครื่องมือสร้างแอปจะให้แอป Context
และ
ให้ออบเจ็กต์ Class
ด้วยเหตุนี้
Intent นี้จะเริ่มต้นคลาส DownloadService
ในแอปอย่างชัดเจน
ดูข้อมูลเพิ่มเติมเกี่ยวกับการสร้างและเริ่มบริการได้ที่คู่มือบริการ
ตัวอย่าง Intent แบบไม่เจาะจงปลายทาง
Intent แบบไม่เจาะจงปลายทางจะระบุการดำเนินการที่เรียกแอปใดก็ได้ในอุปกรณ์ที่ดำเนินการดังกล่าวได้ การใช้ Intent แบบไม่เจาะจงปลายทางมีประโยชน์เมื่อแอปดำเนินการต่อไปนี้ไม่ได้ แต่แอปอื่นๆ สามารถทำได้ และคุณต้องการให้ผู้ใช้เลือกแอปที่จะใช้
เช่น หากคุณมีเนื้อหาที่ต้องการให้ผู้ใช้แชร์กับผู้อื่น ให้สร้าง Intent ด้วยการดำเนินการ ACTION_SEND
และเพิ่มข้อมูลเพิ่มเติมที่ระบุเนื้อหาที่จะแชร์ เมื่อคุณโทร
startActivity()
ด้วยความตั้งใจดังกล่าว ผู้ใช้จะสามารถ
เลือกแอปที่จะแชร์เนื้อหา
// Create the text message with a string. val sendIntent = Intent().apply { action = Intent.ACTION_SEND putExtra(Intent.EXTRA_TEXT, textMessage) type = "text/plain" } // Try to invoke the intent. try { startActivity(sendIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
// Create the text message with a string. Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage); sendIntent.setType("text/plain"); // Try to invoke the intent. try { startActivity(sendIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
เมื่อเรียก startActivity()
ระบบจะตรวจสอบแอปที่ติดตั้งทั้งหมดเพื่อดูว่าแอปใดจัดการ Intent ประเภทนี้ได้ (Intent ที่มีการดำเนินการ ACTION_SEND
และนําข้อมูล "text/plain") หากมีแอปเดียวที่จัดการได้ แอปนั้นจะเปิดขึ้นทันทีและได้รับ Intent หากไม่มีแอปอื่นๆ ช่วยจัดการได้ แอปของคุณก็จะตรวจจับ
ActivityNotFoundException
ที่เกิดขึ้น หากมีหลายกิจกรรมยอมรับ Intent
แสดงกล่องโต้ตอบ เช่น กล่องโต้ตอบที่แสดงในรูปที่ 2 เพื่อให้ผู้ใช้เลือกได้ว่าจะใช้แอปใด
ดูข้อมูลเพิ่มเติมเกี่ยวกับการเปิดแอปอื่นๆ ได้ในคู่มือการส่งผู้ใช้ไปยังแอปอื่น

รูปที่ 2 กล่องโต้ตอบตัวเลือก
การบังคับใช้เครื่องมือเลือกแอป
เมื่อมีแอปมากกว่า 1 แอปที่ตอบสนองต่อความตั้งใจโดยนัยของคุณ ผู้ใช้สามารถเลือกแอปที่จะใช้ และทำให้แอปนั้นเป็นตัวเลือกเริ่มต้นสำหรับ การดำเนินการ ความสามารถในการเลือกค่าเริ่มต้นจะมีประโยชน์เมื่อดำเนินการที่ผู้ใช้อาจต้องการใช้แอปเดียวกันทุกครั้ง เช่น เมื่อเปิดหน้าเว็บ (ผู้ใช้มักต้องการใช้เว็บเบราว์เซอร์เพียงตัวเดียว)
แต่ถ้าแอปหลายแอปสามารถตอบสนองต่อความตั้งใจได้ และผู้ใช้อาจต้องการใช้แอปอื่น
ทุกครั้ง คุณควรแสดงกล่องโต้ตอบตัวเลือกอย่างชัดเจน กล่องโต้ตอบเครื่องมือเลือกจะขอให้ผู้ใช้เลือกแอปที่จะใช้สำหรับการดำเนินการ (ผู้ใช้จะเลือกแอปเริ่มต้นสำหรับการดำเนินการไม่ได้) เช่น เมื่อแอปของคุณทำการ "แชร์" เมื่อมีการดําเนินการ ACTION_SEND
ผู้ใช้อาจต้องการแชร์โดยใช้แอปอื่น ซึ่งขึ้นอยู่กับ
ในสถานการณ์ปัจจุบัน ดังนั้นคุณควรใช้กล่องโต้ตอบตัวเลือกเสมอ ดังแสดงในรูปที่ 2
หากต้องการแสดงตัวเลือก ให้สร้าง Intent
โดยใช้ createChooser()
แล้วส่งไปยัง startActivity()
ดังที่ปรากฏในตัวอย่างต่อไปนี้
ตัวอย่างนี้แสดงกล่องโต้ตอบที่มีรายการแอปที่ตอบสนองต่อ Intent ที่ส่งไปยังเมธอด createChooser()
และใช้ข้อความที่ระบุเป็น
ชื่อกล่องโต้ตอบ
val sendIntent = Intent(Intent.ACTION_SEND) ... // Always use string resources for UI text. // This says something like "Share this photo with" val title: String = resources.getString(R.string.chooser_title) // Create intent to show the chooser dialog val chooser: Intent = Intent.createChooser(sendIntent, title) // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(packageManager) != null) { startActivity(chooser) }
Intent sendIntent = 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 the chooser dialog Intent chooser = Intent.createChooser(sendIntent, title); // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(getPackageManager()) != null) { startActivity(chooser); }
ตรวจหาการเปิด Intent ที่ไม่ปลอดภัย
แอปอาจเปิด Intent เพื่อไปยังส่วนต่างๆ ของคอมโพเนนต์ภายในแอป หรือเพื่อดำเนินการในนามของแอปอื่น เพื่อปรับปรุงความปลอดภัยของแพลตฟอร์ม Android 12 (API ระดับ 31) ขึ้นไปจึงมีฟีเจอร์การแก้ไขข้อบกพร่องที่จะเตือนคุณหากแอปเปิด Intent ที่ไม่ปลอดภัย ตัวอย่างเช่น แอปของคุณอาจ เรียกใช้Intent ที่ซ้อนกัน ซึ่งเป็น Intent ที่ส่งอย่างไม่ปลอดภัย เพื่อเป็นส่วนเสริมในจุดประสงค์อื่น
หากแอปดำเนินการทั้ง 2 อย่างต่อไปนี้ ระบบจะตรวจพบการเปิด Intent ที่ไม่เป็นอันตราย และเกิดการละเมิด StrictMode
- แอปของคุณยกเลิกการแปลง Intent ที่ซ้อนกันจาก Intent เพิ่มเติม
- แอปของคุณจะเริ่มคอมโพเนนต์แอปทันทีโดยใช้ Intent ที่ฝังอยู่นั้น เช่น ส่ง Intent ไปยัง
startActivity()
,startService()
หรือbindService()
อ่านรายละเอียดเพิ่มเติมเกี่ยวกับวิธีระบุสถานการณ์นี้และทําการเปลี่ยนแปลงในแอปได้จากบล็อกโพสต์เกี่ยวกับIntent แบบซ้อนกันของ Android ใน Medium
ตรวจสอบการเปิดใช้งาน Intent ที่ไม่ปลอดภัย
หากต้องการตรวจสอบการเปิด Intent ที่ไม่ปลอดภัยในแอป โปรดเรียกใช้
detectUnsafeIntentLaunch()
เมื่อกำหนดค่า VmPolicy
ดังที่แสดงในข้อมูลโค้ดต่อไปนี้ ถ้า
แอปของคุณตรวจพบการละเมิด StrictMode คุณอาจต้องหยุดการดำเนินการกับแอปเพื่อ
ปกป้องข้อมูลที่อาจมีความละเอียดอ่อน
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()) }
protected void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()); }
ใช้ Intent อย่างมีความรับผิดชอบมากขึ้น
หากต้องการลดโอกาสในการเปิดตัว Intent ที่ไม่ปลอดภัยและการละเมิด StrictMode ให้ทำตามแนวทางปฏิบัติที่ดีที่สุดเหล่านี้
คัดลอกเฉพาะส่วนเพิ่มเติมที่จำเป็นภายใน Intent และดำเนินการตามความจำเป็น
ด้านสุขอนามัยและการตรวจสอบความถูกต้อง แอปอาจคัดลอกบริการเพิ่มเติมจาก Intent หนึ่งไปยัง
อีก Intent หนึ่งที่ใช้เพื่อเปิดตัวคอมโพเนนต์ใหม่ กรณีนี้เกิดขึ้นเมื่อแอปเรียกใช้ putExtras(Intent)
หรือ putExtras(Bundle)
หากแอปของคุณดำเนินการอย่างใดอย่างหนึ่งเหล่านี้ ให้คัดลอกเฉพาะส่วนเสริมที่คอมโพเนนต์ฝั่งที่รับคาดหวัง หาก Intent อื่น (ที่รับสำเนา) เปิดใช้งานคอมโพเนนต์ที่ไม่ได้ส่งออก ให้กรองและตรวจสอบข้อมูลเพิ่มเติมก่อนที่จะคัดลอกไปยัง Intent ที่เปิดใช้งานคอมโพเนนต์
อย่าส่งออกคอมโพเนนต์ของแอปโดยไม่จำเป็น ตัวอย่างเช่น หากคุณตั้งใจจะเปิดใช้งานคอมโพเนนต์แอปโดยใช้ Intent ที่ฝังภายใน ให้ตั้งค่าแอตทริบิวต์ android:exported
ของคอมโพเนนต์นั้นเป็น false
ใช้ PendingIntent
แทน Intent แบบฝัง วิธีนี้ช่วยให้แอปอื่นสามารถเปิดPendingIntent
โดยใช้ข้อมูลประจำตัวของแอปของคุณได้เมื่อแอปอื่นเลิกแบ่งกลุ่มPendingIntent
ที่มีIntent
อยู่ การกำหนดค่านี้ช่วยให้แอปอื่นเปิดคอมโพเนนต์ใดก็ได้ในแอปของคุณได้อย่างปลอดภัย ซึ่งรวมถึงคอมโพเนนต์ที่ไม่ได้ส่งออก
แผนภาพในรูปที่ 2 แสดงวิธีที่ระบบส่งการควบคุมจากแอป (ไคลเอ็นต์) ไปยังแอป (บริการ) อื่น และกลับไปที่แอปของคุณ
- แอปของคุณสร้าง Intent ที่เรียกใช้กิจกรรมในแอปอื่น ภายใน Intent นั้น คุณจะเพิ่มออบเจ็กต์
PendingIntent
เป็นส่วนเสริม PendingIntent นี้เรียกใช้คอมโพเนนต์ในแอปของคุณ ซึ่งไม่ได้ส่งออกคอมโพเนนต์นี้ - เมื่อได้รับ Intent ของแอปคุณ แอปอื่นจะดึงออบเจ็กต์
PendingIntent
ที่ฝังอยู่ - แอปอื่นเรียกใช้เมธอด
send()
ในออบเจ็กต์PendingIntent
- หลังจากส่งการควบคุมกลับไปที่แอปแล้ว ระบบจะเรียกใช้ Intent ที่รอดำเนินการโดยใช้บริบทของแอป
รูปที่ 2 แผนภาพการสื่อสารระหว่างแอปเมื่อใช้รายการที่ฝังซึ่งรอดําเนินการ Intent
การรับ Intent แบบไม่เจาะจงปลายทาง
หากต้องการโฆษณา Intent ที่ไม่ชัดแจ้งที่แอปของคุณรับได้ ให้ประกาศตัวกรอง Intent อย่างน้อย 1 รายการสําหรับคอมโพเนนต์แอปแต่ละรายการที่มีองค์ประกอบ <intent-filter>
ในไฟล์ Manifest
ตัวกรอง Intent แต่ละรายการจะระบุประเภทของ Intent ที่
ตัวกรองยอมรับ โดยอิงตามการดำเนินการของ Intent
ข้อมูล และหมวดหมู่ ระบบจะส่ง Intent แบบไม่เจาะจงปลายทางไปยังคอมโพเนนต์แอปเฉพาะในกรณีที่
Intent ส่งผ่านตัวกรอง Intent ตัวใดตัวหนึ่งได้
หมายเหตุ: ระบบจะส่ง Intent แบบเจาะจงปลายทางเสมอ โดยไม่คำนึงถึงตัวกรอง Intent ที่คอมโพเนนต์ประกาศ
คอมโพเนนต์แอปควรประกาศตัวกรองแยกกันสำหรับงานแต่ละอย่างที่ทำได้โดยเฉพาะ
ตัวอย่างเช่น กิจกรรมหนึ่งในแอปแกลเลอรีรูปภาพอาจมีตัวกรอง 2 ตัว ได้แก่ ตัวกรองตัวหนึ่งสำหรับดูรูปภาพ และตัวกรองอีกตัวหนึ่งสำหรับแก้ไขรูปภาพ เมื่อกิจกรรมเริ่ม
ระบบจะตรวจสอบ Intent
และตัดสินใจเลือกลักษณะการทํางานโดยอิงตามข้อมูล
ใน Intent
(เช่น แสดงการควบคุมเครื่องมือแก้ไขหรือไม่)
ตัวกรอง Intent แต่ละรายการจะกำหนดโดย <intent-filter>
ในไฟล์ Manifest ของแอป โดยฝังอยู่ในคอมโพเนนต์แอปที่เกี่ยวข้อง (เช่น
ในฐานะ <activity>
)
ในคอมโพเนนต์แอปแต่ละรายการที่มีองค์ประกอบ <intent-filter>
ให้ตั้งค่า android:exported
อย่างชัดเจน
แอตทริบิวต์นี้ระบุว่าแอปอื่นๆ สามารถเข้าถึงคอมโพเนนต์ของแอปได้หรือไม่ ในบางส่วน
เช่น กิจกรรมที่มีตัวกรอง Intent
LAUNCHER
หมวดหมู่ คุณควรตั้งค่าแอตทริบิวต์นี้เป็น true
หรือไม่เช่นนั้น
การตั้งค่าแอตทริบิวต์นี้เป็น false
จะปลอดภัยกว่า
คำเตือน: หากกิจกรรม บริการ หรือการออกอากาศ
รีซีฟเวอร์ในแอปของคุณใช้ตัวกรอง Intent และไม่ได้กำหนดค่าอย่างชัดแจ้ง
สำหรับ android:exported
แอปของคุณไม่สามารถติดตั้งในอุปกรณ์ที่
ใช้ Android 12 ขึ้นไป
ภายใน <intent-filter>
คุณระบุประเภทของ Intent ที่จะยอมรับได้โดยใช้องค์ประกอบ 3 รายการต่อไปนี้อย่างน้อย 1 รายการ
<action>
- ประกาศการดำเนินการผ่าน Intent ที่ยอมรับในแอตทริบิวต์
name
ค่า ต้องเป็นค่าสตริงตรงตัวของการกระทำ ไม่ใช่ค่าคงที่ของคลาส <data>
- ประกาศประเภทข้อมูลที่ยอมรับโดยใช้แอตทริบิวต์อย่างน้อย 1 รายการที่ระบุแง่มุมต่างๆ ของ URI ของข้อมูล (
scheme
,host
,port
,path
) และประเภท MIME <category>
- ประกาศหมวดหมู่ Intent ที่ยอมรับในแอตทริบิวต์
name
ค่าต้องตรงกับสตริงที่แสดงค่าของการดำเนินการ ไม่ใช่ค่าคงที่ของคลาสหมายเหตุ: หากต้องการรับ Intent แบบไม่เจาะจงปลายทาง คุณต้อง ต้องมีฟิลด์
CATEGORY_DEFAULT
ในตัวกรอง Intent วิธีการstartActivity()
และstartActivityForResult()
จะถือว่า Intent ทั้งหมด เหมือนกับว่าได้ประกาศหมวดหมู่CATEGORY_DEFAULT
ไว้ หากคุณไม่ประกาศหมวดหมู่นี้ในตัวกรอง Intent จะไม่มีการแก้ไข Intent แบบไม่เจาะจงปลายทางเป็น กิจกรรมของคุณ
ต่อไปนี้คือตัวอย่างการประกาศกิจกรรมที่มีตัวกรอง Intent เพื่อรับ Intent ACTION_SEND
เมื่อประเภทข้อมูลคือข้อความ
<activity android:name="ShareActivity" android:exported="false"> <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>
มากกว่า 1 รายการ
หากมี คุณต้องมั่นใจว่าคอมโพเนนต์จะจัดการ
ชุดค่าผสมขององค์ประกอบตัวกรองเหล่านั้น
เมื่อต้องการจัดการ Intent หลายประเภท แต่ต้องอยู่ในรูปแบบการผสมผสานของประเภทการดำเนินการ ข้อมูล และหมวดหมู่ที่เฉพาะเจาะจงเท่านั้น คุณจะต้องสร้างตัวกรอง Intent หลายรายการ
ระบบจะทดสอบ Intent แบบไม่เจาะจงปลายทางกับตัวกรองโดยเปรียบเทียบความตั้งใจกับแต่ละรายการ องค์ประกอบ 3 อย่าง Intent ต้องผ่านการทดสอบทั้ง 3 รายการจึงจะส่งไปยังคอมโพเนนต์ได้ หากจับคู่ไม่ได้แม้แต่รายการเดียว ระบบ Android จะไม่ส่ง Intent ไปยังคอมโพเนนต์ แต่เนื่องจากคอมโพเนนต์หนึ่งอาจมีตัวกรอง Intent หลายรายการ Intent ที่มี ไม่ผ่านตัวกรองใดคอมโพเนนต์หนึ่ง อาจทะลุผ่านตัวกรองอื่นได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ระบบแก้ไข Intent ได้ที่ส่วนด้านล่าง เกี่ยวกับความละเอียดของความตั้งใจ
ข้อควรระวัง: การใช้ตัวกรอง Intent ไม่ใช่วิธีที่ปลอดภัยในการป้องกันการเริ่มคอมโพเนนต์ของคุณโดยแอปอื่นๆ แม้ว่าตัวกรอง Intent จะจำกัดคอมโพเนนต์ให้ตอบสนองต่อ
Intent แบบไม่เจาะจงปลายทางบางประเภท แอปอื่นอาจเริ่มคอมโพเนนต์ของแอปได้
โดยการใช้เจตนาที่ชัดแจ้งหากนักพัฒนาซอฟต์แวร์กำหนดชื่อคอมโพเนนต์ของคุณ
หากสิ่งสำคัญคือมีแต่แอปของคุณเองเท่านั้นที่เริ่มต้นคอมโพเนนต์ได้
อย่าประกาศตัวกรอง Intent ในไฟล์ Manifest แต่ให้ตั้งค่า
แอตทริบิวต์ของ exported
เป็น "false"
สำหรับคอมโพเนนต์นั้น
ในทำนองเดียวกัน เพื่อหลีกเลี่ยงการเรียกใช้แอปพลิเคชันอื่นโดยไม่ตั้งใจ
Service
โปรดใช้ Intent แบบเจาะจงปลายทางเพื่อเริ่มบริการของคุณเองเสมอ
หมายเหตุ:
คุณต้องประกาศตัวกรอง Intent ในไฟล์ Manifest สำหรับกิจกรรมทั้งหมด
อย่างไรก็ตาม ตัวกรองสำหรับเครื่องรับสัญญาณออกอากาศสามารถลงทะเบียนแบบไดนามิกโดยการเรียกใช้
registerReceiver()
จากนั้นคุณจะยกเลิกการลงทะเบียนรีซีฟเวอร์กับ unregisterReceiver()
ได้ ซึ่งจะช่วยให้แอปของคุณรับฟังการออกอากาศที่เฉพาะเจาะจงได้ในช่วงเวลาที่ระบุเท่านั้นขณะที่แอปทำงานอยู่
ตัวอย่างตัวกรอง
ตัวอย่างในการสาธิตลักษณะการทำงานของตัวกรอง Intent บางรายการมีดังนี้ จากไฟล์ Manifest ของแอปการแชร์ผ่านโซเชียล
<activity android:name="MainActivity" android:exported="true"> <!-- 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" android:exported="false"> <!-- 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>
กิจกรรมแรก MainActivity
คือจุดแรกเข้าหลักของแอป ซึ่งเป็นกิจกรรมที่
เปิดขึ้นเมื่อผู้ใช้เปิดแอปเป็นครั้งแรกด้วยไอคอน Launcher ดังนี้
- การดำเนินการ
ACTION_MAIN
ระบุว่านี่เป็นจุดแรกเข้าหลักและไม่มีข้อมูล Intent - หมวดหมู่
CATEGORY_LAUNCHER
บ่งบอกว่าควรวางไอคอนของกิจกรรมนี้ไว้ในตัวเปิดแอปของระบบ หากองค์ประกอบ<activity>
ไม่ได้ระบุไอคอนด้วยicon
ระบบจะใช้ไอคอนจาก<application>
2 รายการนี้ต้องจับคู่กันเพื่อให้กิจกรรมปรากฏในตัวเปิดแอป
กิจกรรมที่ 2 ShareActivity
มีจุดประสงค์เพื่ออำนวยความสะดวกในการแชร์ข้อความและสื่อ
เนื้อหา แม้ว่าผู้ใช้อาจเข้าสู่กิจกรรมนี้โดยไปที่กิจกรรมจาก MainActivity
แต่ผู้ใช้ก็เข้าสู่ ShareActivity
ได้โดยตรงจากแอปอื่นที่ส่ง Intent ที่ไม่ชัดซึ่งตรงกับตัวกรอง Intent รายการใดรายการหนึ่ง
หมายเหตุ: ประเภท MIME
application/vnd.google.panorama360+jpg
คือประเภทข้อมูลพิเศษที่ระบุ
ภาพพาโนรามา ซึ่งคุณจัดการได้ด้วย Google
panorama API
จับคู่ Intent กับแอปอื่นๆ ตัวกรอง Intent
หากแอปอื่นกำหนดเป้าหมายเป็น Android 13 (API ระดับ 33) ขึ้นไป แอปนั้นจะจัดการ Intent ของแอปได้ก็ต่อเมื่อ Intent ของคุณตรงกับการดำเนินการและหมวดหมู่ขององค์ประกอบ <intent-filter>
ในแอปอื่นนั้นเท่านั้น หากระบบไม่พบรายการที่ตรงกัน ระบบจะแสดงActivityNotFoundException
แอปที่ส่งต้องจัดการ
ข้อยกเว้นนี้
ในทำนองเดียวกัน หากคุณอัปเดตแอปเพื่อให้กำหนดเป้าหมายเป็น Android 13
ขึ้นไป ระบบจะนำส่ง Intent ทั้งหมดที่มาจากแอปภายนอกไปยัง
คอมโพเนนต์ที่ส่งออกมาก็ต่อเมื่อ Intent นั้นตรงกับการดำเนินการ และ
หมวดหมู่ขององค์ประกอบ <intent-filter>
ที่แอปของคุณประกาศ ลักษณะการทำงานนี้จะแสดงขึ้นไม่ว่าแอปที่ส่งจะมี SDK เวอร์ชันเป้าหมายใดก็ตาม
ระบบจะไม่บังคับใช้การจับคู่ความตั้งใจในกรณีต่อไปนี้
- Intent ที่ส่งไปยังคอมโพเนนต์ที่ไม่ได้ประกาศตัวกรอง Intent ใดๆ
- Intent ที่มาจากภายในแอปเดียวกัน
- Intent ที่มาจากระบบ นั่นคือ Intent ที่ส่งจาก
"UID ของระบบ" (uid=1000) แอประบบรวมถึง
system_server
และแอปที่ตั้งค่าandroid:sharedUserId
เป็นandroid.uid.system
- Intent ที่มาจากรูท
ดูข้อมูลเพิ่มเติมเกี่ยวกับการจับคู่ความตั้งใจ
การใช้ Intent ที่รอดำเนินการ
ออบเจ็กต์ PendingIntent
คือ Wrapper ที่อยู่รอบๆ ออบเจ็กต์ Intent
วัตถุประสงค์หลักของ PendingIntent
คือการให้สิทธิ์แก่แอปพลิเคชันภายนอกเพื่อใช้ Intent
ที่มีให้ ราวกับว่าแอปพลิเคชันนั้นทำงานจากกระบวนการของแอปคุณเอง
กรณีการใช้งานหลักสำหรับ Intent ที่รอดำเนินการมีดังนี้
- การประกาศ Intent ที่จะเริ่มดำเนินการเมื่อผู้ใช้ดำเนินการกับการแจ้งเตือน (
NotificationManager
ของระบบ Android จะดำเนินการIntent
) - ประกาศความตั้งใจที่จะดำเนินการเมื่อผู้ใช้ดำเนินการ
วิดเจ็ตแอป
(แอปหน้าจอหลักจะเรียกใช้
Intent
) - การประกาศ Intent ให้ดำเนินการในเวลาที่ระบุในอนาคต (
AlarmManager
ของระบบ Android จะดำเนินการIntent
)
เช่นเดียวกับที่ออบเจ็กต์ Intent
แต่ละรายการได้รับการออกแบบมาให้จัดการโดยคอมโพเนนต์แอปประเภทหนึ่งๆ (Activity
, Service
หรือ BroadcastReceiver
) PendingIntent
ก็ต้องสร้างขึ้นโดยคำนึงถึงสิ่งเดียวกัน เมื่อใช้ Intent ที่รอดำเนินการ แอปจะไม่ดำเนินการ Intent ด้วยการเรียกใช้ เช่น startActivity()
แต่คุณต้องประกาศประเภทคอมโพเนนต์ที่ต้องการเมื่อสร้าง PendingIntent
โดยเรียกใช้เมธอดการสร้างที่เกี่ยวข้อง ดังนี้
PendingIntent.getActivity()
สำหรับIntent
ที่เริ่มต้นActivity
PendingIntent.getService()
สำหรับIntent
ที่เริ่มต้นService
PendingIntent.getBroadcast()
สำหรับIntent
ที่เริ่มต้นBroadcastReceiver
เว้นแต่ว่าแอปของคุณจะได้รับ Intent ที่รอดำเนินการจากแอปอื่นๆ
วิธีการข้างต้นในการสร้าง PendingIntent
น่าจะเป็นเพียงวิธีเดียว
PendingIntent
วิธีการที่คุณจำเป็นต้องใช้
แต่ละวิธีจะใช้แอปปัจจุบัน Context
ค่า
Intent
ที่ต้องการรวม และแฟล็กอย่างน้อย 1 รายการที่ระบุ
ควรใช้ Intent อย่างไร (เช่น สามารถใช้ Intent ได้มากกว่า 1 ครั้งหรือไม่)
หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Intent ที่รอดำเนินการ โปรดดูเอกสารสำหรับแต่ละ ของ Use Case ที่เกี่ยวข้อง เช่น ในการแจ้งเตือน และคำแนะนำ API ของ App Widgets
ระบุการเปลี่ยนแปลง
หากแอปกำหนดเป้าหมายเป็น Android 12 ขึ้นไป คุณต้องระบุการเปลี่ยนแปลงของออบเจ็กต์ PendingIntent
แต่ละรายการที่แอปสร้างขึ้น ในการประกาศว่า
ออบเจ็กต์ PendingIntent
ที่ระบุจะเปลี่ยนแปลงหรือเปลี่ยนแปลงไม่ได้ ให้ใช้
PendingIntent.FLAG_MUTABLE
หรือ
PendingIntent.FLAG_IMMUTABLE
ตามลำดับ
หากแอปพยายามสร้างออบเจ็กต์ PendingIntent
โดยไม่ตั้งค่า Flag การเปลี่ยนแปลง ระบบจะแสดงข้อผิดพลาด
IllegalArgumentException
และ
ข้อความต่อไปนี้จะปรากฏใน Logcat
PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.
สร้าง Intent ที่รอดำเนินการที่เปลี่ยนแปลงไม่ได้เมื่อเป็นไปได้
ในกรณีส่วนใหญ่ แอปควรสร้างออบเจ็กต์ PendingIntent
ที่ไม่เปลี่ยนแปลงได้ ดังที่แสดงในข้อมูลโค้ดต่อไปนี้ หากออบเจ็กต์ PendingIntent
เปลี่ยนแปลงไม่ได้
แอปอื่นๆ จะไม่สามารถแก้ไข Intent ในการปรับผลลัพธ์ของการเรียกใช้
Intent
val pendingIntent = PendingIntent.getActivity(applicationContext,REQUEST_CODE , intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),REQUEST_CODE , intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
อย่างไรก็ตาม กรณีการใช้งานบางอย่างต้องใช้ออบเจ็กต์ PendingIntent
แบบปรับเปลี่ยนได้แทน
- สนับสนุนการดำเนินการตอบกลับโดยตรงใน
การแจ้งเตือน
การตอบกลับโดยตรงต้องมีการเปลี่ยนแปลงข้อมูลคลิปในออบเจ็กต์ PendingIntent
ที่เชื่อมโยงกับการตอบกลับ โดยปกติแล้ว คุณจะขอการเปลี่ยนแปลงนี้โดยการส่ง
FILL_IN_CLIP_DATA
เป็น Flag ไปยังเมธอดfillIn()
- การเชื่อมโยงการแจ้งเตือนกับเฟรมเวิร์ก Android Auto โดยใช้ตัวอย่าง
CarAppExtender
- การวางการสนทนาในบับเบิลโดยใช้อินสแตนซ์ของ
PendingIntent
ออบเจ็กต์PendingIntent
ที่เปลี่ยนแปลงได้ช่วยให้ระบบใช้ Flag ที่ถูกต้องได้ เช่นFLAG_ACTIVITY_MULTIPLE_TASK
และFLAG_ACTIVITY_NEW_DOCUMENT
- ขอข้อมูลตำแหน่งอุปกรณ์ด้วยการโทร
requestLocationUpdates()
หรือ API ที่คล้ายกัน ออบเจ็กต์PendingIntent
แบบปรับเปลี่ยนได้ช่วยให้ระบบเพิ่มข้อมูลเพิ่มเติมของ Intent ที่แสดงถึงเหตุการณ์วงจรชีวิตของตําแหน่งได้ เหตุการณ์เหล่านี้ประกอบไปด้วย การเปลี่ยนแปลงสถานที่ตั้งและผู้ให้บริการที่พร้อมให้บริการ - การตั้งเวลาการปลุกโดยใช้
AlarmManager
ออบเจ็กต์PendingIntent
ที่เปลี่ยนแปลงได้ช่วยให้ระบบเพิ่มEXTRA_ALARM_COUNT
Intent เพิ่มเติม ส่วนเกินนี้แสดงจำนวนครั้งที่การปลุกซ้ำ ถูกเรียกใช้แล้ว ด้วยการใส่ข้อมูลเพิ่มเติมนี้ Intent สามารถแจ้งเตือน แอปว่าการปลุกซ้ำถูกเรียกใช้หลายครั้งหรือไม่ เช่น เมื่ออุปกรณ์อยู่ในโหมดสลีป
หากแอปของคุณสร้างออบเจ็กต์ PendingIntent
ที่เปลี่ยนแปลงได้ เราขอแนะนําอย่างยิ่งให้คุณใช้ Intent ที่ชัดเจนและป้อน ComponentName
วิธีนี้จะทำให้เมื่อใดก็ได้
แอปอื่นจะเรียกใช้ PendingIntent
และตัวควบคุมบัตรกลับไปยังแอปของคุณ
คอมโพเนนต์เดียวกันในแอปจะเริ่มต้นเสมอ
ใช้ Intent แบบเจาะจงปลายทางภายใน Intent ที่รอดำเนินการ
หากต้องการระบุวิธีที่แอปอื่นๆ สามารถใช้ Intent ที่รอดำเนินการของแอปได้ดีขึ้น โปรดทำดังนี้ ใส่ Intent ที่รอดำเนินการเอาไว้รอบๆ เจตนาโจ่งแจ้ง โปรดทําตามขั้นตอนต่อไปนี้เพื่อช่วยปฏิบัติตามแนวทางปฏิบัติแนะนํานี้
- ตรวจสอบว่ามีการตั้งค่าฟิลด์การดำเนินการ แพ็กเกจ และคอมโพเนนต์ของ Intent พื้นฐาน
-
ใช้
FLAG_IMMUTABLE
ซึ่งเพิ่มเข้ามาใน Android 6.0 (API ระดับ 23) เพื่อสร้าง Intent ที่รอดำเนินการ Flag นี้จะช่วยป้องกันไม่ให้แอปที่ได้รับPendingIntent
ทำการเติมพร็อพเพอร์ตี้ที่ไม่ได้สร้างไว้ หากminSdkVersion
ของแอปเป็น22
หรือต่ำกว่า คุณสามารถระบุความปลอดภัยและความสามารถในการใช้งานร่วมกันได้โดยใช้รหัสต่อไปนี้if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
การแก้ไข Intent
เมื่อระบบได้รับ Intent ที่ไม่ชัดแจ้งเพื่อเริ่มกิจกรรม ระบบจะค้นหากิจกรรมที่เหมาะกับ Intent นั้นที่สุดโดยเปรียบเทียบกับตัวกรอง Intent ตาม 3 ด้านต่อไปนี้
- เริ่มถ่ายเลย
- ข้อมูล (ทั้ง URI และประเภทข้อมูล)
- หมวดหมู่
ส่วนต่อไปนี้จะอธิบายวิธีจับคู่ Intent กับคอมโพเนนต์ที่เหมาะสม ตามการประกาศตัวกรอง Intent ในไฟล์ Manifest ของแอป
การทดสอบการดำเนินการ
ในการระบุการดำเนินการของ Intent ที่ยอมรับ ตัวกรอง Intent จะประกาศค่าเป็น 0 ขึ้นไปได้
<action>
ดังที่แสดงในตัวอย่างต่อไปนี้
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
หากต้องการผ่านตัวกรองนี้ การดำเนินการที่ระบุไว้ใน Intent
ต้องตรงกับหนึ่งในการดำเนินการที่ระบุไว้ในตัวกรอง
หากตัวกรองไม่ได้แสดงการดำเนินการใดๆ แสดงว่าไม่มีการดำเนินการใดๆ ที่จะจับคู่กับ Intent ดังนั้น Intent ทั้งหมดจะทดสอบไม่ผ่าน อย่างไรก็ตาม หาก Intent
ไม่ได้ระบุการดำเนินการ แต่จะผ่านการทดสอบตราบใดที่ตัวกรอง
มีการดำเนินการอย่างน้อย 1 รายการ
การทดสอบหมวดหมู่
หากต้องการระบุหมวดหมู่ Intent ที่ยอมรับ ตัวกรอง Intent สามารถประกาศองค์ประกอบ <category>
อย่างน้อย 1 รายการ ดังที่แสดงในตัวอย่างต่อไปนี้
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
เพื่อให้ผ่านการทดสอบหมวดหมู่ ทุกหมวดหมู่ใน Intent
ต้องตรงกับหมวดหมู่ในตัวกรอง แต่ไม่จำเป็นต้องเป็นแบบย้อนกลับ ตัวกรอง Intent อาจประกาศหมวดหมู่มากกว่าที่ระบุไว้ใน Intent
และ Intent
จะยังคงผ่าน ดังนั้น Intent ที่ไม่มีหมวดหมู่จะผ่านการทดสอบนี้เสมอ ไม่ว่าจะมีการประกาศหมวดหมู่ใดในตัวกรองก็ตาม
หมายเหตุ: Android จะใช้หมวดหมู่ CATEGORY_DEFAULT
กับ Intent ที่ไม่ชัดทั้งหมดที่ส่งไปยัง startActivity()
และ startActivityForResult()
โดยอัตโนมัติ
หากต้องการให้กิจกรรมได้รับ Intent ที่ไม่ชัดแจ้ง กิจกรรมนั้นต้องมีหมวดหมู่สำหรับ "android.intent.category.DEFAULT"
ในตัวกรอง Intent ดังที่แสดงในตัวอย่าง <intent-filter>
ก่อนหน้า
การทดสอบข้อมูล
หากต้องการระบุข้อมูล Intent ที่ยอมรับ ตัวกรอง Intent สามารถประกาศองค์ประกอบ <data>
อย่างน้อย 0 รายการ ดังที่แสดงในตัวอย่างต่อไปนี้
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
แต่ละ<data>
สามารถระบุโครงสร้าง URI และประเภทข้อมูล (ประเภทสื่อ MIME)
แต่ละส่วนของ URI จะเป็น
แอตทริบิวต์: scheme
, host
, port
และ path
:
<scheme>://<host>:<port>/<path>
ตัวอย่างต่อไปนี้แสดงค่าที่เป็นไปได้สำหรับแอตทริบิวต์เหล่านี้
content://com.example.project:200/folder/subfolder/etc
ใน URI นี้ รูปแบบคือ content
โฮสต์คือ com.example.project
พอร์ตคือ 200
และเส้นทางคือ folder/subfolder/etc
คุณไม่จำเป็นต้องระบุแอตทริบิวต์เหล่านี้ในองค์ประกอบ <data>
แต่แอตทริบิวต์เหล่านี้มีความเกี่ยวข้องกัน
- หากไม่ได้ระบุรูปแบบ ระบบจะไม่สนใจโฮสต์
- หากไม่ได้ระบุโฮสต์ ระบบจะไม่สนใจพอร์ต
- หากไม่ได้ระบุทั้งรูปแบบและโฮสต์ ระบบจะไม่สนใจเส้นทาง
เมื่อระบบเปรียบเทียบ URI ใน Intent กับข้อกําหนด URI ในตัวกรอง ระบบจะเปรียบเทียบเฉพาะกับส่วนของ URI ที่รวมอยู่ในตัวกรอง เช่น
- หากตัวกรองระบุเฉพาะสคีม URI ทั้งหมดที่มีรูปแบบนั้นตรงกัน ตัวกรอง
- หากตัวกรองระบุรูปแบบและหน่วยงานแต่ไม่มีเส้นทาง URI ทั้งหมดที่มีรูปแบบและหน่วยงานเดียวกันจะผ่านตัวกรอง ไม่ว่าเส้นทางจะเป็นอย่างไรก็ตาม
- หากตัวกรองระบุรูปแบบ หน่วยงาน และเส้นทาง เฉพาะ URI ที่มีรูปแบบ หน่วยงาน และเส้นทางเดียวกันเท่านั้นที่จะผ่านตัวกรอง
หมายเหตุ: ข้อกําหนดเฉพาะของพาธอาจมีเครื่องหมายดอกจัน (*) ไวลด์การ์ดเพื่อให้จับคู่ชื่อพาธได้เพียงบางส่วน
การทดสอบข้อมูลจะเปรียบเทียบทั้ง URI และประเภท MIME ใน Intent กับ URI และประเภท MIME ที่ระบุในตัวกรอง โดยมีกฎดังนี้
- Intent ที่ไม่มี URI หรือประเภท MIME ไม่ได้ส่งผ่านพารามิเตอร์ ให้ทดสอบต่อเมื่อตัวกรองไม่ได้ระบุ URI หรือประเภท MIME ไว้
- Intent ที่มี URI แต่ไม่มีประเภท MIME (ไม่ได้ระบุไว้อย่างชัดเจนหรืออนุมานจาก URI) จะผ่านการทดสอบก็ต่อเมื่อ URI ตรงกับรูปแบบ URI ของตัวกรอง และตัวกรองไม่ได้ระบุประเภท MIME ด้วยเช่นกัน
- Intent ที่มีประเภท MIME แต่ไม่มี URI ผ่านการทดสอบ เฉพาะเมื่อตัวกรองแสดงประเภท MIME เดียวกันและไม่ได้ระบุรูปแบบ URI
- Intent ที่มีทั้ง URI และประเภท MIME (อาจไม่เหมาะสมหรือสามารถอนุมานได้จาก
URI) จะส่งในส่วนของประเภท MIME ของการทดสอบก็ต่อเมื่อ
ประเภทตรงกับประเภทที่แสดงในตัวกรอง รายการจะผ่านส่วน URI ของการตรวจสอบไม่ว่าจะมี URI ที่ตรงกับ URI ในตัวกรอง หรือมี URI
content:
หรือfile:
และตัวกรองไม่ได้ระบุ URI กล่าวคือ ระบบจะถือว่าคอมโพเนนต์รองรับข้อมูลcontent:
และfile:
หากรายการตัวกรองมีประเภท MIME เพียงประเภทเดียว
หมายเหตุ: หาก Intent ระบุประเภท URI หรือ MIME การทดสอบข้อมูลจะ
จะล้มเหลวหากไม่มีองค์ประกอบ <data>
ใน <intent-filter>
กฎข้อสุดท้าย กฎ (ง) นี้แสดงถึงสิ่งที่คาดหวัง
คอมโพเนนต์สามารถรับข้อมูลในเครื่องจากผู้ให้บริการไฟล์หรือผู้ให้บริการเนื้อหา
ตัวกรองของตัวกรองจึงแสดงได้เฉพาะประเภทข้อมูลเท่านั้น และไม่จำเป็นต้องระบุ
ตั้งชื่อรูปแบบ content:
และ file:
ตัวอย่างต่อไปนี้แสดงกรณีทั่วไปที่องค์ประกอบ <data>
บอก Android ว่าคอมโพเนนต์สามารถรับข้อมูลรูปภาพจากเนื้อหาได้
ของผู้ให้บริการ และแสดงไว้ดังนี้
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
ตัวกรองที่ระบุประเภทข้อมูลแต่ไม่ใช่ URI อาจเป็นตัวกรองที่พบบ่อยที่สุด เนื่องจากข้อมูลส่วนใหญ่ที่พร้อมใช้งานมาจากผู้ให้บริการเนื้อหา
การกำหนดค่าที่พบได้ทั่วไปอีกอย่างหนึ่งคือตัวกรองที่มีรูปแบบและประเภทข้อมูล สำหรับ
ตัวอย่างเช่น <data>
ดังเช่นตัวอย่างต่อไปนี้บอกให้ Android ทราบว่า
คอมโพเนนต์สามารถดึงข้อมูลวิดีโอจากเครือข่ายเพื่อนำมาใช้งาน ดังนี้
<intent-filter> <data android:scheme="http" android:mimeType="video/*" /> ... </intent-filter>
การจับคู่ Intent
ระบบจะจับคู่ Intent กับตัวกรอง Intent ไม่เพียงเพื่อค้นหาคอมโพเนนต์เป้าหมายที่จะเปิดใช้งานเท่านั้น แต่ยังเพื่อค้นหาข้อมูลเกี่ยวกับชุดคอมโพเนนต์ในอุปกรณ์ด้วย ตัวอย่างเช่น แอป Home จะเติมตัวเปิดแอป
ด้วยการค้นหากิจกรรมทั้งหมดด้วยตัวกรอง Intent ที่ระบุ
ACTION_MAIN
การดำเนินการและ
CATEGORY_LAUNCHER
หมวดหมู่
การจับคู่จะสำเร็จก็ต่อเมื่อการดําเนินการและหมวดหมู่ใน Intent ตรงกับตัวกรอง ตามที่อธิบายไว้ในเอกสารประกอบของIntentFilter
คลาส
แอปพลิเคชันของคุณใช้การจับคู่ Intent ได้ในลักษณะที่คล้ายกับการทำงานของแอป Home
PackageManager
มีชุดเมธอด query...()
ที่แสดงผลคอมโพเนนต์ทั้งหมดที่ยอมรับ Intent ที่เฉพาะเจาะจง และชุดเมธอด resolve...()
ที่คล้ายกันซึ่งระบุคอมโพเนนต์ที่ดีที่สุดในการตอบสนองต่อ Intent ตัวอย่างเช่น
queryIntentActivities()
แสดงรายการกิจกรรมทั้งหมดที่สามารถทำได้
ความตั้งใจที่ส่งผ่านเป็นอาร์กิวเมนต์ และ queryIntentServices()
แสดงรายการบริการที่คล้ายกัน
ไม่มีวิธีใดเปิดใช้งานคอมโพเนนต์ เพียงแค่ระบุรายการข้อมูลที่
ตอบกลับได้ มีวิธีที่คล้ายกัน
queryBroadcastReceivers()
สำหรับ Broadcast Receiver