เมื่อคุณแตะ "ติดตั้ง" ในไฟล์ APK หรือดาวน์โหลดแอปจาก Play Store ลำดับการดำเนินการที่ซับซ้อนจะเริ่มต้นขึ้นในเบื้องหลัง สิ่งที่ดูเหมือนจะเป็นแถบความคืบหน้าที่เรียบง่ายจริงๆ แล้วแสดงถึงขั้นตอนต่างๆ มากมายที่เกี่ยวข้องกับการแยกวิเคราะห์แพ็คเกจ การตรวจสอบการเข้ารหัส การจัดการสิทธิ์ การแตกไฟล์ และการเพิ่มประสิทธิภาพโค้ด การทำความเข้าใจกระบวนการนี้จะช่วยอธิบายว่าทำไมบางครั้งการติดตั้งจึงล้มเหลว และสิ่งที่คุณสามารถทำได้
ในบทความนี้ เราจะอธิบายทุกขั้นตอนสำคัญของขั้นตอนการติดตั้ง Android ตั้งแต่ช่วงเวลาที่ระบบได้รับ APK จนถึงจุดที่พร้อมเปิดตัวแอป
ขั้นตอนที่ 1: เริ่มต้นการติดตั้ง
กระบวนการติดตั้งเริ่มต้นแตกต่างกันไปขึ้นอยู่กับแหล่งที่มา:
- เล่นสโตร์: แอป Play Store ดาวน์โหลด APK (หรือแยก APK) และเรียกตัวติดตั้งแพ็คเกจของระบบพร้อมสิทธิพิเศษที่เลี่ยงการยืนยันของผู้ใช้
- ไซด์โหลด: เมื่อคุณเปิดไฟล์ APK Android จะเปิดตัวกิจกรรมการติดตั้งแพ็คเกจ บน Android 8.0 และใหม่กว่า แอปที่ติดตั้งจะต้องมีสิทธิ์ "ติดตั้งแอปที่ไม่รู้จัก" สำหรับแหล่งที่มาเฉพาะ
- เอดีบี: คำสั่ง adb install สื่อสารโดยตรงกับบริการตัวจัดการแพ็คเกจผ่าน USB โดยไม่ผ่านตัวติดตั้งแบบกราฟิกทั้งหมด
โดยไม่คำนึงถึงแหล่งที่มา การติดตั้งทั้งหมดจะเข้าถึงบริการระบบเดียวกันในที่สุด: PackageManagerService (PMS) นี่คือหน่วยงานกลางสำหรับการดำเนินการแพ็คเกจทั้งหมดบน Android
ขั้นตอนที่ 2: การแยกวิเคราะห์แพ็คเกจ
ก่อนอื่น ระบบจำเป็นต้องทำความเข้าใจก่อนว่ากำลังติดตั้งอะไร PackageManagerService เรียกใช้ PackageParser เพื่ออ่านไฟล์ APK และแตกข้อมูลเมตาของมัน
โปรแกรมแยกวิเคราะห์จะอ่านไฟล์ AndroidManifest.xml จากภายใน APK ไฟล์ XML ไบนารีนี้มีข้อมูลสำคัญ:
- ชื่อแพ็คเกจ: ตัวระบุเฉพาะสำหรับแอป (เช่น com.example.myapp)
- รหัสเวอร์ชันและชื่อ: ใช้เพื่อพิจารณาว่านี่คือการอัพเกรดหรือการติดตั้งใหม่
- เวอร์ชัน SDK ขั้นต่ำและเป้าหมาย: กำหนดความเข้ากันได้กับอุปกรณ์
- สิทธิ์ที่ประกาศ: ทั้งสิทธิ์ที่แอปร้องขอและสิทธิ์ที่กำหนดเองที่กำหนด
- กิจกรรม ส่วนประกอบ: บริการ เครื่องรับกระจายเสียง และผู้ให้บริการเนื้อหาที่แอปลงทะเบียน
- ข้อกำหนดของ คุณสมบัติด้านฮาร์ดแวร์และซอฟต์แวร์: เช่น กล้อง, GPS หรือเวอร์ชัน OpenGL เฉพาะ
หากไฟล์ Manifest มีรูปแบบไม่ถูกต้องหรือโครงสร้าง APK ไม่ถูกต้อง การติดตั้งจะล้มเหลวในขั้นตอนนี้พร้อมกับข้อความ "ข้อผิดพลาดในการแยกวิเคราะห์" นี่เป็นหนึ่งในสาเหตุที่พบบ่อยที่สุดที่ทำให้ APK ที่ไซด์โหลดไม่สามารถติดตั้งได้
ขั้นตอนที่ 3: การตรวจสอบความเข้ากันได้
เมื่อแยกวิเคราะห์รายการแล้ว ระบบจะทำการตรวจสอบความเข้ากันได้หลายชุด:
- เวอร์ชัน SDK: หาก minSdkVersion ของแอปสูงกว่าระดับ API ของอุปกรณ์ การติดตั้งจะถูกปฏิเสธ
- ความเข้ากันได้ของ ABI: หาก APK มีไลบรารีดั้งเดิม ระบบจะตรวจสอบว่าตรงกับสถาปัตยกรรม CPU ของอุปกรณ์หรือไม่ APK ที่มีเฉพาะไลบรารี armeabi-v7a จะไม่ติดตั้งบนอุปกรณ์ที่ใช้ x86 เท่านั้น
- คุณสมบัติที่จำเป็น: หากแอปประกาศคุณสมบัติฮาร์ดแวร์ที่จำเป็น (เช่น android.hardware.telephony) ระบบจะตรวจสอบว่าอุปกรณ์รองรับคุณสมบัติดังกล่าว
- พื้นที่เก็บข้อมูลที่มีอยู่: ระบบจะตรวจสอบว่ามีพื้นที่ว่างเพียงพอที่จะติดตั้งแอปหรือไม่ รวมถึงพื้นที่สำหรับไลบรารีเนทิฟที่แตกออกมาและไฟล์ DEX ที่ปรับให้เหมาะสม
ขั้นตอนที่ 4: การตรวจสอบลายเซ็น
นี่เป็นหนึ่งในขั้นตอนที่สำคัญที่สุดในกระบวนการติดตั้ง Android ตรวจสอบลายเซ็นการเข้ารหัสของ APK เพื่อให้มั่นใจถึงความสมบูรณ์และความถูกต้อง
กระบวนการตรวจสอบขึ้นอยู่กับแผนการลงนามที่มีอยู่:
ลายเซ็น V1 (การลงนาม JAR)
ระบบจะตรวจสอบไดเร็กทอรี META-INF/ เพื่อหาไฟล์ลายเซ็น (.SF, .RSA หรือ .DSA แต่ละไฟล์ใน APK ได้รับการตรวจสอบเทียบกับไดเจสต์ที่แสดงอยู่ในไฟล์ Manifest สิ่งนี้ช้าเพราะทุกไฟล์จะต้องถูกแฮชแยกกัน)
ลายเซ็น V2 (โครงการลายเซ็น APK v2)
เปิดตัวใน Android 7.0 รูปแบบนี้ลงนาม APK ทั้งหมดเป็นไบนารี่หยด บล็อกลายเซ็นถูกแทรกระหว่างไดเร็กทอรีกลาง ZIP และเรกคอร์ดจุดสิ้นสุดของไดเร็กทอรีกลาง การยืนยันทำได้เร็วกว่ามากเนื่องจากทำงานบนไบต์ดิบโดยไม่จำเป็นต้องขยายขนาดแต่ละรายการ
ลายเซ็น V3 (การหมุนคีย์)
พร้อมใช้งานจาก Android 9.0, V3 ขยาย V2 พร้อมรองรับการหมุนเวียนคีย์ ประกอบด้วยโครงสร้างการพิสูจน์การหมุนเวียนที่เชื่อมโยงคีย์การเซ็นชื่อเก่าและใหม่ ช่วยให้นักพัฒนาสามารถเปลี่ยนคีย์การเซ็นชื่อของตนในขณะที่ยังคงความเข้ากันได้ของการอัปเดต
ลายเซ็น V4 (ส่วนเพิ่ม)
Android 11 เปิดตัว V4 สำหรับการติดตั้งเพิ่มเติม โดยมีลายเซ็นแบบต้นไม้ Merkle ที่ช่วยให้สามารถตรวจสอบแต่ละบล็อกในขณะที่สตรีมไปยังอุปกรณ์ได้
หากการตรวจสอบลายเซ็นล้มเหลวไม่ว่าด้วยเหตุผลใดก็ตาม การติดตั้งจะถูกยกเลิกทันที คุณสามารถตรวจสอบลายเซ็น APK ก่อนการติดตั้งได้โดยใช้ เครื่องมือตรวจสอบ APK ของเรา
อัปเดตการจับคู่ลายเซ็น
หากมีการติดตั้งแอปที่มีชื่อแพ็กเกจเดียวกันอยู่แล้ว ระบบจะทำการตรวจสอบเพิ่มเติม: ใบรับรองการลงนามของ APK ใหม่จะต้องตรงกับใบรับรองของการติดตั้งที่มีอยู่ วิธีนี้จะป้องกันไม่ให้ฝ่ายที่เป็นอันตรายแทนที่แอปที่ถูกต้องด้วยเวอร์ชันที่ถูกดัดแปลง หากลายเซ็นไม่ตรงกัน คุณจะเห็นข้อผิดพลาด "ไม่ได้ติดตั้งแอป: แพ็คเกจขัดแย้งกับแพ็คเกจที่มีอยู่โดยใช้ชื่อเดียวกัน"
ขั้นตอนที่ 5: การยืนยันผู้ใช้
สำหรับการติดตั้งแบบไซด์โหลด ระบบจะแสดงกล่องโต้ตอบการยืนยันการติดตั้งที่แสดง:
- ชื่อแอปและไอคอน (ดึงมาจากทรัพยากรของ APK)
- สิทธิ์การร้องขอแอป (บน Android เวอร์ชันเก่า)
- ไม่ว่าจะเป็นการติดตั้งใหม่หรือการอัปเดต
- คำเตือนเกี่ยวกับแหล่งที่มาของแอปหรือความเสี่ยงที่อาจเกิดขึ้น
ใน Android 12 ขึ้นไป หน้าจอยืนยันจะง่ายกว่า เนื่องจากจะให้สิทธิ์รันไทม์แยกกันเมื่อแอปต้องการสิทธิ์ดังกล่าวในครั้งแรก แทนที่จะให้สิทธิ์ในเวลาติดตั้ง
ขั้นตอนที่ 6: การแยกไฟล์และการวางตำแหน่ง
เมื่อผู้ใช้ยืนยัน (หรือสำหรับการติดตั้ง Play Store โดยอัตโนมัติ) ระบบจะเริ่มแยกและวางไฟล์:
ที่เก็บข้อมูลAPK
ไฟล์ APK เองก็ถูกคัดลอกไปยัง /data/app/[package-name]-[random]/base.apk สำหรับการติดตั้ง APK แบบแยก ไฟล์เพิ่มเติม เช่น split_config.arm64_v8a.apk จะถูกวางไว้ข้างๆ APK พื้นฐาน APK ดั้งเดิมในโฟลเดอร์ดาวน์โหลดไม่ได้รับการแก้ไขหรือลบ
การแยกไลบรารีพื้นเมือง
หาก APK มีไลบรารีดั้งเดิม (ในไดเร็กทอรี lib/ ไลบรารีเหล่านั้นจะถูกแตกออกมาเป็น /data/app/[package-name]-[random]/lib/[abi]/ ใน Android เวอร์ชันใหม่กว่า แอปสามารถเลือกที่จะบีบอัดไลบรารีดั้งเดิมภายใน APK และโหลดไลบรารีโดยตรงโดยใช้ android:extractNativeLibs="false" ซึ่งช่วยประหยัดพื้นที่จัดเก็บข้อมูล)
การสร้างไดเร็กทอรีข้อมูล
ระบบจะสร้างไดเร็กทอรีข้อมูลส่วนตัวของแอปที่ /data/data/[package-name]/ (หรือ /data/user/0/[package-name]/ บนอุปกรณ์ที่มีผู้ใช้หลายคน) ไดเร็กทอรีนี้เป็นของ Linux UID ที่ไม่ซ้ำกันซึ่งกำหนดให้กับแอป ทำให้มั่นใจได้ว่าไม่มีแอปอื่นใดที่สามารถเข้าถึงได้หากไม่มีสิทธิ์รูท
ขั้นตอนที่ 7: การเพิ่มประสิทธิภาพ DEX
ขั้นตอนนี้เป็นขั้นตอนที่ Android แปลงรหัสไบต์ของแอปเป็นรูปแบบที่ปรับให้เหมาะกับฮาร์ดแวร์เฉพาะของอุปกรณ์ กระบวนการนี้มีการพัฒนาอย่างมากเหนือประวัติศาสตร์ของ Android:
ยุค Dalvik (Android 4.4 และรุ่นก่อนหน้า)
เครื่องเสมือน Dalvik ดั้งเดิมใช้การคอมไพล์ Just-In-Time (JIT) ระหว่างการติดตั้ง ไฟล์ classes.dex ได้รับการปรับให้เป็นไฟล์ ODEX ที่มีไบต์โค้ดที่ได้รับการตรวจสอบและปรับให้เหมาะสมแล้ว สิ่งนี้ค่อนข้างเร็ว แต่หมายความว่าแอปทำงานช้าลงในช่วงรันไทม์เนื่องจากโค้ดส่วนใหญ่ยังคงถูกตีความ
ART กับ AOT (Android 5.0 ถึง 6.0)
Android Runtime (ART) เข้ามาแทนที่ Dalvik และแนะนำการคอมไพล์ Ahead-Of-Time (AOT) ระหว่างการติดตั้ง รหัสไบต์ DEX ทั้งหมดจะถูกคอมไพล์เป็นรหัสเครื่องเนทิฟ ทำให้แอปทำงานเร็วขึ้น แต่เพิ่มเวลาการติดตั้งและการใช้พื้นที่เก็บข้อมูลมากขึ้นอย่างมาก แอพบางตัวใช้เวลาติดตั้งหลายนาที
การรวบรวมโปรไฟล์ที่แนะนำ (Android 7.0+)
Modern Android ใช้วิธีการแบบไฮบริด ระหว่างการติดตั้ง จะมีการรวบรวมเฉพาะเส้นทางการเริ่มต้นที่สำคัญเท่านั้น ในขณะที่ผู้ใช้รันแอป ระบบจะรวบรวมโปรไฟล์การดำเนินการที่ระบุเส้นทางโค้ดที่ใช้บ่อย ในระหว่างการบำรุงรักษาที่ไม่ได้ใช้งาน (โดยทั่วไปคือขณะชาร์จข้ามคืน) ระบบจะรวบรวมเส้นทางลัดเหล่านี้ไปเป็นโค้ดเนทีฟ สิ่งนี้จะรักษาสมดุลของความเร็วการติดตั้ง การใช้พื้นที่เก็บข้อมูล และประสิทธิภาพรันไทม์
โค้ดที่คอมไพล์แล้วจะถูกจัดเก็บไว้ใน /data/dalvik-cache/ หรือข้าง APK เป็นไฟล์ .odex, .vdex และ .art ไฟล์ .vdex มีรหัส DEX ที่ตรวจสอบแล้ว ไฟล์ .odex มีโค้ดเนทิฟที่คอมไพล์แล้ว และไฟล์ .art มีอิมเมจฮีปที่เตรียมใช้งานไว้ล่วงหน้าเพื่อการเริ่มต้นที่เร็วขึ้น
ขั้นตอนที่ 8: การลงทะเบียนการอนุญาต
PackageManagerService ลงทะเบียนสิทธิ์และส่วนประกอบที่ประกาศของแอปกับระบบ:
- สิทธิ์เวลาติดตั้ง (เช่น INTERNET หรือ VIBRATE จะได้รับโดยอัตโนมัติโดยไม่ต้องโต้ตอบกับผู้ใช้)
- สิทธิ์รันไทม์ (เช่น CAMERA หรือ LOCATION ได้รับการลงทะเบียนแล้วแต่ไม่ได้รับอนุญาต แอปจะต้องขอเมื่อรันไทม์)
- ตัวกรองเจตนา ได้รับการลงทะเบียนแล้ว ดังนั้นระบบจึงรู้ว่าแอปใดสามารถจัดการการกระทำใดได้ (เช่น การเปิด URL หรือการแชร์เนื้อหา)
- ผู้ให้บริการเนื้อหา ได้รับการลงทะเบียนกับหน่วยงานเพื่อให้แอปอื่นสามารถสืบค้นได้
ขั้นตอนที่ 9: การรวมระบบ
ขั้นตอนสุดท้ายรวมแอปเข้ากับระบบ Android:
- อัพเดตฐานข้อมูลแพ็คเกจ: ฐานข้อมูลแพ็กเกจของระบบ (/data/system/packages.xml) ได้รับการอัปเดตด้วยข้อมูลของแอปใหม่ รวมถึง UID ที่ได้รับมอบหมาย สิทธิ์ และการประกาศส่วนประกอบ
- การแจ้งเตือนตัวเรียกใช้: ตัวเปิดหน้าจอหลักจะได้รับแจ้งเกี่ยวกับแอปใหม่ เพื่อให้สามารถแสดงไอคอนแอปได้
- ออกอากาศ: ระบบส่งการออกอากาศ PACKAGE_ADDED เพื่อให้แอปอื่นๆ ตอบสนองต่อการติดตั้งใหม่ (เช่น แอปสำรองข้อมูลอาจกำหนดเวลาการสำรองข้อมูล)
- บริบทของ SELinux: ไฟล์ของแอปมีป้ายกำกับด้วยบริบทความปลอดภัยของ SELinux ที่เหมาะสม โดยอิงตามเวอร์ชัน SDK เป้าหมายและการอนุญาตที่ประกาศ
เหตุใดการติดตั้งจึงล้มเหลว
การทำความเข้าใจไปป์ไลน์การติดตั้งจะช่วยวินิจฉัยความล้มเหลวทั่วไป:
- "ข้อผิดพลาดในการแยกวิเคราะห์": APK เสียหาย ไม่สมบูรณ์ หรือมีรายการที่มีรูปแบบไม่ถูกต้อง สิ่งนี้มักเกิดขึ้นกับการดาวน์โหลดที่ไม่สมบูรณ์หรือไฟล์ที่แปลงไม่ถูกต้อง
- "ไม่ได้ติดตั้งแอป" (ลายเซ็นไม่ตรงกัน): คุณกำลังพยายามอัปเดตแอปด้วย APK ที่ลงนามโดยคีย์อื่น คุณต้องถอนการติดตั้งเวอร์ชันที่มีอยู่ก่อน
- "พื้นที่เก็บข้อมูลไม่เพียงพอ": พื้นที่ไม่เพียงพอสำหรับ APK, ไลบรารีที่แตกออกมา และเอาต์พุตการเพิ่มประสิทธิภาพ DEX โดยทั่วไปพื้นที่ที่ต้องการคือ 2-3 เท่าของขนาด APK
- "แพ็คเกจขัดแย้งกับแพ็คเกจที่มีอยู่": ชื่อแพ็คเกจเดียวกันแต่ลายเซ็นต่างกัน เป็นเรื่องปกติเมื่อสลับระหว่าง Play Store และเวอร์ชันไซด์โหลด
- ดาวน์เกรดเวอร์ชันถูกบล็อก: ตามค่าเริ่มต้น Android จะป้องกันการติดตั้งเวอร์ชันเก่ากว่าเวอร์ชันที่ใหม่กว่า ADB สามารถแทนที่สิ่งนี้ด้วย adb install -d
แยกการติดตั้ง APK
เมื่อติดตั้ง APK แบบแยก (จาก App Bundle) กระบวนการจะแตกต่างออกไปเล็กน้อย ระบบใช้ การติดตั้งตามเซสชัน API:
- มีการสร้างเซสชันการติดตั้งใหม่
- APK แยกแต่ละรายการจะถูกเขียนลงในเซสชัน
- เซสชั่นถูกคอมมิต ทำให้เกิดไปป์ไลน์การยืนยันแบบสมบูรณ์
- การแยกทั้งหมดต้องมีชื่อแพ็กเกจ รหัสเวอร์ชัน และใบรับรองการลงนามที่ตรงกัน
นี่คือกลไกที่ใช้โดยโปรแกรมติดตั้ง XAPK และเครื่องมือเช่น การรวม APKS เป็น APK ของเราเพื่อจัดการการติดตั้งหลายไฟล์
การติดตั้งผ่าน ADB
เมื่อคุณใช้ adb install กระบวนการจะข้ามตัวติดตั้งแบบกราฟิก แต่เป็นไปตามไปป์ไลน์ภายในเดียวกัน ADB สื่อสารกับบริการตัวจัดการแพ็คเกจผ่านการเชื่อมต่อซ็อกเก็ต รองรับแฟล็กเพิ่มเติมที่ไม่สามารถใช้งานได้ผ่าน GUI:
- -r: แทนที่แอปที่มีอยู่ (อนุญาตให้ติดตั้งใหม่)
- -d: อนุญาตให้ดาวน์เกรดเวอร์ชัน
- -g: ให้สิทธิ์รันไทม์ทั้งหมดทันที
- -t: อนุญาตให้ติดตั้ง APK สำหรับการทดสอบเท่านั้น
- --install-multiple: ติดตั้ง APK แบบแยกในเซสชันเดียว
จะเกิดอะไรขึ้นระหว่างการถอนการติดตั้ง
เพื่อความสมบูรณ์ นี่คือสิ่งที่จะเกิดขึ้นเมื่อมีการลบแอป:
- กระบวนการของแอปถูกหยุดทำงาน
- APK และไลบรารีที่แตกออกมาจะถูกลบออกจาก /data/app/
- ไดเร็กทอรีข้อมูลส่วนตัวของแอปจะถูกลบออก (เว้นแต่ผู้ใช้จะเลือกที่จะเก็บข้อมูล)
- ไฟล์แคช DEX ที่คอมไพล์แล้วจะถูกลบ
- ฐานข้อมูลแพ็คเกจได้รับการอัพเดต
- การออกอากาศ PACKAGE_REMOVED จะถูกส่งไป
- ตัวเรียกใช้งานจะลบไอคอนแอป
โปรดทราบว่าไฟล์เฉพาะแอปบนที่จัดเก็บข้อมูลภายนอก (/Android/data/[package]/ และ /Android/obb/[package]/ จะถูกลบใน Android 10 และใหม่กว่าด้วย ด้วยการบังคับใช้พื้นที่เก็บข้อมูลแบบกำหนดขอบเขต)
เหตุใดการทำความเข้าใจ PackageManager จึงช่วยประหยัดเวลาในการดีบัก
กระบวนการติดตั้ง Android เป็นลำดับการตรวจสอบความปลอดภัย การทำงานของไฟล์ และการรวมระบบที่จัดทำขึ้นอย่างระมัดระวัง แต่ละขั้นตอนมีจุดมุ่งหมาย ตั้งแต่การปกป้องผู้ใช้จากแอปที่ถูกดัดแปลงไปจนถึงการปรับประสิทธิภาพให้เหมาะสมสำหรับฮาร์ดแวร์เฉพาะ เมื่อการติดตั้งล้มเหลว ข้อผิดพลาดมักจะชี้ไปที่ขั้นตอนเฉพาะในไปป์ไลน์นี้ และการทำความเข้าใจกระบวนการนี้จะช่วยให้คุณวินิจฉัยและแก้ไขปัญหาได้อย่างรวดเร็ว
การติดตั้งจาก Play Store, ไซด์โหลด APK ด้วยมือ และพุชบิลด์ด้วย ADB ช่องทางทั้งหมดผ่านไปป์ไลน์พื้นฐานเดียวกัน ซึ่งเป็นช่องทางที่ทำให้แน่ใจว่าทุกแอปบนอุปกรณ์ของคุณได้รับการตรวจสอบ วางอย่างถูกต้อง และปรับให้เหมาะกับฮาร์ดแวร์ของคุณ