اندروید 8.0 (سطح 26 API) همراه با ویژگی ها و قابلیت های جدید، شامل انواع تغییرات رفتاری سیستم و API است. این سند برخی از تغییرات کلیدی را که باید درک کنید و در برنامههای خود در نظر بگیرید، برجسته میکند.
بیشتر این تغییرات بر همه برنامهها تأثیر میگذارد، صرف نظر از اینکه چه نسخهای از اندروید را هدف قرار میدهند. با این حال، چندین تغییر تنها بر برنامه هایی که اندروید 8.0 را هدف قرار می دهند، تأثیر می گذارد. برای به حداکثر رساندن وضوح، این صفحه به دو بخش تقسیم میشود: تغییرات برای همه برنامهها و تغییرات برای برنامههایی که Android 8.0 را هدف قرار میدهند .
تغییرات برای همه برنامه ها
این تغییرات رفتاری اعمال می شود
محدودیت های اجرای پس زمینه
به عنوان یکی از تغییراتی که Android 8.0 (سطح API 26) برای بهبود عمر باتری معرفی میکند، هنگامی که برنامه شما وارد حالت کش میشود و هیچ مؤلفه فعالی ندارد، سیستم تمام wakelockهایی را که برنامه نگه میدارد آزاد میکند.
علاوه بر این، برای بهبود عملکرد دستگاه، سیستم رفتارهای خاصی را توسط برنامه هایی که در پیش زمینه اجرا نمی شوند محدود می کند. به طور مشخص:
- اکنون برنامههایی که در پسزمینه اجرا میشوند محدودیتهایی برای دسترسی آزادانه به خدمات پسزمینه دارند.
- برنامهها نمیتوانند از مانیفستهای خود برای ثبت نام برای اکثر پخشهای ضمنی (یعنی پخشهایی که به طور خاص در برنامه هدف قرار نمیگیرند) استفاده کنند.
به طور پیشفرض، این محدودیتها فقط برای برنامههایی اعمال میشود که O را هدف قرار میدهند. با این حال، کاربران میتوانند این محدودیتها را برای هر برنامهای از صفحه تنظیمات فعال کنند، حتی اگر برنامه O را هدف قرار نداده باشد.
Android 8.0 (سطح API 26) همچنین شامل تغییرات زیر در روشهای خاص است:
- اگر برنامهای که اندروید 8.0 را هدف قرار میدهد، در شرایطی که اجازه ایجاد سرویسهای پسزمینه را ندارد، سعی کند از آن روش استفاده کند، متد
startService()
اکنون یکIllegalStateException
ایجاد میکند. - متد جدید
Context.startForegroundService()
یک سرویس پیش زمینه را راه اندازی می کند. این سیستم به برنامهها اجازه میدهد حتی زمانی که برنامه در پسزمینه است،Context.startForegroundService()
را فراخوانی کنند. با این حال، برنامه باید متدstartForeground()
آن سرویس را در عرض پنج ثانیه پس از ایجاد سرویس فراخوانی کند.
برای اطلاعات بیشتر، محدودیتهای اجرای پسزمینه را ببینید.
محدودیت های موقعیت مکانی پس زمینه اندروید
به منظور حفظ باتری، تجربه کاربر و سلامت سیستم، برنامههای پسزمینه بهروزرسانیهای مکان را کمتر در صورت استفاده در دستگاهی که Android 8.0 دارد، دریافت میکند. این تغییر رفتار بر همه برنامههایی که بهروزرسانیهای مکان را دریافت میکنند، از جمله سرویسهای Google Play، تأثیر میگذارد.
این تغییرات API های زیر را تحت تاثیر قرار می دهد:
- ارائه دهنده مکان فیوز شده (FLP)
- ژئوفنسینگ
- اندازه گیری های GNSS
- مدیر موقعیت مکانی
- مدیر وای فای
برای اطمینان از اینکه برنامه شما مطابق انتظار اجرا می شود، مراحل زیر را انجام دهید:
- منطق برنامه خود را مرور کنید و مطمئن شوید که از آخرین APIهای مکان استفاده می کنید.
- آزمایش کنید که برنامه شما رفتاری را که برای هر مورد استفاده انتظار دارید نشان دهد.
- استفاده از Fused Location Provider (FLP) یا geofencing را برای رسیدگی به موارد استفاده که به مکان فعلی کاربر بستگی دارد، در نظر بگیرید.
برای اطلاعات بیشتر درباره این تغییرات، به محدودیتهای موقعیت مکانی پسزمینه مراجعه کنید.
میانبرهای برنامه
Android 8.0 (سطح API 26) شامل تغییرات زیر در میانبرهای برنامه است:
- پخش
com.android.launcher.action.INSTALL_SHORTCUT
دیگر هیچ تأثیری بر برنامه شما ندارد، زیرا اکنون یک پخش خصوصی و ضمنی است. در عوض، باید با استفاده از متدrequestPinShortcut()
از کلاسShortcutManager
یک میانبر برنامه ایجاد کنید. - هدف
ACTION_CREATE_SHORTCUT
اکنون میتواند میانبرهای برنامهای ایجاد کند که با استفاده از کلاسShortcutManager
مدیریت میکنید. این هدف همچنین میتواند میانبرهای راهانداز قدیمی ایجاد کند که باShortcutManager
تعاملی ندارند. قبلاً، این هدف فقط میتوانست میانبرهای راهانداز قدیمی ایجاد کند. - میانبرهای ایجاد شده با استفاده از
requestPinShortcut()
و میانبرهای ایجاد شده در فعالیتی که هدفACTION_CREATE_SHORTCUT
را مدیریت می کند اکنون میانبرهای برنامه کاملاً پیشرفته هستند. در نتیجه، اکنون برنامهها میتوانند با استفاده از روشهای موجود درShortcutManager
، آنها را بهروزرسانی کنند. - میانبرهای قدیمی عملکرد خود را نسبت به نسخه های قبلی اندروید حفظ می کنند، اما باید آنها را به صورت دستی در برنامه خود به میانبرهای برنامه تبدیل کنید.
برای کسب اطلاعات بیشتر در مورد تغییرات میانبرهای برنامه، به راهنمای ویژگی های میانبر و ابزارک پین کردن مراجعه کنید.
بومی سازی و بین المللی سازی
Android 7.0 (سطح API 24) مفهوم قادر به تعیین یک دسته محلی پیشفرض را معرفی کرد، اما برخی از APIها همچنان از روش عمومی Locale.getDefault()
بدون آرگومان استفاده میکردند، در حالی که در عوض باید از Locale دستهبندی پیشفرض DISPLAY
استفاده میکردند. در Android 8.0 (سطح API 26)، روشهای زیر اکنون از Locale.getDefault(Category.DISPLAY)
به جای Locale.getDefault()
استفاده میکنند:
زمانی که مقدار displayScript مشخص شده برای آرگومان Locale
در دسترس نباشد Locale.getDisplayScript(Locale)
به Locale.getDefault()
بازمی گردد.
تغییرات محلی اضافی و بین المللی سازی به شرح زیر است:
- فراخوانی
Currency.getDisplayName(null)
یکNullPointerException
را ایجاد می کند که با رفتار مستند مطابقت دارد. - تجزیه نام منطقه زمانی تغییر کرده است. پیش از این، دستگاههای Android از مقدار ساعت سیستم نمونهبرداری شده در زمان راهاندازی برای ذخیره نام منطقه زمانی مورد استفاده برای تجزیه زمانهای تاریخ استفاده میکردند. در نتیجه، اگر ساعت سیستم در زمان راهاندازی اشتباه باشد یا در موارد نادر دیگر، تجزیه میتواند تأثیر منفی بگذارد.
اکنون، در موارد معمول، منطق تجزیه هنگام تجزیه نام منطقه زمانی از ICU و مقدار ساعت فعلی سیستم استفاده می کند. این تغییر نتایج صحیح تری ارائه می دهد، که ممکن است زمانی که برنامه شما از کلاس هایی مانند
SimpleDateFormat
استفاده می کند، با نسخه های قبلی Android متفاوت باشد. - اندروید 8.0 (سطح API 26) نسخه ICU را به نسخه 58 به روز می کند.
پنجره های هشدار
اگر برنامهای از مجوز SYSTEM_ALERT_WINDOW
استفاده میکند و از یکی از انواع پنجرههای زیر برای نمایش پنجرههای هشدار بالای دیگر برنامهها و پنجرههای سیستم استفاده میکند:
... سپس این پنجره ها همیشه در زیر پنجره هایی ظاهر می شوند که از نوع پنجره TYPE_APPLICATION_OVERLAY
استفاده می کنند. اگر برنامهای Android 8.0 (سطح API 26) را هدف قرار دهد، برنامه از نوع پنجره TYPE_APPLICATION_OVERLAY
برای نمایش پنجرههای هشدار استفاده میکند.
برای اطلاعات بیشتر، به بخش انواع پنجرههای متداول برای پنجرههای هشدار در تغییرات رفتار برنامههایی که Android 8.0 را هدف قرار میدهند، مراجعه کنید.
ورودی و ناوبری
با ظهور برنامههای Android در ChromeOS و سایر عوامل بزرگ مانند تبلتها، شاهد تجدید حیات استفاده از پیمایش صفحه کلید در برنامههای Android هستیم. در Android 8.0 (سطح API 26)، با استفاده از صفحهکلید بهعنوان یک دستگاه ورودی ناوبری دوباره آدرسدهی کردهایم، که منجر به مدل قابلاعتمادتر و قابل پیشبینیتر برای پیمایش مبتنی بر فلش و برگه میشود.
به طور خاص، ما تغییرات زیر را در رفتار تمرکز عنصر ایجاد کردهایم:
اگر هیچ رنگ حالت فوکوس را برای یک شی
View
تعریف نکردهاید (چه پیشزمینه یا پسزمینه قابل ترسیم شدن آن)، اکنون چارچوب یک رنگ برجسته تمرکز پیشفرض را برایView
تعیین میکند. این برجستهسازی فوکوس یک طرح ریپلی است که بر اساس موضوع فعالیت است.اگر نمیخواهید یک شی
View
از این برجستهسازی پیشفرض هنگام دریافت فوکوس استفاده کند، ویژگیandroid:defaultFocusHighlightEnabled
را در فایل XML طرحبندی حاویView
رویfalse
قرار دهید، یا در منطق رابط کاربری برنامه خود،false
بهsetDefaultFocusHighlightEnabled()
ارسال کنید.- برای آزمایش اینکه چگونه ورودی صفحهکلید بر تمرکز عنصر UI تأثیر میگذارد، میتوانید گزینه Drawing > Show layout bounds developer را فعال کنید. در اندروید 8.0، این گزینه یک نماد "X" را روی عنصری که در حال حاضر فوکوس دارد نمایش می دهد.
همچنین، همه عناصر نوار ابزار در Android 8.0 به صورت خودکار خوشههای ناوبری صفحهکلید هستند، که حرکت به داخل و خارج از هر نوار ابزار را برای کاربران آسانتر میکند.
برای کسب اطلاعات بیشتر درباره نحوه بهبود پشتیبانی از پیمایش صفحه کلید در برنامه خود، راهنمای ناوبری صفحه کلید پشتیبانی را بخوانید.
تکمیل خودکار فرم وب
اکنون که Android Autofill Framework پشتیبانی داخلی برای عملکرد تکمیل خودکار ارائه میکند، روشهای زیر مربوط به اشیاء WebView
برای برنامههای نصبشده در دستگاههای دارای Android 8.0 (سطح API 26) تغییر کرده است:
-
WebSettings
- متد
getSaveFormData()
اکنونfalse
را برمی گرداند. قبلاً این روش به جای آنtrue
برمی گرداند. - فراخوانی
setSaveFormData()
دیگر تاثیری ندارد.
- متد
-
WebViewDatabase
- فراخوانی
clearFormData()
دیگر تاثیری ندارد. - متد
hasFormData()
اکنونfalse
را برمی گرداند. پیش از این، زمانی که فرم حاوی داده بود، این روشtrue
برمیگرداند.
- فراخوانی
دسترسی
Android 8.0 (سطح API 26) شامل تغییرات زیر در دسترسی است:
چارچوب دسترسپذیری اکنون همه حرکات دوبار ضربه را به کنشهای
ACTION_CLICK
تبدیل میکند. این تغییر به TalkBack اجازه میدهد تا مانند سایر سرویسهای دسترسپذیری رفتار کند.اگر اشیاء
View
برنامه شما از کنترل لمسی سفارشی استفاده میکنند، باید بررسی کنید که هنوز با TalkBack کار میکنند. فقط ممکن است لازم باشد کنترل کننده کلیکی را که اشیاءView
شما استفاده می کنند، ثبت کنید. اگر TalkBack همچنان ژستهای انجامشده روی این اشیاءView
را تشخیص نمیدهد،performAccessibilityAction()
را لغو کنید.- سرویسهای دسترسپذیری اکنون از تمام موارد
ClickableSpan
در اشیاءTextView
برنامه شما آگاه هستند.
برای کسب اطلاعات بیشتر در مورد نحوه دسترسی بیشتر به برنامه، به قابلیت دسترسی مراجعه کنید.
شبکه و اتصال HTTP(S).
Android 8.0 (سطح API 26) شامل تغییرات رفتاری زیر در شبکه و اتصال HTTP(S) است:
- درخواست های OPTIONS بدون متن دارای سرصفحه
Content-Length: 0
هستند. قبلاً آنها هیچ عنوانContent-Length
نداشتند. - HttpURLConnection URL های حاوی مسیرهای خالی را با اضافه کردن یک اسلش بعد از نام میزبان یا مرجع با یک اسلش عادی می کند. به عنوان مثال،
http://example.com
بهhttp://example.com/
تبدیل می کند. - یک انتخابگر پراکسی سفارشی که از طریق ProxySelector.setDefault() تنظیم شده است فقط آدرس (طرح، میزبان و پورت) URL درخواستی را هدف قرار می دهد. در نتیجه، انتخاب پراکسی ممکن است فقط بر اساس آن مقادیر باشد. URL ارسال شده به یک انتخابگر پروکسی سفارشی شامل مسیر URL درخواستی، پارامترهای پرس و جو یا قطعات نمی شود.
- URI ها نمی توانند حاوی برچسب های خالی باشند.
پیش از این، این پلتفرم راهحلی برای پذیرش برچسبهای خالی در نام میزبان پشتیبانی میکرد که استفاده غیرقانونی از URI است. این راه حل برای سازگاری با نسخه های قدیمی libcore بود. برنامهنویسهایی که به اشتباه از API استفاده میکنند، پیام ADB را میبینند: "URI example..com دارای برچسبهای خالی در نام میزبان است. این نام نادرست است و در نسخههای Android آینده پذیرفته نخواهد شد." Android 8.0 این راه حل را حذف می کند. سیستم برای URI های ناقص null برمی گرداند.
- اجرای Android 8.0 از HttpsURLConnection نسخه بازگشتی پروتکل TLS/SSL ناامن را انجام نمی دهد.
- مدیریت اتصالات HTTP(S) تونل به شرح زیر تغییر کرده است:
- هنگام تونل کردن اتصال HTTPS از طریق اتصال، سیستم هنگام ارسال این اطلاعات به سرور میانی، شماره پورت (:443) را به درستی در خط میزبان قرار می دهد. قبلاً شماره پورت فقط در خط CONNECT وجود داشت.
- سیستم دیگر هدرهای عامل کاربر و مجوز پروکسی را از یک درخواست تونل شده به سرور پراکسی ارسال نمی کند.
هنگام راهاندازی تونل، سیستم دیگر هدر مجوز پروکسی را روی اتصال Http(s)URLC تونلشده به پروکسی ارسال نمیکند. در عوض، سیستم یک هدر مجوز پروکسی تولید میکند و زمانی که پروکسی HTTP 407 را در پاسخ به درخواست اولیه ارسال میکند، آن را به پروکسی ارسال میکند.
به طور مشابه، سیستم دیگر هدر عامل کاربر را از درخواست تونل شده به درخواست پراکسی که تونل را راه اندازی می کند کپی نمی کند. در عوض، کتابخانه یک سربرگ عامل کاربر برای آن درخواست ایجاد می کند.
- متد
send(java.net.DatagramPacket)
در صورتی که متد connect() قبلا اجرا شده با شکست مواجه شود، یک SocketException پرتاب می کند.- () DatagramSocket.connect یک pendingSocketException را در صورت وجود یک خطای داخلی تنظیم می کند. قبل از Android 8.0، یک فراخوان recv() بعدی یک SocketException پرتاب کرد، حتی اگر یک تماس send() با موفقیت انجام شود. برای ثبات، هر دو تماس اکنون یک SocketException را پرتاب می کنند.
- InetAddress.isReachable() قبل از بازگشت به پروتکل TCP Echo، ICMP را امتحان می کند.
- برخی از میزبانهایی که پورت 7 (TCP Echo) را مسدود میکنند، مانند google.com، اگر پروتکل ICMP Echo را بپذیرند، اکنون ممکن است قابل دسترسی باشند.
- برای میزبان های واقعاً غیرقابل دسترسی، این تغییر به این معنی است که دو برابر زمان قبل از بازگشت تماس صرف می شود.
بلوتوث
Android 8.0 (سطح API 26) تغییرات زیر را در طول دادههایی که روش ScanRecord.getBytes()
بازیابی میکند ایجاد میکند:
- متد
getBytes()
هیچ فرضی در مورد تعداد بایت های دریافتی نمی کند. بنابراین، برنامهها نباید به حداقل یا حداکثر تعداد بایتهای برگشتی متکی باشند. در عوض، آنها باید طول آرایه حاصل را ارزیابی کنند. - دستگاه های سازگار با بلوتوث 5 ممکن است طول داده بیش از حداکثر 60 بایت قبلی را برگردانند.
- اگر یک دستگاه راه دور پاسخ اسکن را ارائه نکند، ممکن است کمتر از 60 بایت نیز برگردانده شود.
اتصال بدون درز
Android 8.0 (سطح API 26) تعدادی بهبود در تنظیمات Wi-Fi ایجاد می کند تا انتخاب شبکه Wi-Fi را که بهترین تجربه کاربری را ارائه می دهد آسانتر کند. تغییرات خاص عبارتند از:
- بهبود پایداری و قابلیت اطمینان
- یک رابط کاربری شهودی تر خوانا.
- یک منوی تنظیمات برگزیده Wi-Fi یکپارچه.
- در دستگاههای سازگار، فعالسازی خودکار Wi-Fi زمانی که یک شبکه ذخیرهشده با کیفیت بالا در این نزدیکی است.
امنیت
Android 8.0 شامل تغییرات مرتبط با امنیت زیر است:
- این پلتفرم دیگر از SSLv3 پشتیبانی نمی کند.
- هنگام برقراری یک اتصال HTTPS به سروری که به اشتباه مذاکرات پروتکل TLS-نسخه را اجرا می کند،
HttpsURLConnection
دیگر راه حل بازگشت به نسخه های قبلی پروتکل TLS و تلاش مجدد را انجام نمی دهد. - Android 8.0 (سطح API 26) یک فیلتر محاسبات ایمن (SECCOMP) را برای همه برنامه ها اعمال می کند. فهرست سیستمهای مجاز به آنهایی که از طریق بیونیک در معرض قرار میگیرند محدود میشود. اگرچه چندین syscals دیگر برای سازگاری به عقب ارائه شده است، توصیه می کنیم از آنها استفاده نکنید.
- اشیاء
WebView
برنامه شما اکنون در حالت چند پردازشی اجرا می شوند. برای افزایش امنیت، محتوای وب در فرآیندی مجزا و مجزا از فرآیند برنامه حاوی پردازش میشود. - دیگر نمیتوانید فرض کنید که فایلهای APK در فهرستهایی قرار دارند که نامهای آنها به -1 یا -2 ختم میشود. برنامه ها باید از
sourceDir
برای دریافت دایرکتوری استفاده کنند و مستقیماً به قالب دایرکتوری تکیه نکنند. - برای اطلاعات در مورد پیشرفت های امنیتی مربوط به استفاده از کتابخانه های بومی، به کتابخانه های بومی مراجعه کنید.
علاوه بر این، Android 8.0 (سطح API 26) تغییرات زیر را در رابطه با نصب برنامه های ناشناخته از منابع ناشناس معرفی می کند:
- مقدار تنظیم قدیمی
INSTALL_NON_MARKET_APPS
اکنون همیشه 1 است. برای تعیین اینکه آیا یک منبع ناشناخته می تواند برنامه ها را با استفاده از نصب کننده بسته نصب کند، باید در عوض از مقدار بازگشتیcanRequestPackageInstalls()
استفاده کنید. - اگر سعی کنید مقدار
INSTALL_NON_MARKET_APPS
را با استفاده ازsetSecureSetting()
تغییر دهید، یکUnsupportedOperationException
پرتاب می شود. برای جلوگیری از نصب برنامه های ناشناخته توسط کاربران با استفاده از منابع ناشناخته، در عوض باید محدودیت کاربرDISALLOW_INSTALL_UNKNOWN_SOURCES
را اعمال کنید. - نمایه های مدیریت شده ایجاد شده در دستگاه های دارای Android 8.0 (سطح API 26) به طور خودکار دارای محدودیت کاربر
DISALLOW_INSTALL_UNKNOWN_SOURCES
فعال است. برای نمایههای مدیریتشده موجود در دستگاههایی که به Android 8.0 ارتقا یافتهاند، محدودیت کاربرDISALLOW_INSTALL_UNKNOWN_SOURCES
بهطور خودکار فعال میشود، مگر اینکه مالک نمایه صراحتاً این محدودیت را (قبل از ارتقا) با تنظیمINSTALL_NON_MARKET_APPS
روی 1 غیرفعال کرده باشد.
برای جزئیات بیشتر در مورد نصب برنامه های ناشناخته، راهنمای مجوزهای نصب برنامه ناشناخته را ببینید.
برای دستورالعملهای بیشتر درباره ایمنتر کردن برنامهتان، به امنیت برای برنامهنویسان Android مراجعه کنید.
حریم خصوصی
Android 8.0 (سطح API 26) تغییرات مرتبط با حریم خصوصی زیر را در پلتفرم ایجاد می کند.
- این پلتفرم اکنون شناسه ها را به گونه ای متفاوت مدیریت می کند.
- برای برنامههایی که قبل از OTA روی نسخهای از Android 8.0 (سطح API 26) (سطح API 26) نصب شدهاند، مقدار
ANDROID_ID
ثابت میماند مگر اینکه حذف نصب شده و پس از OTA دوباره نصب شود. برای حفظ مقادیر در سراسر حذف پس از OTA، توسعه دهندگان می توانند مقادیر قدیمی و جدید را با استفاده از Backup Key/Value مرتبط کنند. - برای برنامههای نصبشده در دستگاهی که Android نسخه ۸.۰ دارد، مقدار
ANDROID_ID
اکنون به ازای کلید امضای برنامه و همچنین به ازای هر کاربر تعیین میشود. مقدارANDROID_ID
برای هر ترکیبی از کلید امضای برنامه، کاربر و دستگاه منحصر به فرد است. در نتیجه، برنامههایی که کلیدهای امضای متفاوتی دارند که روی یک دستگاه اجرا میشوند، دیگر شناسه Android یکسانی را نمیبینند (حتی برای یک کاربر). - مقدار
ANDROID_ID
در حذف یا نصب مجدد بسته تغییر نمیکند، تا زمانی که کلید امضا یکسان باشد (و برنامه قبل از OTA روی نسخهای از Android 8.0 نصب نشده باشد). - مقدار
ANDROID_ID
تغییر نمی کند حتی اگر یک به روز رسانی سیستم باعث تغییر کلید امضای بسته شود. - در دستگاههایی که دارای خدمات Google Play و شناسه تبلیغاتی هستند، باید از شناسه تبلیغاتی استفاده کنید. یک سیستم ساده و استاندارد برای کسب درآمد از برنامهها، Advertising ID یک شناسه منحصر به فرد و قابل تنظیم مجدد توسط کاربر برای تبلیغات است. توسط خدمات گوگل پلی ارائه شده است.
سایر تولیدکنندگان دستگاه باید به ارائه
ANDROID_ID
ادامه دهند.
- برای برنامههایی که قبل از OTA روی نسخهای از Android 8.0 (سطح API 26) (سطح API 26) نصب شدهاند، مقدار
- پرس و جو از ویژگی سیستم
net.hostname
یک نتیجه تهی ایجاد می کند.
ثبت استثنائات کشف نشده
اگر برنامهای یک Thread.UncaughtExceptionHandler
نصب کند که به Thread.UncaughtExceptionHandler
پیشفرض فراخوانی نمیکند، سیستم برنامه را در صورت بروز یک استثنای غیرقابل شناسایی، نمیکشد. با شروع از Android 8.0 (سطح API 26)، سیستم در این شرایط، stacktrace استثنایی را ثبت میکند. در نسخه های قبلی پلتفرم، سیستم Stacktrace استثنا را ثبت نمی کرد.
توصیه می کنیم که پیاده سازی های سفارشی Thread.UncaughtExceptionHandler
همیشه به کنترل کننده پیش فرض فراخوانی شود. برنامه هایی که از این توصیه پیروی می کنند تحت تأثیر تغییر اندروید 8.0 قرار نخواهند گرفت.
تغییر امضای findViewById().
همه نمونههای متد findViewById()
اکنون <T extends View> T
به جای View
برمیگردانند. این تغییر دارای پیامدهای زیر است:
- این ممکن است منجر به این شود که کد موجود اکنون دارای نوع بازگشت مبهم باشد، برای مثال اگر هر دو
someMethod(View)
وsomeMethod(TextView)
وجود داشته باشد که نتیجه فراخوانی را بهfindViewById()
می برد. - هنگامی که از زبان مبدأ جاوا 8 استفاده میکنید، زمانی که نوع بازگشتی نامحدود باشد، به یک Cast واضح برای
View
نیاز دارد (به عنوان مثالassertNotNull(findViewById(...)).someViewMethod())
. - نادیده گرفتن متدهای غیر نهایی
findViewById()
(به عنوان مثال،Activity.findViewById()
) باید نوع برگشتی خود را به روز کند.
آمار استفاده از ارائه دهنده مخاطبین تغییر می کند
در نسخههای قبلی اندروید، بخش Contacts Provider به توسعهدهندگان اجازه میدهد تا دادههای استفاده را برای هر مخاطب دریافت کنند. این دادههای استفاده، اطلاعات مربوط به هر آدرس ایمیل و هر شماره تلفن مرتبط با یک مخاطب را نشان میدهد، از جمله تعداد دفعاتی که با مخاطب تماس گرفته شده و آخرین باری که با مخاطب تماس گرفته شده است. برنامههایی که مجوز READ_CONTACTS
را درخواست میکنند میتوانند این دادهها را بخوانند.
اگر برنامهها مجوز READ_CONTACTS
را درخواست کنند، همچنان میتوانند این دادهها را بخوانند. در Android 8.0 (سطح API 26) و بالاتر، جستارهای مربوط به دادههای استفاده به جای مقادیر دقیق، تقریبی را برمیگردانند. سیستم اندروید مقادیر دقیق را به صورت داخلی حفظ می کند، بنابراین این تغییر بر API تکمیل خودکار تأثیر نمی گذارد.
این تغییر رفتار بر پارامترهای پرس و جو زیر تأثیر می گذارد:
مدیریت مجموعه
AbstractCollection.removeAll()
و AbstractCollection.retainAll()
اکنون همیشه یک NullPointerException
پرتاب می کنند. قبلاً، NullPointerException
زمانی که مجموعه خالی بود پرتاب نمی شد. این تغییر رفتار را با مستندات سازگار می کند.
شرکت اندروید
Android 8.0 (سطح API 26) رفتار برخی APIها و ویژگیهای برنامههای سازمانی، از جمله کنترلکنندههای خطمشی دستگاه (DPC) را تغییر میدهد . تغییرات شامل:
- رفتارهای جدید برای کمک به برنامهها برای پشتیبانی از نمایههای کاری در دستگاههای کاملاً مدیریتشده.
- تغییراتی در مدیریت بهروزرسانی سیستم، تأیید برنامه، و احراز هویت برای افزایش یکپارچگی دستگاه و سیستم.
- بهبودهایی در تجربه کاربر برای تهیه، اعلانها، صفحه اخیر و VPN همیشه روشن.
برای مشاهده همه تغییرات سازمانی در Android 8.0 (سطح API 26) و نحوه تأثیرگذاری آنها بر برنامه شما، Android را در Enterprise بخوانید.
برنامه هایی که اندروید 8.0 را هدف قرار می دهند
این تغییرات رفتاری منحصراً برای برنامههایی اعمال میشود که Android 8.0 (سطح API 26) یا بالاتر را هدف قرار میدهند. برنامههایی که با Android 8.0 کامپایل میشوند، یا targetSdkVersion
روی Android 8.0 یا بالاتر تنظیم میکنند، باید برنامههای خود را تغییر دهند تا از این رفتارها به درستی پشتیبانی کنند، در صورتی که برای برنامه قابل اجرا باشد.
پنجره های هشدار
برنامههایی که از مجوز SYSTEM_ALERT_WINDOW
استفاده میکنند، دیگر نمیتوانند از انواع پنجرههای زیر برای نمایش پنجرههای هشدار در بالای سایر برنامهها و پنجرههای سیستم استفاده کنند:
در عوض، برنامهها باید از نوع پنجره جدیدی به نام TYPE_APPLICATION_OVERLAY
استفاده کنند.
هنگام استفاده از نوع پنجره TYPE_APPLICATION_OVERLAY
برای نمایش پنجره های هشدار برای برنامه خود، ویژگی های زیر نوع پنجره جدید را در نظر داشته باشید:
- پنجرههای هشدار برنامه همیشه در زیر پنجرههای مهم سیستم مانند نوار وضعیت و IME ظاهر میشوند.
- سیستم میتواند پنجرههایی را که از نوع پنجره
TYPE_APPLICATION_OVERLAY
برای بهبود نمایش صفحه استفاده میکنند، جابجا یا تغییر اندازه دهد. - با باز کردن اعلانها، کاربران میتوانند به تنظیماتی دسترسی پیدا کنند تا برنامه را از نمایش پنجرههای هشدار که با استفاده از نوع پنجره
TYPE_APPLICATION_OVERLAY
نشان داده شدهاند، مسدود کنند.
اعلان های تغییر محتوا
Android 8.0 (سطح API 26) نحوه رفتار ContentResolver.notifyChange()
و registerContentObserver(Uri, boolean, ContentObserver)
را برای برنامه هایی که Android 8.0 را هدف قرار می دهند، تغییر می دهد.
این APIها اکنون نیاز دارند که یک ContentProvider
معتبر برای مرجع در همه Uris تعریف شود. تعریف یک ContentProvider
معتبر با مجوزهای مربوطه به دفاع از برنامه شما در برابر تغییرات محتوای برنامههای مخرب کمک میکند و از نشت اطلاعات خصوصی بالقوه به برنامههای مخرب جلوگیری میکند.
مشاهده فوکوس
اشیاء قابل کلیک View
اکنون به طور پیش فرض نیز قابل فوکوس هستند. اگر میخواهید یک شی View
قابل کلیک باشد اما قابل فوکوس نباشد، ویژگی android:focusable
در فایل XML طرحبندی حاوی View
روی false
قرار دهید، یا در منطق رابط کاربری برنامهتان، false
را به setFocusable()
ارسال کنید.
تطبیق عامل کاربر در تشخیص مرورگر
Android 8.0 (سطح API 26) و بالاتر شامل رشته شناسه ساخت OPR
است. برخی از تطابق الگوها ممکن است باعث شود منطق تشخیص مرورگر یک مرورگر غیر Opera را به اشتباه به عنوان Opera شناسایی کند. نمونه ای از این تطابق الگو می تواند این باشد:
if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}
برای جلوگیری از مشکلات ناشی از چنین شناسایی نادرست، از رشته ای غیر از OPR
به عنوان الگوی تطبیق برای مرورگر Opera استفاده کنید.
امنیت
تغییرات زیر بر امنیت Android 8.0 (سطح API 26) تأثیر می گذارد:
- اگر پیکربندی امنیت شبکه برنامه شما از پشتیبانی از ترافیک متن واضح انصراف دهد ، اشیاء
WebView
برنامه شما نمی توانند از طریق HTTP به وب سایت ها دسترسی داشته باشند. هر شیWebView
باید به جای آن از HTTPS استفاده کند. - تنظیمات سیستم مجاز به منابع ناشناخته حذف شده است. در جای خود، مجوز نصب برنامه های ناشناخته، نصب برنامه های ناشناخته را از منابع ناشناس مدیریت می کند. برای کسب اطلاعات بیشتر در مورد این مجوز جدید، راهنمای مجوزهای نصب برنامه ناشناس را ببینید.
برای دستورالعملهای بیشتر درباره ایمنتر کردن برنامهتان، به امنیت برای برنامهنویسان Android مراجعه کنید.
دسترسی به حساب و قابلیت کشف
در Android 8.0 (سطح API 26)، برنامهها دیگر نمیتوانند به حسابهای کاربر دسترسی داشته باشند، مگر اینکه احراز هویت مالک حسابها باشد یا کاربر این دسترسی را اعطا کند. مجوز GET_ACCOUNTS
دیگر کافی نیست. برای اینکه برنامهها به یک حساب دسترسی داشته باشند، باید از AccountManager.newChooseAccountIntent()
یا از یک روش خاص authenticator استفاده کنند. پس از دسترسی به حسابها، یک برنامه میتواند برای دسترسی به آنها با AccountManager.getAccounts()
تماس بگیرد.
Android 8.0 LOGIN_ACCOUNTS_CHANGED_ACTION
را منسوخ میکند. در عوض، برنامهها باید از addOnAccountsUpdatedListener()
برای دریافت بهروزرسانیهای حسابها در طول زمان اجرا استفاده کنند.
برای اطلاعات در مورد API های جدید و روش های اضافه شده برای دسترسی به حساب و قابلیت کشف، دسترسی به حساب و قابلیت کشف را در بخش API های جدید این سند ببینید.
حریم خصوصی
تغییرات زیر بر حریم خصوصی در Android 8.0 (سطح API 26) تأثیر می گذارد.
- ویژگی های سیستم
net.dns1
،net.dns2
،net.dns3
وnet.dns4
دیگر در دسترس نیستند، تغییری که حریم خصوصی را در پلتفرم بهبود می بخشد. - برای به دست آوردن اطلاعات شبکه مانند سرورهای DNS، برنامههای دارای مجوز
ACCESS_NETWORK_STATE
میتوانند یکNetworkRequest
یاNetworkCallback
را ثبت کنند. این کلاس ها در اندروید 5.0 (سطح API 21) و بالاتر در دسترس هستند. - Build.SERIAL منسوخ شده است. برنامههایی که نیاز به دانستن شماره سریال سختافزاری دارند، باید از روش جدید
Build.getSerial()
استفاده کنند که به مجوزREAD_PHONE_STATE
نیاز دارد. -
LauncherApps
API دیگر به برنامه های نمایه کاری اجازه نمی دهد اطلاعات مربوط به نمایه اصلی را دریافت کنند. وقتی کاربر در نمایه کاری است،LauncherApps
API طوری رفتار میکند که انگار هیچ برنامهای در پروفایلهای دیگر در همان گروه نمایه نصب نشده است. مانند قبل، تلاش برای دسترسی به پروفایل های نامرتبط باعث SecurityExceptions می شود.
مجوزها
قبل از Android 8.0 (سطح API 26)، اگر برنامهای در زمان اجرا درخواست مجوز میکرد و مجوز اعطا میشد، سیستم به اشتباه بقیه مجوزهایی را که متعلق به همان گروه مجوز بود و در آن ثبت شده بود به برنامه اعطا میکرد. آشکار
برای برنامه هایی که اندروید 8.0 را هدف قرار می دهند، این رفتار اصلاح شده است. به برنامه فقط مجوزهایی داده می شود که صریحاً درخواست کرده است. با این حال، هنگامی که کاربر مجوزی را به برنامه اعطا می کند، تمام درخواست های بعدی برای مجوز در آن گروه مجوز به طور خودکار اعطا می شود.
برای مثال، فرض کنید یک برنامه هر دو READ_EXTERNAL_STORAGE
و WRITE_EXTERNAL_STORAGE
را در مانیفست خود فهرست می کند. برنامه READ_EXTERNAL_STORAGE
را درخواست می کند و کاربر آن را اعطا می کند. اگر برنامه سطح API 25 یا پایینتر را هدف قرار دهد، سیستم WRITE_EXTERNAL_STORAGE
همزمان اعطا میکند، زیرا به همان گروه مجوز STORAGE
تعلق دارد و در مانیفست نیز ثبت شده است. اگر برنامه Android 8.0 (سطح API 26) را هدف قرار دهد، سیستم در آن زمان فقط READ_EXTERNAL_STORAGE
را اعطا می کند. با این حال، اگر برنامه بعداً WRITE_EXTERNAL_STORAGE
درخواست کند، سیستم فوراً این امتیاز را بدون درخواست از کاربر اعطا می کند.
رسانه ها
- این فریم ورک میتواند بهخودی خود پخش خودکار صدا را انجام دهد. در این حالت، هنگامی که برنامه دیگری فوکوس را با
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
درخواست میکند، برنامهای که فوکوس دارد، حجم آن را کاهش میدهد اما معمولاً پاسخ تماسonAudioFocusChange()
دریافت نمیکند و فوکوس صوتی را از دست نخواهد داد. API های جدیدی برای نادیده گرفتن این رفتار برای برنامه هایی که به جای ducking نیاز به توقف دارند در دسترس هستند. - هنگامی که کاربر تماس تلفنی می گیرد، پخش جریانی رسانه فعال در طول مدت تماس قطع می شود.
- همه APIهای مرتبط با صدا باید از
AudioAttributes
به جای انواع جریان صوتی برای توصیف مورد استفاده پخش صدا استفاده کنند. به استفاده از انواع جریان صوتی فقط برای کنترلهای میزان صدا ادامه دهید. سایر کاربردهای انواع جریان همچنان کار می کنند (به عنوان مثال، آرگومانstreamType
برای سازندهAudioTrack
منسوخ شده)، اما سیستم این را به عنوان یک خطا ثبت می کند. - هنگام استفاده از
AudioTrack
، اگر برنامه یک بافر صوتی به اندازه کافی بزرگ درخواست کند، فریم ورک سعی می کند از خروجی بافر عمیق در صورت موجود بودن استفاده کند. - در Android 8.0 (سطح API 26) مدیریت رویدادهای دکمه رسانه متفاوت است:
- مدیریت دکمههای رسانه در یک فعالیت رابط کاربری تغییر نکرده است: فعالیتهای پیشزمینه همچنان در مدیریت رویدادهای دکمه رسانه اولویت دارند.
- اگر فعالیت پیش زمینه رویداد دکمه رسانه را کنترل نکند، سیستم رویداد را به برنامه ای هدایت می کند که اخیراً صدا را به صورت محلی پخش کرده است. هنگام تعیین اینکه کدام برنامه رویدادهای دکمه رسانه را دریافت می کند، وضعیت فعال، پرچم ها و وضعیت پخش یک جلسه رسانه در نظر گرفته نمی شود.
- اگر جلسه رسانه برنامه منتشر شده باشد، سیستم رویداد دکمه رسانه را به
MediaButtonReceiver
برنامه می فرستد، در صورتی که یکی داشته باشد. - برای هر مورد دیگری، سیستم رویداد دکمه رسانه را کنار میگذارد.
کتابخانه های بومی
در برنامههایی که Android 8.0 (سطح API 26) را هدف قرار میدهند، کتابخانههای بومی اگر حاوی هر بخش باری باشند که هم قابل نوشتن و هم قابل اجرا باشد، دیگر بارگیری نمیشوند. اگر برخی از برنامهها کتابخانههای بومی با بخشهای بارگذاری نادرست داشته باشند، ممکن است به دلیل این تغییر کار نکنند. این یک اقدام تقویت کننده امنیتی است.
برای اطلاعات بیشتر، بخشهای قابل نوشتن و اجرایی را ببینید.
تغییرات پیوند دهنده به سطح API که یک برنامه هدف قرار می دهد گره خورده است. اگر تغییر پیوند دهنده در سطح API مورد نظر وجود داشته باشد، برنامه نمی تواند کتابخانه را بارگیری کند. اگر سطح API پایینتر از سطح API را هدف قرار میدهید که در آن تغییر پیوند دهنده رخ میدهد، logcat یک هشدار نشان میدهد.
مدیریت مجموعه
در Android 8.0 (سطح API 26)، Collections.sort()
در بالای List.sort()
پیاده سازی شده است. عکس آن در Android 7.x (سطوح API 24 و 25) صادق بود: اجرای پیش فرض List.sort()
به نام Collections.sort()
.
این تغییر به Collections.sort()
اجازه می دهد تا از پیاده سازی های بهینه سازی شده List.sort()
استفاده کند، اما دارای محدودیت های زیر است:
پیاده سازی های
List.sort()
نبایدCollections.sort()
فراخوانی کنند، زیرا انجام این کار باعث سرریز پشته به دلیل بازگشت بی نهایت می شود. در عوض، اگر رفتار پیشفرض را در پیادهسازیList
خود میخواهید، باید از overridingsort()
اجتناب کنید.اگر یک کلاس والد
sort()
را به طور نامناسب پیاده سازی کند، معمولاً خوب است کهList.sort()
با یک پیاده سازی ساخته شده در بالایList.toArray()
,Arrays.sort()
وListIterator.set()
لغو کنید. به عنوان مثال:@Override public void sort(Comparator<? super E> c) { Object[] elements = toArray(); Arrays.sort(elements, c); ListIterator<E> iterator = (ListIterator<Object>) listIterator(); for (Object element : elements) { iterator.next(); iterator.set((E) element); } }
در بیشتر موارد، میتوانید
List.sort()
با پیادهسازیای که بسته به سطح API به پیادهسازیهای پیشفرض مختلف واگذار میکند، لغو کنید. به عنوان مثال:@Override public void sort(Comparator<? super E> comparator) { if (Build.VERSION.SDK_INT <= 25) { Collections.sort(this); } else { super.sort(comparator); } }
اگر دومی را فقط به این دلیل انجام میدهید که میخواهید یک متد
sort()
در تمام سطوح API در دسترس داشته باشید، به جای استفاده ازsort()
sortCompat()
بدهید.Collections.sort()
اکنون به عنوان یک اصلاح ساختاری در پیادهسازیهای List کهsort()
را فراخوانی میکنند به حساب میآید. به عنوان مثال، در نسخههای پلتفرم قبل از Android 8.0 (سطح API 26)، اگر مرتبسازی با فراخوانیList.sort()
انجام میشد، با تکرار روی یکArrayList
و فراخوانیsort()
روی آن بخشی از تکرار، یکConcurrentModificationException
ایجاد میکرد. .Collections.sort()
استثنایی ایجاد نکرد.این تغییر رفتار پلتفرم را سازگارتر میکند: هر یک از این رویکردها اکنون منجر به یک
ConcurrentModificationException
میشود.
رفتار بارگذاری کلاس
Android 8.0 (سطح API 26) بررسی میکند تا مطمئن شود که بارکنندههای کلاس هنگام بارگیری کلاسهای جدید، مفروضات زمان اجرا را زیر پا نمیگذارند. این بررسی ها انجام می شود که آیا کلاس از جاوا (از forName()
)، بایت کد Dalvik یا JNI ارجاع شده باشد. این پلتفرم تماسهای مستقیم از جاوا به متد loadClass()
را رهگیری نمیکند و نتایج چنین تماسهایی را نیز بررسی نمیکند. این رفتار نباید بر عملکرد بارگذارهای کلاس با رفتار خوب تأثیر بگذارد.
پلتفرم بررسی می کند که توصیفگر کلاسی که بارگذار کلاس برمی گرداند با توصیفگر مورد انتظار مطابقت داشته باشد. اگر توصیفگر برگشتی با هم مطابقت نداشته باشد، پلتفرم یک خطای NoClassDefFoundError
ایجاد میکند و در استثنای یک پیام دقیق که مغایرت را ذکر میکند، ذخیره میکند.
پلتفرم همچنین بررسی می کند که توصیفگرهای کلاس های درخواستی معتبر هستند. این بررسی فراخوانی های JNI را می گیرد که به طور غیرمستقیم کلاس هایی مانند GetFieldID()
را بارگیری می کنند و توصیفگرهای نامعتبر را به آن کلاس ها ارسال می کنند. به عنوان مثال، فیلدی با امضای java/lang/String
یافت نشد زیرا آن امضا نامعتبر است. باید Ljava/lang/String;
.
این با فراخوانی JNI به FindClass()
که در آن java/lang/String
یک نام کاملاً واجد شرایط معتبر است متفاوت است.
Android 8.0 (سطح API 26) از داشتن چندین بارکننده کلاس برای تعریف کلاس ها با استفاده از یک شی DexFile پشتیبانی نمی کند. تلاش برای انجام این کار باعث میشود که زمان اجرا اندروید یک خطای InternalError
با پیغام "تلاش برای ثبت فایل dex <filename>
با بارگذارهای کلاس متعدد" ایجاد کند.
DexFile API اکنون منسوخ شده است، و شما قویاً تشویق میشوید به جای آن از یکی از کلاسلودرهای پلتفرم، از جمله PathClassLoader
یا BaseDexClassLoader
استفاده کنید.
توجه: میتوانید چندین بارکننده کلاس ایجاد کنید که به همان محفظه فایل APK یا JAR از سیستم فایل اشاره میکنند. انجام این کار به طور معمول منجر به سربار حافظه زیادی نمی شود: اگر پرونده های DEX در ظرف به جای فشرده سازی ذخیره شوند ، این سیستم عامل می تواند به جای استخراج مستقیم آنها ، یک عمل mmap
را بر روی آنها انجام دهد. اما اگر این پلتفرم باید پرونده DEX را از ظرف استخراج کند ، مراجعه به یک فایل DEX به این روش ممکن است حافظه زیادی مصرف کند.
در اندروید ، تمام لودرهای کلاس با توانایی موازی در نظر گرفته می شوند. هنگامی که چندین موضوع برای بارگیری همان کلاس با همان لودر کلاس ، اولین نخ برای تکمیل عملیات برنده می شوند و نتیجه برای سایر موضوعات استفاده می شود. این رفتار بدون در نظر گرفتن اینکه لودر کلاس همان کلاس را برگردانده است ، کلاس دیگری را برگردانده است ، یا یک استثنا را پرتاب می کند. این سکوی بی صدا چنین استثنائاتی را نادیده می گیرد.
احتیاط: در نسخه های پلت فرم پایین تر از Android 8.0 (API سطح 26) ، شکستن این فرضیات می تواند منجر به تعریف چندین بار کلاس ، فساد پشته به دلیل سردرگمی کلاس و سایر اثرات نامطلوب شود.