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

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

اگر قبلاً برنامه ای برای اندروید منتشر کرده اید، توجه داشته باشید که ممکن است برنامه شما تحت تأثیر این تغییرات در پلتفرم قرار گیرد.

باتری و حافظه

اندروید 7.0 شامل تغییرات رفتاری سیستم با هدف بهبود عمر باتری دستگاه ها و کاهش مصرف رم است. این تغییرات می‌تواند بر دسترسی برنامه شما به منابع سیستم و همچنین نحوه تعامل برنامه شما با سایر برنامه‌ها از طریق اهداف ضمنی خاص تأثیر بگذارد.

دوز

Doze که در Android 6.0 (سطح API 23) معرفی شد، با به تعویق انداختن CPU و فعالیت های شبکه، زمانی که کاربر دستگاهی را قطع، ثابت و با صفحه خاموش می گذارد، عمر باتری را بهبود می بخشد. Android 7.0 با اعمال زیرمجموعه‌ای از CPU و محدودیت‌های شبکه در حالی که دستگاه با صفحه خاموش وصل است، اما لزوماً ثابت نیست، برای مثال، هنگامی که یک گوشی در جیب کاربر حرکت می‌کند، پیشرفت‌های بیشتری را برای Doze به ارمغان می‌آورد.

تصویری از اینکه Doze چگونه اولین سطح از محدودیت‌های فعالیت سیستم را برای بهبود عمر باتری اعمال می‌کند

شکل 1. تصویری از نحوه اعمال اولین سطح از محدودیت های فعالیت سیستم برای بهبود عمر باتری Doze.

وقتی دستگاهی از باتری استفاده می‌کند و صفحه نمایش برای مدت معینی خاموش است، دستگاه وارد Doze می‌شود و اولین زیرمجموعه محدودیت‌ها را اعمال می‌کند: دسترسی به شبکه برنامه را قطع می‌کند، و کارها و همگام‌سازی‌ها را به تعویق می‌اندازد. اگر دستگاه پس از وارد شدن به Doze برای مدت معینی ثابت باشد، سیستم بقیه محدودیت‌های Doze را روی PowerManager.WakeLock اعمال می‌کند. هشدارهای WakeLock، AlarmManager ، GPS و اسکن‌های Wi-Fi. صرف نظر از اینکه برخی یا همه محدودیت‌های Doze اعمال می‌شوند، سیستم دستگاه را برای پنجره‌های تعمیر و نگهداری کوتاه بیدار می‌کند، که در طی آن برنامه‌ها اجازه دسترسی به شبکه را دارند و می‌توانند هر کار/همگام‌سازی معوقی را اجرا کنند.

تصویری از نحوه اعمال سطح دوم از محدودیت‌های فعالیت سیستم توسط Doze پس از ثابت ماندن دستگاه برای مدت معینی

شکل 2. تصویری از نحوه اعمال سطح دوم از محدودیت های فعالیت سیستم پس از ثابت ماندن دستگاه برای مدت معینی Doze.

توجه داشته باشید که فعال کردن صفحه نمایش یا وصل کردن آن به دستگاه از Doze خارج می شود و این محدودیت های پردازش را حذف می کند. رفتار اضافی بر توصیه‌ها و بهترین شیوه‌ها در تطبیق برنامه شما با نسخه قبلی Doze که در Android 6.0 (سطح API 23) معرفی شده است، تأثیری نمی‌گذارد، همانطور که در Optimizing for Doze و App Standby بحث شده است. همچنان باید این توصیه‌ها را دنبال کنید، مانند استفاده از Firebase Cloud Messaging (FCM) برای ارسال و دریافت پیام‌ها، و برنامه‌ریزی به‌روزرسانی‌ها را برای تطبیق با رفتار Doze اضافی شروع کنید.

Project Svelte: بهینه سازی پس زمینه

Android 7.0 سه پخش ضمنی را حذف می کند تا به بهینه سازی استفاده از حافظه و مصرف انرژی کمک کند. این تغییر ضروری است زیرا پخش‌های ضمنی اغلب برنامه‌هایی را شروع می‌کنند که برای گوش دادن به آنها در پس‌زمینه ثبت نام کرده‌اند. حذف این پخش ها می تواند به طور قابل توجهی به عملکرد دستگاه و تجربه کاربر کمک کند.

دستگاه‌های تلفن همراه تغییرات اتصال مکرری را تجربه می‌کنند، مانند هنگام جابجایی بین Wi-Fi و داده تلفن همراه. در حال حاضر، برنامه‌ها می‌توانند با ثبت یک گیرنده برای پخش ضمنی CONNECTIVITY_ACTION در مانیفست خود، تغییرات در اتصال را کنترل کنند. از آنجایی که بسیاری از برنامه‌ها برای دریافت این پخش ثبت نام می‌کنند، یک سوئیچ شبکه می‌تواند باعث شود که همه آنها بیدار شوند و پخش را به یکباره پردازش کنند.

به طور مشابه، در نسخه‌های قبلی Android، برنامه‌ها می‌توانستند برای دریافت پخش‌های ضمنی ACTION_NEW_PICTURE و ACTION_NEW_VIDEO از برنامه‌های دیگر، مانند دوربین، ثبت نام کنند. وقتی کاربر با برنامه دوربین عکس می‌گیرد، این برنامه‌ها برای پردازش پخش بیدار می‌شوند.

برای کاهش این مشکلات، Android 7.0 بهینه سازی های زیر را اعمال می کند:

  • برنامه‌هایی که Android 7.0 (سطح API 24) و بالاتر را هدف قرار می‌دهند، اگر گیرنده پخش خود را در مانیفست اعلام کنند، پخش‌های CONNECTIVITY_ACTION دریافت نمی‌کنند. اگر برنامه‌ها BroadcastReceiver خود را با Context.registerReceiver() ثبت کنند، همچنان پخش‌های CONNECTIVITY_ACTION را دریافت خواهند کرد و این زمینه همچنان معتبر است.
  • سیستم دیگر پخش ACTION_NEW_PICTURE یا ACTION_NEW_VIDEO را ارسال نمی کند. این بهینه‌سازی بر همه برنامه‌ها تأثیر می‌گذارد، نه تنها برنامه‌هایی که اندروید 7.0 را هدف قرار می‌دهند.

اگر برنامه شما از هر یک از این مقاصد استفاده می‌کند، باید وابستگی‌ها را در اسرع وقت حذف کنید تا بتوانید دستگاه‌های Android 7.0 را به درستی هدف‌گیری کنید. چارچوب Android چندین راه حل برای کاهش نیاز به این پخش های ضمنی ارائه می دهد. به عنوان مثال، JobScheduler API مکانیزمی قوی برای برنامه‌ریزی عملیات شبکه در زمانی که شرایط مشخص شده، مانند اتصال به یک شبکه بدون اندازه‌گیری برآورده می‌شود، فراهم می‌کند. حتی می توانید از JobScheduler برای واکنش به تغییرات ارائه دهندگان محتوا استفاده کنید.

برای اطلاعات بیشتر در مورد بهینه‌سازی پس‌زمینه در Android 7.0 (سطح API 24) و نحوه تطبیق برنامه خود، به بهینه‌سازی پس‌زمینه مراجعه کنید.

تغییرات مجوزها

Android 7.0 شامل تغییراتی در مجوزهایی است که ممکن است بر برنامه شما تأثیر بگذارد.

مجوز سیستم فایل تغییر می کند

به منظور بهبود امنیت فایل‌های خصوصی، دایرکتوری خصوصی برنامه‌هایی که Android نسخه ۷.۰ یا بالاتر را هدف قرار می‌دهند، دسترسی را محدود کرده است ( 0700 ). این تنظیم از نشت ابرداده فایل های خصوصی مانند اندازه یا وجود آنها جلوگیری می کند. این تغییر مجوز عوارض جانبی متعددی دارد:

  • مجوزهای فایل های خصوصی دیگر نباید توسط مالک کاهش یابد، و تلاش برای انجام این کار با استفاده از MODE_WORLD_READABLE و/یا MODE_WORLD_WRITEABLE ، یک SecurityException را ایجاد می کند.

    توجه: هنوز این محدودیت به طور کامل اجرا نشده است. برنامه ها همچنان ممکن است با استفاده از API های بومی یا File API مجوزها را در فهرست خصوصی خود تغییر دهند. با این حال، ما به شدت از کاهش مجوزهای فهرست خصوصی خودداری می کنیم.

  • عبور URIهای file:// در خارج از دامنه بسته ممکن است مسیری غیرقابل دسترسی برای گیرنده ایجاد کند. بنابراین، تلاش برای ارسال یک file:// URI باعث ایجاد یک FileUriExposedException می شود. روش توصیه شده برای به اشتراک گذاری محتوای یک فایل خصوصی استفاده از FileProvider است.
  • DownloadManager دیگر نمی تواند فایل های ذخیره شده خصوصی را با نام فایل به اشتراک بگذارد. برنامه‌های قدیمی ممکن است در هنگام دسترسی به COLUMN_LOCAL_FILENAME با یک مسیر غیرقابل دسترسی تمام شوند. برنامه‌هایی که Android نسخه 7.0 یا بالاتر را هدف قرار می‌دهند، هنگام تلاش برای دسترسی به COLUMN_LOCAL_FILENAME یک SecurityException ایجاد می‌کنند. برنامه‌های قدیمی که مکان دانلود را با استفاده از DownloadManager.Request.setDestinationInExternalFilesDir() یا DownloadManager.Request.setDestinationInExternalPublicDir() مکان دانلود را روی یک مکان عمومی تنظیم می‌کنند همچنان می‌توانند به مسیر در COLUMN_LOCAL_FILENAME دسترسی داشته باشند، اما این روش به شدت ممنوع است. راه ترجیحی برای دسترسی به فایلی که توسط DownloadManager در معرض دید قرار می‌گیرد، استفاده از ContentResolver.openFileDescriptor() است.

به اشتراک گذاری فایل ها بین برنامه ها

برای برنامه‌هایی که Android 7.0 را هدف قرار می‌دهند، چارچوب Android خط‌مشی StrictMode API را اعمال می‌کند که افشای file:// ​​URI در خارج از برنامه شما را ممنوع می‌کند. اگر یک هدف حاوی URI فایل از برنامه شما خارج شود، برنامه با یک استثنا FileUriExposedException از کار می افتد.

برای اشتراک گذاری فایل ها بین برنامه ها، باید یک content:// URI ارسال کنید و یک مجوز دسترسی موقت به URI بدهید. ساده ترین راه برای اعطای این مجوز استفاده از کلاس FileProvider است. برای اطلاعات بیشتر در مورد مجوزها و اشتراک گذاری فایل ها، به اشتراک گذاری فایل ها مراجعه کنید.

بهبود دسترسی

Android 7.0 شامل تغییراتی است که به منظور بهبود قابلیت استفاده از پلتفرم برای کاربرانی با دید ضعیف یا ضعیف طراحی شده است. این تغییرات معمولاً نیازی به تغییر کد در برنامه شما ندارند، با این حال باید این ویژگی ها را بررسی کرده و با برنامه خود آزمایش کنید تا تأثیرات احتمالی آن را بر تجربه کاربر ارزیابی کنید.

بزرگنمایی صفحه

Android 7.0 به کاربران امکان می‌دهد اندازه نمایشگر را تنظیم کنند که تمام عناصر روی صفحه را بزرگ یا کوچک می‌کند و در نتیجه دسترسی به دستگاه را برای کاربران کم‌بینا بهبود می‌بخشد. کاربران نمی توانند روی صفحه نمایش از حداقل عرض صفحه نمایش sw320dp بزرگنمایی کنند، که عرض یک Nexus 4، یک تلفن متوسط ​​معمولی است.

صفحه نمایش اندازه نمایشگر زوم نشده دستگاهی که دارای تصویر سیستم Android نسخه 7.0 است
صفحه نمایش اثر افزایش اندازه نمایشگر دستگاهی که دارای تصویر سیستم اندروید 7.0 است

شکل 3. صفحه سمت راست اثر افزایش اندازه نمایشگر دستگاهی را که دارای تصویر سیستم اندروید 7.0 است را نشان می دهد.

هنگامی که تراکم دستگاه تغییر می کند، سیستم به روش های زیر به برنامه های در حال اجرا اطلاع می دهد:

  • اگر برنامه ای سطح API 23 یا پایین تر را هدف قرار دهد، سیستم به طور خودکار تمام فرآیندهای پس زمینه خود را از بین می برد. این بدان معناست که اگر کاربر از چنین برنامه‌ای برای باز کردن صفحه تنظیمات و تغییر تنظیمات اندازه نمایشگر فاصله بگیرد، سیستم برنامه را به همان روشی که در موقعیت‌های کم حافظه انجام می‌دهد، از بین می‌برد. اگر برنامه دارای فرآیندهای پیش زمینه باشد، سیستم آن فرآیندها را از تغییر پیکربندی همانطور که در Handling Runtime Changes توضیح داده شده است مطلع می کند، درست مثل اینکه جهت دستگاه تغییر کرده است.
  • اگر برنامه‌ای Android 7.0 را هدف قرار دهد، همه فرآیندهای آن (پیش‌زمینه و پس‌زمینه) از تغییر پیکربندی همانطور که در Handling Runtime Changes توضیح داده شده مطلع می‌شوند.

اکثر برنامه ها برای پشتیبانی از این ویژگی نیازی به تغییر ندارند، مشروط بر اینکه برنامه ها از بهترین شیوه های اندروید پیروی کنند. موارد خاصی که باید بررسی شوند:

  • برنامه خود را روی دستگاهی با عرض صفحه sw320dp تست کنید و مطمئن شوید که به اندازه کافی کار می کند.
  • هنگامی که پیکربندی دستگاه تغییر می کند، هر گونه اطلاعات کش وابسته به چگالی، مانند بیت مپ های کش یا منابع بارگیری شده از شبکه را به روز کنید. هنگامی که برنامه از حالت توقف باز می‌گردد، تغییرات پیکربندی را بررسی کنید.

    توجه: اگر داده‌های وابسته به پیکربندی را در حافظه پنهان ذخیره می‌کنید، ایده خوبی است که ابرداده‌های مرتبط مانند اندازه صفحه نمایش یا تراکم پیکسلی مناسب برای آن داده را درج کنید. ذخیره این ابرداده به شما این امکان را می دهد که تصمیم بگیرید که آیا پس از تغییر پیکربندی نیاز به بازخوانی داده های حافظه پنهان دارید یا خیر.

  • از تعیین ابعاد با واحدهای px خودداری کنید، زیرا آنها با تراکم صفحه نمایش مقیاس ندارند. در عوض، ابعاد را با واحدهای پیکسل ( dp ) مستقل از چگالی مشخص کنید.

تنظیمات Vision در Setup Wizard

Android 7.0 شامل تنظیمات Vision در صفحه خوش‌آمدگویی است، جایی که کاربران می‌توانند تنظیمات دسترسی زیر را در یک دستگاه جدید تنظیم کنند: حرکت بزرگنمایی ، اندازه قلم ، اندازه نمایشگر و TalkBack . این تغییر باعث افزایش دید باگ های مربوط به تنظیمات مختلف صفحه نمایش می شود. برای ارزیابی تأثیر این ویژگی، باید برنامه های خود را با فعال بودن این تنظیمات آزمایش کنید. می‌توانید تنظیمات را در تنظیمات > دسترسی پیدا کنید.

پیوند برنامه‌های NDK به کتابخانه‌های پلتفرم

با شروع Android 7.0، این سیستم از اتصال پویا برنامه‌ها به کتابخانه‌های غیر NDK جلوگیری می‌کند، که ممکن است باعث از کار افتادن برنامه شما شود. هدف از این تغییر رفتار ایجاد یک تجربه برنامه سازگار در به‌روزرسانی‌های پلتفرم و دستگاه‌های مختلف است. حتی اگر کد شما ممکن است با کتابخانه‌های خصوصی مرتبط نباشد، ممکن است یک کتابخانه استاتیک شخص ثالث در برنامه شما این کار را انجام دهد. بنابراین، همه توسعه‌دهندگان باید بررسی کنند که برنامه‌هایشان در دستگاه‌های دارای اندروید ۷.۰ خراب نشود. اگر برنامه شما از کد بومی استفاده می کند، باید فقط از API های عمومی NDK استفاده کنید.

سه راه وجود دارد که برنامه شما ممکن است سعی کند به APIهای پلتفرم خصوصی دسترسی پیدا کند:

  • برنامه شما مستقیماً به کتابخانه های پلتفرم خصوصی دسترسی دارد. باید برنامه خود را به‌روزرسانی کنید تا نسخه‌ای از آن کتابخانه‌ها را شامل شود یا از APIهای عمومی NDK استفاده کنید.
  • برنامه شما از یک کتابخانه شخص ثالث استفاده می کند که به کتابخانه های پلت فرم خصوصی دسترسی دارد. حتی اگر مطمئن هستید که برنامه شما مستقیماً به کتابخانه های خصوصی دسترسی ندارد، همچنان باید برنامه خود را برای این سناریو آزمایش کنید.
  • برنامه شما به کتابخانه ای اشاره می کند که در APK آن موجود نیست. برای مثال، اگر سعی کنید از نسخه OpenSSL خود استفاده کنید اما فراموش کرده باشید که آن را با APK برنامه خود همراه کنید، ممکن است این اتفاق بیفتد. این برنامه ممکن است به طور معمول در نسخه‌های پلتفرم Android که شامل libcrypto.so است اجرا شود. با این حال، برنامه ممکن است در نسخه‌های بعدی اندروید که شامل این کتابخانه نمی‌شوند (مانند Android 6.0 و بالاتر) از کار بیفتد. برای رفع این مشکل، مطمئن شوید که همه کتابخانه‌های غیر NDK خود را با APK خود بسته‌بندی کرده‌اید.

برنامه‌ها نباید از کتابخانه‌های بومی که در NDK گنجانده نشده‌اند استفاده کنند زیرا ممکن است بین نسخه‌های مختلف Android تغییر یا حذف شوند. تغییر از OpenSSL به BoringSSL نمونه ای از چنین تغییری است. همچنین، از آنجایی که هیچ الزامات سازگاری برای کتابخانه‌های پلتفرم موجود در NDK وجود ندارد، دستگاه‌های مختلف ممکن است سطوح مختلفی از سازگاری را ارائه دهند.

به منظور کاهش تأثیری که این محدودیت ممکن است بر برنامه‌های منتشر شده در حال حاضر داشته باشد، مجموعه‌ای از کتابخانه‌ها که کاربرد قابل توجهی دارند - مانند libandroid_runtime.so ، libcutils.so ، libcrypto.so و libssl.so - به طور موقت در Android 7.0 قابل دسترسی هستند. (سطح API 24) برای برنامه هایی که سطح API 23 یا پایین تر را هدف قرار می دهند. اگر برنامه شما یکی از این کتابخانه ها را بارگیری کند، logcat یک هشدار ایجاد می کند و یک نان تست روی دستگاه مورد نظر ظاهر می شود تا به شما اطلاع دهد. اگر این هشدارها را مشاهده کردید، باید برنامه خود را به‌روزرسانی کنید تا یا نسخه‌ای از آن کتابخانه‌ها را شامل شود یا فقط از APIهای عمومی NDK استفاده کنید. نسخه‌های بعدی پلتفرم اندروید ممکن است استفاده از کتابخانه‌های خصوصی را به کلی محدود کند و باعث از کار افتادن برنامه شما شود.

همه برنامه ها هنگام فراخوانی یک API که نه عمومی است و نه به طور موقت در دسترس است، خطای زمان اجرا ایجاد می کنند. نتیجه این است که System.loadLibrary و dlopen(3) هر دو NULL را برمی‌گردانند و ممکن است باعث از کار افتادن برنامه شما شوند. باید کد برنامه خود را بررسی کنید تا استفاده از APIهای پلتفرم خصوصی را حذف کنید و برنامه های خود را با استفاده از دستگاه یا شبیه ساز دارای Android 7.0 (سطح API 24) به طور کامل آزمایش کنید. اگر مطمئن نیستید که آیا برنامه شما از کتابخانه های خصوصی استفاده می کند، می توانید logcat را بررسی کنید تا خطای زمان اجرا را شناسایی کنید.

جدول زیر رفتاری را که باید از یک برنامه بسته به استفاده از کتابخانه‌های بومی خصوصی و سطح API هدف آن ( android:targetSdkVersion ) انتظار داشته باشید را توصیف می‌کند.

کتابخانه ها سطح API را هدف قرار دهید دسترسی در زمان اجرا از طریق لینکر پویا رفتار Android 7.0 (سطح API 24). رفتار پلتفرم اندروید آینده
عمومی NDK هر قابل دسترس همانطور که انتظار می رود کار می کند همانطور که انتظار می رود کار می کند
خصوصی (کتابخانه های خصوصی با دسترسی موقت) 23 یا کمتر به طور موقت در دسترس است همانطور که انتظار می رود کار می کند، اما شما یک هشدار logcat دریافت می کنید. خطای زمان اجرا
خصوصی (کتابخانه های خصوصی با دسترسی موقت) 24 یا بالاتر محدود شده است خطای زمان اجرا خطای زمان اجرا
خصوصی (سایر) هر محدود شده است خطای زمان اجرا خطای زمان اجرا

بررسی کنید که آیا برنامه شما از کتابخانه های خصوصی استفاده می کند

برای کمک به شناسایی مشکلات بارگیری کتابخانه های خصوصی، logcat ممکن است یک هشدار یا خطای زمان اجرا ایجاد کند. به عنوان مثال، اگر برنامه شما سطح API 23 یا پایین‌تر را هدف قرار می‌دهد و سعی می‌کند به یک کتابخانه خصوصی در دستگاهی که Android نسخه 7.0 دارد دسترسی پیدا کند، ممکن است هشداری مشابه موارد زیر مشاهده کنید:

03-21 17:07:51.502 31234 31234 W linker  : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120

این اخطارهای logcat به شما می‌گویند کدام کتابخانه سعی می‌کند به یک API پلتفرم خصوصی دسترسی پیدا کند، اما باعث از کار افتادن برنامه شما نمی‌شود. اگر برنامه سطح API 24 یا بالاتر را هدف قرار دهد، logcat خطای زمان اجرا زیر را ایجاد می کند و ممکن است برنامه شما از کار بیفتد:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so"
("/system/lib/libcutils.so") needed or dlopened by
"/system/lib/libnativeloader.so" is not accessible for the namespace
"classloader-namespace"
  at java.lang.Runtime.loadLibrary0(Runtime.java:977)
  at java.lang.System.loadLibrary(System.java:1602)

همچنین اگر برنامه شما از کتابخانه های شخص ثالثی استفاده می کند که به صورت پویا به API های پلت فرم خصوصی پیوند می زنند، ممکن است این خروجی های logcat را ببینید. ابزار readelf در Android 7.0DK به شما این امکان را می‌دهد که با اجرای دستور زیر، فهرستی از تمام کتابخانه‌های مشترک پیوند شده پویا از یک فایل .so را ایجاد کنید:

aarch64-linux-android-readelf -dW libMyLibrary.so

برنامه خود را به روز کنید

در اینجا چند مرحله وجود دارد که می‌توانید برای رفع این نوع خطاها انجام دهید و مطمئن شوید که برنامه شما در به‌روزرسانی‌های آینده پلتفرم خراب نمی‌شود:

  • اگر برنامه شما از کتابخانه‌های پلتفرم خصوصی استفاده می‌کند، باید آن را به‌روزرسانی کنید تا نسخه‌ای از آن کتابخانه‌ها را شامل شود یا از APIهای عمومی NDK استفاده کنید.
  • اگر برنامه شما از کتابخانه شخص ثالثی استفاده می کند که به نمادهای خصوصی دسترسی دارد، برای به روز رسانی کتابخانه با نویسنده کتابخانه تماس بگیرید.
  • مطمئن شوید که تمام کتابخانه های غیر NDK خود را با APK خود بسته بندی کرده اید.
  • از توابع استاندارد JNI به جای getJavaVM و getJNIEnv از libandroid_runtime.so استفاده کنید:
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • از __system_property_get به جای نماد خصوصی_ property_get از libcutils.so استفاده کنید. برای انجام این کار، از __system_property_get با موارد زیر استفاده کنید:
    #include <sys/system_properties.h>

    توجه: در دسترس بودن و محتوای ویژگی های سیستم از طریق CTS آزمایش نمی شود. راه حل بهتر این است که به طور کامل از این ویژگی ها استفاده نکنید.

  • از یک نسخه محلی نماد SSL_ctrl از libcrypto.so استفاده کنید. برای مثال، باید libcyrpto.a به صورت ایستا در فایل .so خود پیوند دهید، یا یک نسخه پیوند شده پویا از libcrypto.so را از BoringSSL/OpenSSL اضافه کنید و آن را در APK خود بسته بندی کنید.

اندروید برای کار

Android 7.0 شامل تغییراتی برای برنامه‌هایی است که Android for Work را هدف قرار می‌دهند، از جمله تغییرات در نصب گواهی، بازنشانی رمز عبور، مدیریت کاربر ثانویه، و دسترسی به شناسه‌های دستگاه. اگر در حال ساختن برنامه برای محیط‌های Android for Work هستید، باید این تغییرات را بررسی کنید و برنامه خود را بر اساس آن اصلاح کنید.

  • قبل از اینکه DPC بتواند آن را تنظیم کند، باید نصب کننده گواهی تفویض شده را نصب کنید. برای برنامه‌های نمایه و مالک دستگاه که Android 7.0 (سطح API 24) را هدف قرار می‌دهند، باید نصب‌کننده گواهی واگذار شده را قبل از اینکه کنترل‌کننده خط‌مشی دستگاه (DPC) DevicePolicyManager.setCertInstallerPackage() را فراخوانی کند نصب کنید. اگر نصب کننده قبلاً نصب نشده باشد، سیستم یک IllegalArgumentException را پرتاب می کند.
  • محدودیت‌های بازنشانی گذرواژه برای مدیران دستگاه اکنون برای مالکان نمایه اعمال می‌شود. مدیران دستگاه دیگر نمی‌توانند از DevicePolicyManager.resetPassword() برای پاک کردن گذرواژه‌ها یا تغییر گذرواژه‌هایی که قبلاً تنظیم شده‌اند استفاده کنند. سرپرست‌های دستگاه همچنان می‌توانند رمز عبور تعیین کنند، اما فقط زمانی که دستگاه رمز عبور، پین یا الگوی نداشته باشد.
  • صاحبان دستگاه و نمایه می‌توانند حساب‌ها را مدیریت کنند، حتی اگر محدودیت‌هایی تعیین شده باشد. صاحبان دستگاه و مالکان نمایه می‌توانند با APIهای مدیریت حساب تماس بگیرند، حتی اگر محدودیت‌های کاربری DISALLOW_MODIFY_ACCOUNTS وجود داشته باشد.
  • صاحبان دستگاه می توانند کاربران ثانویه را راحت تر مدیریت کنند. وقتی دستگاهی در حالت مالک دستگاه اجرا می‌شود، محدودیت DISALLOW_ADD_USER به‌طور خودکار تنظیم می‌شود. این از ایجاد کاربران ثانویه مدیریت نشده توسط کاربران جلوگیری می کند. علاوه بر این، متدهای CreateUser() و createAndInitializeUser() منسوخ شده اند. متد جدید DevicePolicyManager.createAndManageUser() جایگزین آنها می شود.
  • صاحبان دستگاه می توانند به شناسه های دستگاه دسترسی داشته باشند. صاحب دستگاه می‌تواند با استفاده از DevicePolicyManager.getWifiMacAddress() به آدرس مک Wi-Fi یک دستگاه دسترسی داشته باشد. اگر Wi-Fi هرگز در دستگاه فعال نشده باشد، این روش مقدار null را برمی‌گرداند.
  • تنظیم حالت کار دسترسی به برنامه های کاری را کنترل می کند. وقتی حالت کار خاموش است، راه‌انداز سیستم نشان می‌دهد که برنامه‌های کاری با خاکستری کردن آن‌ها در دسترس نیستند. فعال کردن حالت کار دوباره رفتار عادی را بازیابی می کند.
  • هنگام نصب یک فایل PKCS #12 حاوی یک زنجیره گواهی مشتری و کلید خصوصی مربوطه از تنظیمات UI، گواهی CA در زنجیره دیگر در فضای ذخیره اطلاعات مورد اعتماد نصب نمی شود. هنگامی که برنامه‌ها تلاش می‌کنند زنجیره گواهی مشتری را بعداً بازیابی کنند، این روی نتیجه KeyChain.getCertificateChain() تأثیری نمی‌گذارد. در صورت نیاز، گواهی CA باید به طور جداگانه از طریق تنظیمات UI، با یک قالب رمزگذاری شده با DER تحت پسوند فایل crt. یا cer. در فضای ذخیره اطلاعات معتبر نصب شود.
  • با شروع اندروید 7.0، ثبت نام اثر انگشت و فضای ذخیره سازی برای هر کاربر مدیریت می شود. اگر Device Policy Client (DPC) مالک نمایه، سطح API 23 (یا پایین‌تر) را در دستگاهی با Android 7.0 (سطح API 24) هدف قرار دهد، کاربر همچنان می‌تواند اثر انگشت را روی دستگاه تنظیم کند، اما برنامه‌های کاربردی نمی‌توانند به اثر انگشت دستگاه دسترسی داشته باشند. وقتی DPC سطح API 24 و بالاتر را هدف قرار می دهد، کاربر می تواند با رفتن به تنظیمات > امنیت > امنیت نمایه کاری ، اثر انگشت را به طور خاص برای نمایه کاری تنظیم کند.
  • یک وضعیت رمزگذاری جدید ENCRYPTION_STATUS_ACTIVE_PER_USER توسط DevicePolicyManager.getStorageEncryptionStatus() برگردانده می شود تا نشان دهد که رمزگذاری فعال است و کلید رمزگذاری به کاربر گره خورده است. وضعیت جدید تنها در صورتی برگردانده می شود که DPC سطح API 24 و بالاتر را هدف قرار دهد. برای برنامه‌هایی که سطوح API قبلی را هدف قرار می‌دهند، ENCRYPTION_STATUS_ACTIVE برگردانده می‌شود، حتی اگر کلید رمزگذاری مختص کاربر یا نمایه باشد.
  • در Android 7.0، اگر دستگاه دارای نمایه کاری با چالش کاری جداگانه نصب شده باشد، چندین روش که معمولاً کل دستگاه را تحت تأثیر قرار می دهند، رفتار متفاوتی دارند. این روش‌ها به‌جای تأثیرگذاری بر کل دستگاه، فقط برای نمایه کاری اعمال می‌شوند. (فهرست کامل این روش ها در اسناد DevicePolicyManager.getParentProfileInstance() است.) برای مثال، DevicePolicyManager.lockNow() فقط نمایه کاری را قفل می کند، به جای قفل کردن کل دستگاه. برای هر یک از این روش‌ها، می‌توانید با فراخوانی روش در نمونه والد DevicePolicyManager ، رفتار قدیمی را دریافت کنید. می‌توانید با فراخوانی DevicePolicyManager.getParentProfileInstance() این والد را دریافت کنید. به عنوان مثال، اگر متد lockNow() نمونه والد را فراخوانی کنید، کل دستگاه قفل می شود.

یادداشت ها حفظ

Android 7.0 اشکالی را که در آن قابل مشاهده بودن حاشیه نویسی ها نادیده گرفته می شد، برطرف می کند. این مشکل زمان اجرا را فعال کرد تا به حاشیه نویسی هایی که نباید می توانست دسترسی داشته باشد. این یادداشت ها شامل موارد زیر بود:

  • VISIBILITY_BUILD : در نظر گرفته شده است که فقط در زمان ساخت قابل مشاهده باشد.
  • VISIBILITY_SYSTEM : در نظر گرفته شده است که در زمان اجرا قابل مشاهده باشد، اما فقط برای سیستم اصلی.

اگر برنامه شما به این رفتار متکی است، لطفاً یک خط مشی حفظ را به حاشیه نویسی اضافه کنید که باید در زمان اجرا در دسترس باشد. این کار را با استفاده از @Retention(RetentionPolicy.RUNTIME) انجام می دهید.

تغییرات پیکربندی پیش فرض TLS/SSL

Android 7.0 تغییرات زیر را در پیکربندی پیش‌فرض TLS/SSL مورد استفاده برنامه‌ها برای HTTPS و سایر ترافیک TLS/SSL ایجاد می‌کند:

  • مجموعه‌های رمز RC4 اکنون غیرفعال شده‌اند.
  • مجموعه‌های رمز CHACHA20-POLY1305 اکنون فعال هستند.

غیرفعال شدن RC4 به طور پیش‌فرض ممکن است منجر به قطع شدن اتصال HTTPS یا TLS/SSL شود، زمانی که سرور با مجموعه‌های رمزنگاری مدرن مذاکره نمی‌کند. راه حل ترجیحی بهبود پیکربندی سرور برای فعال کردن مجموعه‌ها و پروتکل‌های رمز قوی‌تر و مدرن‌تر است. در حالت ایده‌آل، TLSv1.2 و AES-GCM باید فعال باشند، و مجموعه‌های رمز محرمانه پیشرو (ECDHE) باید فعال و ترجیح داده شوند.

یک جایگزین این است که برنامه را تغییر دهید تا از یک SSLSocketFactory سفارشی برای برقراری ارتباط با سرور استفاده کنید. کارخانه باید به گونه‌ای طراحی شود که نمونه‌های SSLSocket را ایجاد کند که علاوه بر مجموعه‌های رمز پیش‌فرض، برخی از مجموعه‌های رمز مورد نیاز سرور را فعال کنند.

توجه: این تغییرات مربوط به WebView نیست.

برنامه هایی که اندروید 7.0 را هدف قرار می دهند

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

تغییرات سریال سازی

Android 7.0 (سطح API 24) اشکالی را در محاسبه سریالVersionUID پیش‌فرض رفع کرد که با مشخصات مطابقت نداشت.

کلاس‌هایی که Serializable پیاده‌سازی می‌کنند و فیلد serialVersionUID صریح را مشخص نمی‌کنند، می‌توانند تغییری در serialVersionUID پیش‌فرض خود ببینند که باعث می‌شود هنگام تلاش برای سریال‌زدایی نمونه‌هایی از کلاس که در نسخه‌های قبلی سریال‌سازی شده‌اند یا توسط برنامه‌ای که هدفش سریال‌سازی شده‌اند، استثنا ایجاد شود. نسخه قبلی پیام خطا چیزی شبیه به این خواهد بود:

local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567

رفع این مشکلات مستلزم افزودن یک فیلد serialVersionUID به هر کلاس آسیب‌دیده با مقدار stream classdesc serialVersionUID از پیام خطا است، مثلاً در این مورد 1234 . این تغییر به همه توصیه‌های عملی خوب برای نوشتن کد سریال‌سازی پایبند است و روی همه نسخه‌های اندروید کار خواهد کرد.

اشکال خاصی که رفع شد مربوط به وجود روش های اولیه استاتیک، یعنی <clinit> بود. با توجه به مشخصات، وجود یا عدم وجود یک روش اولیه استاتیک در کلاس، سریالVersionUID پیش‌فرض محاسبه‌شده برای آن کلاس را تحت تأثیر قرار می‌دهد. قبل از رفع اشکال، اگر کلاسی نداشته باشد، محاسبات کلاس فوق را برای یک اولیه‌ساز استاتیک بررسی می‌کند.

برای روشن‌تر شدن، این تغییر بر برنامه‌هایی که سطوح API 23 یا پایین‌تر را هدف می‌گیرند، کلاس‌هایی که دارای یک قسمت serialVersionUID هستند یا کلاس‌هایی که دارای روش اولیه‌ای استاتیک هستند، تأثیر نمی‌گذارد.

سایر نکات مهم

  • هنگامی که یک برنامه در Android 7.0 اجرا می شود، اما سطح API پایین تری را هدف قرار می دهد و کاربر اندازه نمایشگر را تغییر می دهد، روند برنامه از بین می رود. برنامه باید بتواند به خوبی این سناریو را مدیریت کند. در غیر این صورت، زمانی که کاربر آن را از Recents بازیابی می کند، از کار می افتد.

    باید برنامه خود را آزمایش کنید تا مطمئن شوید که این رفتار رخ نمی دهد. شما می توانید این کار را با ایجاد یک خرابی یکسان در هنگام کشتن دستی برنامه از طریق DDMS انجام دهید.

    برنامه‌هایی که اندروید 7.0 (سطح API 24) و بالاتر را هدف قرار می‌دهند، به‌طور خودکار با تغییرات چگالی از بین نمی‌روند. با این حال، ممکن است همچنان به تغییرات پیکربندی ضعیف پاسخ دهند.

  • برنامه‌های اندروید 7.0 باید بتوانند تغییرات پیکربندی را به خوبی مدیریت کنند و نباید در شروع‌های بعدی خراب شوند. می‌توانید رفتار برنامه را با تغییر اندازه قلم ( تنظیم > نمایش > اندازه قلم )، و سپس بازیابی برنامه از Recents تأیید کنید.
  • به دلیل وجود اشکال در نسخه‌های قبلی اندروید، سیستم نوشتن در سوکت TCP در رشته اصلی را به‌عنوان نقض حالت سخت پرچم‌گذاری نکرد. اندروید 7.0 این باگ را برطرف می کند. برنامه‌هایی که این رفتار را نشان می‌دهند اکنون یک android.os.NetworkOnMainThreadException می‌اندازند. به طور کلی، انجام عملیات شبکه بر روی رشته اصلی ایده بدی است زیرا این عملیات معمولا تاخیر بالایی دارند که باعث ANR و jank می شود.
  • خانواده روش‌های Debug.startMethodTracing() اکنون به‌جای ذخیره‌سازی در سطح بالای کارت SD، خروجی‌ها را به‌طور پیش‌فرض در دایرکتوری مخصوص بسته شما در فضای ذخیره‌سازی مشترک ذخیره می‌کنند. این بدان معناست که برنامه‌ها دیگر نیازی به درخواست مجوز WRITE_EXTERNAL_STORAGE برای استفاده از این APIها ندارند.
  • بسیاری از APIهای پلتفرم اکنون شروع به بررسی برای بارهای بزرگ ارسال شده در تراکنش‌های Binder کرده‌اند، و سیستم اکنون TransactionTooLargeExceptions به‌جای ثبت یا سرکوب بی‌صدا به عنوان RuntimeExceptions بازگردانی می‌کند. یکی از مثال‌های رایج، ذخیره داده‌های بیش از حد در Activity.onSaveInstanceState() است که باعث می‌شود ActivityThread.StopInfo زمانی که برنامه شما Android 7.0 را هدف قرار می‌دهد RuntimeException ایجاد کند.
  • اگر یک برنامه وظایف Runnable را در یک View پست کند، و View به پنجره متصل نباشد، سیستم وظیفه Runnable را با View در صف قرار می دهد. کار Runnable تا زمانی که View به یک پنجره متصل نشود اجرا نمی شود. این رفتار باگ های زیر را برطرف می کند:
    • اگر برنامه‌ای از رشته‌ای غیر از رشته رابط کاربری پنجره مورد نظر به View پست شود، در نتیجه Runnable ممکن است در رشته اشتباهی اجرا شود.
    • اگر وظیفه Runnable از یک رشته به غیر از یک رشته حلقه پست شده باشد، برنامه می تواند وظیفه Runnable را آشکار کند.
  • اگر برنامه‌ای در Android 7.0 با مجوز DELETE_PACKAGES سعی کند بسته‌ای را حذف کند، اما برنامه دیگری آن بسته را نصب کرده باشد، سیستم به تأیید کاربر نیاز دارد. در این سناریو، برنامه‌ها هنگام فراخوانی PackageInstaller.uninstall() باید از STATUS_PENDING_USER_ACTION به عنوان وضعیت بازگشت انتظار داشته باشند.
  • ارائه دهنده JCA به نام Crypto منسوخ شده است، زیرا تنها الگوریتم آن، SHA1PRNG، از نظر رمزنگاری ضعیف است. برنامه‌ها دیگر نمی‌توانند از SHA1PRNG برای استخراج (ناامن) کلیدها استفاده کنند، زیرا این ارائه‌دهنده دیگر در دسترس نیست. برای اطلاعات بیشتر، به پست وبلاگ ارائه دهنده امنیت "Crypto" منسوخ شده در Android N مراجعه کنید.