از اندروید ۹ (سطح API 28)، پلتفرم رابطهای غیر SDK که برنامه شما میتواند از آنها استفاده کند را محدود میکند. این محدودیتها هر زمان که یک برنامه به یک رابط غیر SDK ارجاع دهد یا سعی کند با استفاده از reflection یا JNI به آن دسترسی پیدا کند، اعمال میشوند. این محدودیتها برای کمک به بهبود تجربه کاربر و توسعهدهنده و کاهش خطرات خرابی برای کاربران و انتشار اضطراری برای توسعهدهندگان اعمال شدهاند. برای اطلاعات بیشتر در مورد این تصمیم، به بخش «بهبود پایداری با کاهش استفاده از رابطهای غیر SDK» مراجعه کنید.
تفاوت بین رابطهای SDK و غیر SDK
به طور کلی، رابطهای SDK عمومی، آنهایی هستند که در فهرست بستههای چارچوب اندروید مستند شدهاند. مدیریت رابطهای غیر SDK، جزئیات پیادهسازی است که API آن را خلاصه میکند، بنابراین این رابطها بدون اطلاع قبلی قابل تغییر هستند.
برای جلوگیری از خرابیها و رفتارهای غیرمنتظره، برنامهها فقط باید از بخشهای رسمی مستند شده کلاسها در SDK استفاده کنند. این همچنین بدان معنی است که هنگام تعامل با یک کلاس با استفاده از مکانیسمهایی مانند reflection، نباید به متدها یا فیلدهایی که در SDK فهرست نشدهاند، دسترسی پیدا کنید.
لیستهای API غیر SDK
با هر انتشار اندروید، رابطهای کاربری غیر SDK بیشتری محدود میشوند. ما میدانیم که این محدودیتها میتوانند بر گردش کار انتشار شما تأثیر بگذارند و میخواهیم مطمئن شویم که شما ابزارهایی برای تشخیص استفاده از رابطهای کاربری غیر SDK، فرصتی برای ارائه بازخورد و زمان برای برنامهریزی و تطبیق با سیاستهای جدید دارید.
برای به حداقل رساندن تأثیر محدودیتهای غیر SDK بر گردش کار توسعه شما، رابطهای غیر SDK به لیستهایی تقسیم میشوند که میزان محدودیت استفاده از آنها را بسته به اینکه کدام سطح API هدف قرار گرفته است، تعریف میکنند. جدول زیر هر یک از این لیستها را شرح میدهد:
| فهرست | برچسبهای کد | توضیحات |
|---|---|---|
| لیست سیاه |
| رابطهای غیر SDK که صرف نظر از سطح API هدف برنامهتان نمیتوانید از آنها استفاده کنید. اگر برنامه شما سعی کند به یکی از این رابطها دسترسی پیدا کند، سیستم خطایی صادر میکند . |
| مسدود شده به صورت مشروط |
| از اندروید ۹ (سطح API 28)، هر سطح API دارای رابطهای غیر SDK است که وقتی یک برنامه آن سطح API را هدف قرار میدهد، محدود میشوند. این لیستها با حداکثر سطح API ( اگر برنامه شما سعی کند به رابطی دسترسی پیدا کند که برای سطح API هدف شما محدود شده است، سیستم طوری رفتار میکند که انگار API بخشی از لیست سیاه است . |
| پشتیبانی نشده |
| رابطهای غیر SDK که بدون محدودیت هستند و برنامه شما میتواند از آنها استفاده کند. با این حال، توجه داشته باشید که این رابطها پشتیبانی نمیشوند و بدون اطلاع قبلی قابل تغییر هستند. انتظار میرود که این رابطها در نسخههای آینده اندروید در لیست max-target-x به صورت مشروط مسدود شوند. |
| SDK |
| رابطهایی که میتوانند آزادانه مورد استفاده قرار گیرند و اکنون به عنوان بخشی از فهرست بستههای چارچوب اندروید که رسماً مستند شده است، پشتیبانی میشوند. |
| API های تست |
| رابطهایی که برای آزمایش داخلی سیستم استفاده میشوند، مانند APIهایی که آزمایش را از طریق مجموعه تست سازگاری (CTS) تسهیل میکنند. APIهای آزمایشی بخشی از SDK نیستند . از اندروید ۱۱ (سطح API ۳۰) ، APIهای آزمایشی در لیست سیاه قرار میگیرند، بنابراین برنامهها صرف نظر از سطح API هدفشان مجاز به استفاده از آنها نیستند. همه APIهای آزمایشی پشتیبانی نمیشوند و صرف نظر از سطح API پلتفرم، بدون اطلاع قبلی قابل تغییر هستند. |
اگرچه میتوانید از برخی رابطهای غیر SDK استفاده کنید (بسته به سطح API هدف برنامه شما)، استفاده از هر روش یا فیلد غیر SDK همیشه خطر بالای خرابی برنامه شما را به همراه دارد. اگر برنامه شما به رابطهای غیر SDK متکی است، باید برنامهریزی برای مهاجرت به رابطهای SDK یا سایر جایگزینها را آغاز کنید. اگر نمیتوانید جایگزینی برای استفاده از رابط غیر SDK برای یک ویژگی در برنامه خود پیدا کنید، باید یک API عمومی جدید درخواست کنید .
تعیین اینکه یک رابط به کدام لیست تعلق دارد
فهرست رابطهای غیر SDK به عنوان بخشی از پلتفرم ساخته شدهاند. برای اطلاعات مربوط به هر نسخه اندروید، به بخشهای زیر مراجعه کنید.
اندروید ۱۶
برای اندروید ۱۶ (سطح API ۳۶)، میتوانید فایل زیر را دانلود کنید که تمام رابطهای غیر SDK و لیستهای مربوط به آنها را شرح میدهد:
فایل: hiddenapi-flags.csv
مجموع مقابلهای SHA-256: 9102af02fe6ab68b92464bdff5e5b09f3bd62c65d1130aaf85d3296f17d38074
برای کسب اطلاعات بیشتر در مورد تغییرات فهرست APIهای غیر SDK در اندروید ۱۶، به بهروزرسانیهای محدودیتهای رابط کاربری غیر SDK در اندروید ۱۶ مراجعه کنید.
اندروید ۱۵
برای اندروید ۱۵ (سطح API 35)، میتوانید فایل زیر را دانلود کنید که تمام رابطهای غیر SDK و لیستهای مربوط به آنها را شرح میدهد:
فایل: hiddenapi-flags.csv
SHA-256 checksum: 40134e205e58922a708c453726b279a296e6a1f34a988abd90cec0f3432ea5a9
برای کسب اطلاعات بیشتر در مورد تغییرات فهرست APIهای غیر SDK در اندروید ۱۵، به بهروزرسانیهای محدودیتهای رابط کاربری غیر SDK در اندروید ۱۵ مراجعه کنید.
اندروید ۱۴
برای اندروید ۱۴ (سطح API ۳۴)، میتوانید فایل زیر را دانلود کنید که تمام رابطهای غیر SDK و لیستهای مربوط به آنها را شرح میدهد:
فایل: hiddenapi-flags.csv
مجموع مقابلهای SHA-256: 7e00db074cbe51c51ff4b411f7b48e98692951395c5c17d069c822cc1d0eae0f
برای کسب اطلاعات بیشتر در مورد تغییرات فهرست APIهای غیر SDK در اندروید ۱۴، به بهروزرسانیهای محدودیتهای رابط کاربری غیر SDK در اندروید ۱۴ مراجعه کنید.
اندروید ۱۳
برای اندروید ۱۳ (سطح API ۳۳)، میتوانید فایل زیر را دانلود کنید که تمام رابطهای غیر SDK و لیستهای مربوط به آنها را شرح میدهد:
فایل: hiddenapi-flags.csv
SHA-256 checksum: 233a277aa8ac475b6df61bffd95665d86aac6eb2ad187b90bf42a98f5f2a11a3
برای کسب اطلاعات بیشتر در مورد تغییرات فهرست APIهای غیر SDK در اندروید ۱۳، از جمله جایگزینهای API عمومی پیشنهادی برای APIهایی که به طور مشروط در اندروید ۱۳ مسدود شدهاند، به بهروزرسانیهای محدودیتهای رابط کاربری غیر SDK در اندروید ۱۳ مراجعه کنید.
اندروید ۱۲
برای اندروید ۱۲ (سطح API 31)، میتوانید فایل زیر را دانلود کنید که تمام رابطهای غیر SDK و لیستهای مربوط به آنها را شرح میدهد:
فایل: hiddenapi-flags.csv
مجموع کنترلی SHA-256: 40674ff4291eb268f86561bf687e69dbd013df9ec9531a460404532a4ac9a761
برای کسب اطلاعات بیشتر در مورد تغییرات فهرست APIهای غیر SDK در اندروید ۱۲، از جمله جایگزینهای API عمومی پیشنهادی برای APIهایی که به طور مشروط در اندروید ۱۲ مسدود شدهاند، به فهرست تغییرات برای اندروید ۱۲ مراجعه کنید.
اندروید ۱۱
برای اندروید ۱۱ (سطح API 30)، میتوانید فایل زیر را دانلود کنید که تمام رابطهای غیر SDK و لیستهای مربوط به آنها را شرح میدهد:
فایل: hiddenapi-flags.csv
مجموع مقابلهای SHA-256: a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56
برای کسب اطلاعات بیشتر در مورد تغییرات فهرست APIهای غیر SDK در اندروید ۱۱، از جمله جایگزینهای API عمومی پیشنهادی برای APIهایی که به طور مشروط در اندروید ۱۱ مسدود شدهاند، به فهرست تغییرات برای اندروید ۱۱ مراجعه کنید.
اندروید ۱۰
برای اندروید ۱۰ (سطح API ۲۹)، میتوانید فایل زیر را دانلود کنید که تمام رابطهای غیر SDK و لیستهای مربوط به آنها را شرح میدهد:
فایل: hiddenapi-flags.csv
مجموع مقابلهای SHA-256: f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb
برای کسب اطلاعات بیشتر در مورد تغییرات فهرست APIهای غیر SDK در اندروید ۱۰، از جمله جایگزینهای API عمومی پیشنهادی برای APIهایی که به طور مشروط در اندروید ۱۰ مسدود شدهاند، به فهرست تغییرات برای اندروید ۱۰ مراجعه کنید.
اندروید ۹
برای اندروید ۹ (سطح API 28)، فایل متنی زیر شامل فهرست APIهای غیر SDK است که محدود نشدهاند (در لیست خاکستری قرار دارند): hiddenapi-light-greylist.txt .
لیست مسدود شدهها ( blacklist ) و لیست APIهای مسدود شده مشروط (لیست خاکستری تیره) در زمان ساخت استخراج میشوند.
ایجاد لیست از AOSP
هنگام کار با AOSP، میتوانید یک فایل hiddenapi-flags.csv ایجاد کنید که شامل تمام رابطهای غیر SDK و لیستهای مربوط به آنها باشد. برای انجام این کار، منبع AOSP را دانلود کنید و سپس دستور زیر را اجرا کنید:
m out/soong/hiddenapi/hiddenapi-flags.csv
سپس میتوانید فایل را در آدرس زیر پیدا کنید:
out/soong/hiddenapi/hiddenapi-flags.csv
رفتار مورد انتظار هنگام دسترسی به رابطهای محدود غیر SDK
جدول زیر رفتاری را که میتوانید انتظار داشته باشید در صورت تلاش برنامه شما برای دسترسی به رابط کاربری غیر SDK که بخشی از لیست سیاه است، شرح میدهد.
| راههای دسترسی | نتیجه |
|---|---|
| دستورالعمل دالویک که به یک فیلد ارجاع میدهد | NoSuchFieldError رخ داد |
| دستورالعمل دالویک که به یک متد ارجاع میدهد | خطای NoSuchMethodError رخ داد |
انعکاس با استفاده از Class.getDeclaredField() یا Class.getField() | خطای NoSuchFieldException رخ داد |
بازتاب با استفاده از Class.getDeclaredMethod() و Class.getMethod() | خطای NoSuchMethodException رخ داد |
بازتاب با استفاده از Class.getDeclaredFields() و Class.getFields() | اعضای غیر SDK در نتایج نیستند |
بازتاب با استفاده از Class.getDeclaredMethods() و Class.getMethods() | اعضای غیر SDK در نتایج نیستند |
JNI با استفاده از env->GetFieldID() | NULL برگردانده میشود، NoSuchFieldError رخ میدهد |
JNI با استفاده از env->GetMethodID() | NULL برگردانده میشود، NoSuchMethodError رخ میدهد |
برنامه خود را برای رابطهای غیر SDK آزمایش کنید
روشهای مختلفی وجود دارد که میتوانید برای آزمایش رابطهای غیر SDK در برنامه خود استفاده کنید.
با استفاده از یک برنامهی قابل اشکالزدایی تست کنید
شما میتوانید با ساخت و اجرای یک برنامهی قابل اشکالزدایی روی یک دستگاه یا شبیهساز که اندروید ۹ (سطح API 28) یا بالاتر را اجرا میکند، رابطهای غیر SDK را آزمایش کنید. مطمئن شوید که دستگاه یا شبیهساز مورد استفاده شما با سطح API هدف برنامهی شما مطابقت دارد.
هنگام اجرای تستها روی برنامه شما، اگر برنامه شما به رابطهای غیر SDK خاصی دسترسی داشته باشد، سیستم یک پیام گزارش چاپ میکند. میتوانید پیامهای گزارش برنامه خود را بررسی کنید تا جزئیات زیر را بیابید:
- کلاس، نام و نوع تعریفشده (به فرمتی که توسط زمان اجرای اندروید استفاده میشود).
- روشهای دسترسی: یا از طریق لینک کردن، استفاده از بازتاب (reflection) یا استفاده از JNI.
- رابط غیر SDK به کدام لیست تعلق دارد.
شما میتوانید از adb logcat برای دسترسی به این پیامهای لاگ که زیر PID برنامهی در حال اجرا ظاهر میشوند، استفاده کنید. برای مثال، یک ورودی در لاگ ممکن است به شکل زیر باشد:
Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
تست با استفاده از StrictMode API
همچنین میتوانید با استفاده از StrictMode API، رابطهای غیر SDK را آزمایش کنید. برای فعال کردن این قابلیت، از متد detectNonSdkApiUsage استفاده کنید. پس از فعال کردن StrictMode API، میتوانید با استفاده از penaltyListener ، برای هر بار استفاده از یک رابط غیر SDK، یک callback دریافت کنید، که در آن میتوانید مدیریت سفارشی را پیادهسازی کنید. شیء Violation ارائه شده در callback از Throwable مشتق شده است و stack trace که در داخل آن قرار دارد، زمینه استفاده را فراهم میکند.
تست با استفاده از ابزار lint اندروید استودیو
هر زمان که برنامه خود را در اندروید استودیو میسازید، ابزار lint کد شما را برای یافتن مشکلات احتمالی بررسی میکند. اگر برنامه شما از رابطهای غیر SDK استفاده میکند، بسته به اینکه آن رابطها به کدام لیست تعلق دارند، ممکن است خطاهای ساخت یا هشدارهایی را مشاهده کنید.
همچنین میتوانید ابزار lint را از خط فرمان اجرا کنید یا بازرسیها را به صورت دستی روی یک پروژه، پوشه یا فایل خاص انجام دهید .
با استفاده از کنسول Play تست کنید
وقتی برنامه خود را در یک مسیر آزمایشی در کنسول Play آپلود میکنید، برنامه شما به طور خودکار برای مشکلات احتمالی آزمایش میشود و یک گزارش پیش از راهاندازی ایجاد میشود. اگر برنامه شما از رابطهای غیر SDK استفاده میکند، بسته به اینکه آن رابطها به کدام لیست تعلق دارند، یک خطا یا هشدار در گزارش پیش از راهاندازی نمایش داده میشود.
برای اطلاعات بیشتر، به بخش سازگاری با اندروید در بخش «استفاده از گزارشهای پیش از راهاندازی برای شناسایی مشکلات» مراجعه کنید.
درخواست یک API عمومی جدید
اگر نمیتوانید جایگزینی برای استفاده از رابط کاربری غیر SDK برای یک ویژگی در برنامه خود پیدا کنید، میتوانید با ایجاد یک درخواست ویژگی در ردیاب مشکل ما، یک API عمومی جدید درخواست کنید.
هنگام ایجاد درخواست ویژگی، اطلاعات زیر را ارائه دهید:
- از کدام API پشتیبانی نشده استفاده میکنید، از جمله توصیفگر کامل مشاهده شده در پیام
Accessing hidden ...logcat. - چرا باید از این APIها استفاده کنید، شامل جزئیاتی در مورد ویژگی سطح بالایی که API برای آن ضروری است، نه فقط جزئیات سطح پایین.
- چرا هرگونه API عمومی SDK مرتبط برای اهداف شما کافی نیست.
- هر گزینه دیگری که امتحان کردهاید و چرا جواب ندادهاند.
وقتی این جزئیات را در درخواست ویژگی خود ارائه میدهید، احتمال اعطای یک API عمومی جدید را افزایش میدهید.
سوالات دیگر
این بخش شامل پاسخ به برخی از سوالات دیگری است که توسعهدهندگان مرتباً میپرسند:
سوالات عمومی
گوگل چگونه میتواند مطمئن باشد که میتواند نیازهای همه برنامهها را از طریق issuetracker دریافت کند؟
ما لیستهای اولیه برای اندروید ۹ (سطح API 28) را از طریق تحلیل استاتیک برنامهها ایجاد کردیم که با استفاده از روشهای زیر تکمیل شد:
- تست دستی برترین برنامههای Play و Non-Play
- گزارشهای داخلی
- جمعآوری خودکار دادهها از کاربران داخلی
- گزارشهای پیشنمایش توسعهدهندگان
- تحلیل استاتیک اضافی که به گونهای طراحی شده بود که به طور محافظهکارانهای شامل موارد مثبت کاذب بیشتری باشد
همانطور که لیستها را برای هر نسخه جدید ارزیابی میکنیم، میزان استفاده از API و همچنین بازخورد توسعهدهندگان را از طریق ردیاب مشکلات در نظر میگیریم.
چگونه میتوانم دسترسی به رابطهای غیر SDK را فعال کنم؟
شما میتوانید با استفاده از دستورات adb برای تغییر سیاست اجرای API، دسترسی به رابطهای غیر SDK را در دستگاههای در حال توسعه فعال کنید. دستوراتی که استفاده میکنید بسته به سطح API متفاوت است. این دستورات نیازی به دستگاه روت شده ندارند.
- اندروید ۱۰ (سطح API ۲۹) یا بالاتر
برای فعال کردن دسترسی، از adb زیر استفاده کنید
فرمان:
adb shell settings put global hidden_api_policy 1
برای تنظیم مجدد سیاست اجرای API به تنظیمات پیشفرض، از دستور زیر استفاده کنید:
adb shell settings delete global hidden_api_policy
- اندروید ۹ (سطح API 28)
برای فعال کردن دسترسی، از دستورات adb زیر استفاده کنید:
adb shell settings put global hidden_api_policy_pre_p_apps 1adb shell settings put global hidden_api_policy_p_apps 1برای تنظیم مجدد سیاست اجرای API به تنظیمات پیشفرض، از دستورات زیر استفاده کنید:
adb shell settings delete global hidden_api_policy_pre_p_appsadb shell settings delete global hidden_api_policy_p_apps
میتوانید عدد صحیح را در سیاست اجرای API روی یکی از مقادیر زیر تنظیم کنید:
- ۰: غیرفعال کردن تمام تشخیص رابطهای غیر SDK. استفاده از این تنظیم، تمام پیامهای گزارش مربوط به استفاده از رابطهای غیر SDK را غیرفعال میکند و مانع از آزمایش برنامه شما با استفاده از
StrictModeAPI میشود. این تنظیم توصیه نمیشود. - ۱: دسترسی به تمام رابطهای غیر SDK را فعال کنید، اما پیامهای گزارش را با هشدارهایی برای هرگونه استفاده از رابط غیر SDK چاپ کنید. استفاده از این تنظیم همچنین به شما امکان میدهد برنامه خود را با استفاده از API
StrictModeآزمایش کنید. - ۲: استفاده از رابطهای غیر SDK که متعلق به لیست سیاه هستند یا به طور مشروط برای سطح API هدف شما مسدود شدهاند را غیرفعال کنید.
سوالاتی در مورد لیستهای رابط غیر SDK
از کجا میتوانم لیستهای API غیر SDK را در تصویر سیستم پیدا کنم؟
آنها در بیتهای پرچم دسترسی به فیلد و متد در فایلهای dex پلتفرم کدگذاری میشوند. هیچ فایل جداگانهای در تصویر سیستم وجود ندارد که حاوی این لیستها باشد.
آیا فهرست APIهای غیر SDK در دستگاههای OEM مختلف با نسخههای اندروید یکسان، یکسان است؟
تولیدکنندگان اصلی تجهیزات (OEM) میتوانند رابطهای خود را به لیست سیاه اضافه کنند، اما نمیتوانند رابطها را از لیستهای API غیر SDK AOSP حذف کنند. CDD از چنین تغییراتی جلوگیری میکند و آزمایشهای CTS تضمین میکنند که Android Runtime این لیست را اجرا میکند.
سوالاتی در مورد سازگاری برنامههای مرتبط
آیا محدودیتی برای رابطهای غیر NDK در کد بومی وجود دارد؟
کیت توسعه نرمافزار اندروید (SDK) شامل رابطهای جاوا است. این پلتفرم در اندروید ۷ (سطح API ۲۶) شروع به محدود کردن دسترسی به رابطهای غیر NDK برای کد بومی C/C++ کرد. برای اطلاعات بیشتر، به «بهبود پایداری با محدودیتهای نماد خصوصی C/C++ در اندروید N» مراجعه کنید.
آیا برنامهای برای محدود کردن دستکاری فایلهای dex2oat یا DEX وجود دارد؟
ما برنامهی فعالی برای محدود کردن دسترسی به فایل باینری dex2oat نداریم، اما قصد نداریم فرمت فایل DEX پایدار باشد یا رابط عمومی فراتر از بخشهایی باشد که به طور عمومی در فرمت اجرایی Dalvik مشخص شدهاند. ما حق تغییر یا حذف dex2oat و بخشهای نامشخص فرمت DEX را در هر زمانی برای خود محفوظ میداریم. همچنین توجه داشته باشید که فایلهای مشتق شدهی تولید شده توسط dex2oat مانند ODEX (همچنین با نام OAT شناخته میشود)، VDEX و CDEX همگی فرمتهای نامشخص هستند.
اگر یک SDK شخص ثالث مهم (مثلاً یک مبهمساز) نتواند از استفاده از رابطهای غیر SDK اجتناب کند، اما متعهد به حفظ سازگاری با نسخههای آینده اندروید شود، چه میشود؟ آیا اندروید میتواند در این مورد از الزامات سازگاری خود صرف نظر کند؟
ما برنامهای برای چشمپوشی از الزامات سازگاری بر اساس هر SDK نداریم. اگر یک توسعهدهنده SDK فقط میتواند با تکیه بر رابطهای موجود در لیستهای پشتیبانی نشده (که قبلاً خاکستری بودند) سازگاری را حفظ کند، باید برنامهریزی برای مهاجرت به رابطهای SDK یا سایر جایگزینها را آغاز کند و هر زمان که نتواند جایگزینی برای استفاده از رابط غیر SDK پیدا کند، درخواست یک API عمومی جدید بدهد .
آیا محدودیتهای رابط کاربری غیر SDK برای همه برنامهها، از جمله برنامههای سیستمی و برنامههای شخص ثالث، اعمال میشود، نه فقط برنامههای شخص ثالث؟
بله، با این حال، ما برنامههای امضا شده با کلید پلتفرم و برخی از برنامههای تصویر سیستم را از این قاعده مستثنی میکنیم. توجه داشته باشید که این معافیتها فقط برای برنامههایی اعمال میشود که بخشی از تصویر سیستم (یا برنامههای تصویر سیستم بهروزرسانی شده) هستند. این لیست فقط برای برنامههایی در نظر گرفته شده است که بر اساس APIهای پلتفرم خصوصی ساخته میشوند، نه APIهای SDK (که در آن LOCAL_PRIVATE_PLATFORM_APIS := true ).