تغییرات رفتار اندروید 8.0

اندروید 8.0 (سطح 26 API) همراه با ویژگی ها و قابلیت های جدید، شامل انواع تغییرات رفتاری سیستم و API است. این سند برخی از تغییرات کلیدی را که باید درک کنید و در برنامه‌های خود در نظر بگیرید، برجسته می‌کند.

بیشتر این تغییرات بر همه برنامه‌ها تأثیر می‌گذارد، صرف نظر از اینکه چه نسخه‌ای از اندروید را هدف قرار می‌دهند. با این حال، چندین تغییر تنها بر برنامه هایی که اندروید 8.0 را هدف قرار می دهند، تأثیر می گذارد. برای به حداکثر رساندن وضوح، این صفحه به دو بخش تقسیم می‌شود: تغییرات برای همه برنامه‌ها و تغییرات برای برنامه‌هایی که Android 8.0 را هدف قرار می‌دهند .

تغییرات برای همه برنامه ها

این تغییرات رفتاری اعمال می شود همه برنامه ها وقتی آنها بر روی پلتفرم Android 8.0 (سطح API 26) اجرا می شوند، صرف نظر از سطح API مورد نظرشان. همه توسعه‌دهندگان باید این تغییرات را بررسی کرده و برنامه‌های خود را تغییر دهند تا در صورت لزوم، به درستی از آنها پشتیبانی کنند.

محدودیت های اجرای پس زمینه

به عنوان یکی از تغییراتی که 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 ادامه دهند.

  • پرس و جو از ویژگی سیستم 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) مدیریت رویدادهای دکمه رسانه متفاوت است:
    1. مدیریت دکمه‌های رسانه در یک فعالیت رابط کاربری تغییر نکرده است: فعالیت‌های پیش‌زمینه همچنان در مدیریت رویدادهای دکمه رسانه اولویت دارند.
    2. اگر فعالیت پیش زمینه رویداد دکمه رسانه را کنترل نکند، سیستم رویداد را به برنامه ای هدایت می کند که اخیراً صدا را به صورت محلی پخش کرده است. هنگام تعیین اینکه کدام برنامه رویدادهای دکمه رسانه را دریافت می کند، وضعیت فعال، پرچم ها و وضعیت پخش یک جلسه رسانه در نظر گرفته نمی شود.
    3. اگر جلسه رسانه برنامه منتشر شده باشد، سیستم رویداد دکمه رسانه را به MediaButtonReceiver برنامه می فرستد، در صورتی که یکی داشته باشد.
    4. برای هر مورد دیگری، سیستم رویداد دکمه رسانه را کنار می‌گذارد.

کتابخانه های بومی

در برنامه‌هایی که 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 خود می‌خواهید، باید از overriding sort() اجتناب کنید.

    اگر یک کلاس والد 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) ، شکستن این فرضیات می تواند منجر به تعریف چندین بار کلاس ، فساد پشته به دلیل سردرگمی کلاس و سایر اثرات نامطلوب شود.