وقتی روی «نصب» روی یک فایل APK ضربه میزنید یا برنامهای را از Play Store دانلود میکنید، یک توالی پیچیده از عملیات در پشت صحنه شروع میشود. آنچه که یک نوار پیشرفت ساده به نظر می رسد در واقع ده ها مرحله را شامل تجزیه بسته، تأیید رمزنگاری، مدیریت مجوز، استخراج فایل و بهینه سازی کد را نشان می دهد. درک این فرآیند به توضیح اینکه چرا گاهی اوقات نصب ها با شکست مواجه می شوند و چه کاری می توانید در مورد آن انجام دهید کمک می کند.
در این مقاله، تمام مراحل اصلی نصب Android را از لحظهای که سیستم یک APK دریافت میکند تا زمانی که برنامه آماده راهاندازی میشود، مرور میکنیم.
مرحله 1: شروع نصب
فرآیند نصب بسته به منبع متفاوت شروع می شود:
- پلی استور: برنامه Play Store APK (یا APK های تقسیم شده) را دانلود می کند و با نصب کننده بسته سیستم با امتیازات ویژه ای تماس می گیرد که برخی از تأییدیه های کاربر را دور می زند.
- بارگذاری جانبی: هنگامی که یک فایل APK را باز می کنید، Android فعالیت نصب کننده بسته را راه اندازی می کند. در Android 8.0 و جدیدتر، برنامه نصبکننده باید مجوز «نصب برنامههای ناشناخته» را برای منبع خاص خود داشته باشد.
- ADB: دستور adb install مستقیماً با سرویس مدیریت بسته از طریق USB ارتباط برقرار می کند و نصب کننده گرافیکی را به طور کامل دور می زند.
صرف نظر از منبع، همه نصب ها در نهایت به یک سرویس سیستم می رسند: PackageManagerService (PMS). این مرجع مرکزی برای تمام عملیات بسته در Android است.
مرحله 2: تجزیه بسته
قبل از هر چیز دیگری، سیستم باید بفهمد که در حال نصب چه چیزی است. PackageManagerService از PackageParser برای خواندن فایل APK و استخراج فراداده آن فراخوانی می کند.
تجزیه کننده فایل AndroidManifest.xml را از داخل APK می خواند. این فایل XML باینری حاوی اطلاعات حیاتی است:
- نام بسته: شناسه منحصر به فرد برنامه (به عنوان مثال، com.example.myapp)
- کد و نام نسخه: برای تعیین اینکه آیا این یک ارتقا است یا یک نصب جدید استفاده می شود
- نسخه های حداقل و هدف SDK: سازگاری با دستگاه را تعیین می کند
- مجوزهای اعلام شده: هم به درخواست های برنامه اجازه می دهد و هم مجوزهای سفارشی که تعریف می کند
- اجزاء: فعالیت ها، خدمات، گیرنده های پخش و ارائه دهندگان محتوا که برنامه ثبت می کند
- ویژگی های سخت افزاری و نرم افزاری: مورد نیاز مانند دوربین، GPS، یا نسخه های OpenGL خاص
اگر مانیفست نادرست باشد یا ساختار 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 با خلاصههای فهرستشده در مانیفست تأیید میشود. این سرعت کند است زیرا هر فایل باید به صورت جداگانه هش شود.
امضای V2 (APK Signature Scheme v2)
این طرح که در Android 7.0 معرفی شده است، کل APK را به عنوان یک حباب باینری امضا می کند. بلوک امضا بین دایرکتوری مرکزی ZIP و رکورد انتهای دایرکتوری مرکزی درج می شود. راستیآزمایی بسیار سریعتر است زیرا روی بایتهای خام بدون نیاز به فشردهسازی ورودیهای جداگانه عمل میکند.
امضای V3 (چرخش کلید)
موجود در Android 9.0، V3 گسترش V2 با پشتیبانی از چرخش کلید. این شامل یک ساختار اثبات چرخش است که کلیدهای امضای قدیمی و جدید را به هم پیوند می دهد و به توسعه دهندگان اجازه می دهد کلید امضای خود را تغییر دهند و در عین حال سازگاری به روز رسانی را حفظ کنند.
امضای V4 (افزایشی)
Android 11 نسخه 4 را برای نصب تدریجی معرفی کرد. این یک امضای مبتنی بر درخت Merkle را ارائه می دهد که اجازه می دهد تا تک تک بلوک ها را هنگام پخش جریانی به دستگاه تأیید کنید.
اگر تأیید امضا به هر دلیلی ناموفق باشد، نصب بلافاصله لغو می شود. میتوانید امضای APK را قبل از نصب با استفاده از ابزار تأیید کننده APK بررسی کنید.
به روز رسانی مطابقت امضا
اگر برنامهای با همان نام بسته قبلاً نصب شده باشد، سیستم یک بررسی اضافی انجام میدهد: گواهی امضای APK جدید باید با گواهی نصب موجود مطابقت داشته باشد. این مانع از جایگزینی یک برنامه قانونی با نسخه دستکاری شده توسط یک طرف مخرب می شود. اگر امضاها مطابقت نداشته باشند، خطای "برنامه نصب نشده است: بسته با یک بسته موجود به همین نام در تضاد است" خواهید دید.
مرحله 5: تایید کاربر
برای نصب های جانبی، سیستم یک گفتگوی تأیید نصب را نشان می دهد که نشان می دهد:
- نام و نماد برنامه (استخراج شده از منابع APK)
- به درخواست های برنامه اجازه می دهد (در نسخه های قدیمی Android)
- چه این یک نصب جدید باشد یا یک به روز رسانی
- هر گونه هشدار در مورد منبع برنامه یا خطرات احتمالی
در Android 12 و بالاتر، صفحه تأیید سادهتر است، زیرا مجوزهای زمان اجرا بهجای زمان نصب، زمانی که برنامه برای اولین بار به آنها نیاز دارد، بهصورت جداگانه اعطا میشود.
مرحله 6: استخراج و قرار دادن فایل
پس از تأیید کاربر (یا برای نصب فروشگاه Play، به صورت خودکار)، سیستم شروع به استخراج و قرار دادن فایلها میکند:
ذخیره سازی 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]/ در دستگاه های چند کاربره) ایجاد می کند. این دایرکتوری متعلق به یک UID لینوکس منحصر به فرد است که به برنامه اختصاص داده شده است و اطمینان می دهد که هیچ برنامه دیگری نمی تواند بدون امتیازات ریشه به آن دسترسی داشته باشد.
مرحله 7: بهینه سازی DEX
این مرحله جایی است که Android بایت کد برنامه را به قالبی بهینه شده برای سخت افزار خاص دستگاه تبدیل می کند. این فرآیند به طور قابل توجهی در طول تاریخ Android تکامل یافته است:
عصر دالویک (Android 4.4 و نسخه های قبلی)
ماشین مجازی اصلی دالویک از کامپایل Just-In-Time (JIT) استفاده می کرد. در حین نصب، فایل classes.dex به یک فایل ODEX که حاوی بایت کد تایید شده و بهینه شده بود، بهینه شد. این نسبتاً سریع بود اما به این معنی بود که برنامه در زمان اجرا کندتر اجرا می شد زیرا بیشتر کدها هنوز تفسیر می شدند.
هنر با AOT (Android 5.0 تا 6.0)
Android Runtime (ART) جایگزین Dalvik شد و کامپایل Ahead-Of-Time (AOT) را معرفی کرد. در طول نصب، کل بایت کد DEX به کد ماشین بومی کامپایل شد. این باعث شد برنامهها سریعتر اجرا شوند، اما زمان نصب و استفاده از فضای ذخیرهسازی را بهطور قابلتوجهی افزایش دادند. نصب برخی از برنامه ها چند دقیقه طول کشید.
تلفیقی با هدایت نمایه (Android 7.0 و بالاتر)
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 وجود ندارد. فضای واقعی مورد نیاز معمولاً ۲ تا ۳ برابر اندازه APK است.
- "بسته با بسته موجود تداخل دارد": همان نام بسته اما امضای متفاوت. هنگام جابجایی بین Play Store و نسخه های جانبی رایج است.
- ارتقاء نسخه مسدود شده است: بهطور پیشفرض، Android از نصب نسخه قدیمیتر به نسخه جدیدتر جلوگیری میکند. ADB می تواند این مورد را با adb install -d لغو کند.
تقسیم APK نصب
هنگام نصب فایلهای APK تقسیمشده (از App Bundles)، روند کمی متفاوت است. این سیستم از یک API نصب مبتنی بر جلسه استفاده می کند:
- یک جلسه نصب جدید ایجاد می شود
- هر APK تقسیم شده در جلسه نوشته می شود
- جلسه متعهد شده است و خط لوله تأیید کامل را راه اندازی می کند
- همه تقسیمها باید دارای نام بستهها، کدهای نسخه و گواهی امضای منطبق باشند
این مکانیزمی است که توسط نصب کنندگان XAPK و ابزارهایی مانند ادغام APKS به APK ما برای مدیریت نصب چند فایل استفاده می شود.
نصب از طریق ADB
هنگامی که از adb install استفاده می کنید، فرآیند نصب کننده گرافیکی را دور می زند اما همان خط لوله داخلی را دنبال می کند. ADB از طریق یک اتصال سوکت با سرویس مدیریت بسته ارتباط برقرار می کند. از پرچم های اضافی که از طریق رابط کاربری گرافیکی در دسترس نیستند پشتیبانی می کند:
- -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 از طریق همان قیف زیربنایی، قیف که مطمئن میشود همه برنامههای دستگاه شما تأیید، درست قرار گرفته و برای سختافزار شما بهینه شده است.