التغييرات في السلوك: التطبيقات التي تستهدف الإصدار 17 من Android أو الإصدارات الأحدث

مثل الإصدارات السابقة، يتضمّن Android 17 تغييرات في السلوك قد تؤثر في تطبيقك. تنطبق التغييرات التالية في السلوك حصريًا على التطبيقات التي تستهدف Android 17 أو الإصدارات الأحدث. إذا كان تطبيقك يستهدف Android 17 أو إصدارًا أحدث، عليك تعديله ليتوافق مع هذه السلوكيات، حيثما ينطبق ذلك.

يُرجى أيضًا مراجعة قائمة التغييرات في السلوك التي تؤثر في جميع التطبيقات التي تعمل على Android 17 بغض النظر عن targetSdkVersion لتطبيقك.

تجربة المستخدم وواجهة مستخدم النظام

يتضمّن Android 17 التغييرات التالية التي تهدف إلى إنشاء تجربة مستخدم أكثر اتساقًا وسهولة.

التطبيق المصغّر لحدّ الذاكرة

بدءًا من الإصدار Android 17، يفرض النظام حدًا صارمًا على الذاكرة المستخدَمة في تحديثات RemoteViews للتطبيقات التي تستهدف الإصدار Android 17 (المستوى 37 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث. عندما يمرّر تطبيق عنصر RemoteViews إلى AppWidgetManager.updateAppWidget، تحسب system_server إجمالي استهلاك الذاكرة لجميع بيانات الصور في كل مجموعة اتجاه وحجم في الحمولة. إذا تجاوز إجمالي الذاكرة الحد الأقصى للنظام (mMaxWidgetBitmapMemory)، يرفض النظام التحديث ويعرض الخطأ IllegalArgumentException:

java.lang.IllegalArgumentException: RemoteViews for widget update exceeds maximum bitmap memory usage (used: XXXXX, max: YYYYY)

بالنسبة إلى التطبيقات التي تستهدف المستوى 36 أو أقل من واجهة برمجة التطبيقات، يسجّل النظام انتهاك الذاكرة هذا كتحذير (Slog.w) بدون طرح استثناء.

كيفية احتساب النظام للحدّ الأقصى للذاكرة

يضبط النظام ميزانية ذاكرة الصور النقطية للأداة على 6 * width * height بايت (1.5 * 4 * width * height، أي ما يعادل 1.5 ضعف حجم مخزن مؤقت ARGB_8888 بملء الشاشة) لإعدادات العرض النشطة. في المستوى 37 من واجهة برمجة التطبيقات والإصدارات الأحدث، تشمل عملية الاحتساب هذه ما يلي:

  • عناصر Bitmap في الذاكرة وعناصر Icon المستندة إلى الصور النقطية (Icon.TYPE_BITMAP وIcon.TYPE_ADAPTIVE_BITMAP) المخزَّنة في RemoteViews.mBitmapCache (مثل طلبات setImageViewBitmap أو Icon.createWithBitmap أو Icon.createWithAdaptiveBitmap أو Jetpack Glance ImageProvider(bitmap)). يتم احتساب كل مثيل فريد من Bitmap أو Icon المستند إلى الصور النقطية في mBitmapCache مرة واحدة لكل تسلسل هرمي في RemoteViews.
  • لا يتم احتساب الصور المستندة إلى معرّف الموارد المنتظم (URI) (Icon.createWithContentUri أو setImageViewUri أو Glance ImageProvider(uri)) ضمن الحد الأقصى لعدد وحدات بايت RemoteViews في الاتصال بين العمليات (IPC) في system_server، ولكن عملية مضيف التطبيق المصغّر تفك ترميز ملف content:// المُشار إليه بدقة كاملة في الذاكرة الديناميكية الخاصة به. يجب دائمًا كتابة صورة تم تقليل حجمها في context.cacheDir قبل عرضها من خلال معرّف موارد منتظم (URI) من النوع FileProvider.

خطوات الحدّ من التأثير

لإبقاء تحديثات التطبيقات المصغّرة ضمن الحد الأقصى للذاكرة على الهواتف والأجهزة اللوحية والأجهزة القابلة للطي، اتّبِع الخطوات التالية:

  1. احتساب ميزانية الذاكرة لوقت التشغيل من WindowMetrics: في مستوى واجهة برمجة التطبيقات 30 والإصدارات الأحدث، يمكنك قراءة حدود النافذة النشطة من WindowManager.currentWindowMetrics.bounds بدلاً من resources.displayMetrics. على الأجهزة المتعددة الدقة والأجهزة القابلة للطي، قد يعرض "displayMetrics" أبعاد الشاشة غير النشطة. قدِّر إجمالي ميزانية صور التطبيقات المصغّرة على النحو التالي: 6L * bounds.width() * bounds.height() كما هو موضّح في المثال التالي:

    private const val FALLBACK_MAX_BYTES = 15_000_000L
    
    fun calculateWidgetMemoryCapBytes(context: Context): Long {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val wm = context.getSystemService(WindowManager::class.java)
                ?: return FALLBACK_MAX_BYTES
            val bounds = wm.currentWindowMetrics.bounds
            return 6L * bounds.width().toLong() * bounds.height().toLong()
        }
        val dm = context.resources.displayMetrics
        return 6L * dm.widthPixels.toLong() * dm.heightPixels.toLong()
    }
    
  2. يجب تقليل دقة الصور لتتلاءم مع أبعاد العرض في التطبيق المصغّر واستخدام RGB_565: يجب فك ترميز الصور النقطية باستخدام قيم BitmapFactory.Options.inSampleSize من مضاعفات الرقم 2 بحجم يتناسب مع الحد الأقصى لأبعاد العرض في التطبيق المصغّر (maxWidthDp في maxHeightDp)، واستخدام Bitmap.Config.RGB_565 (2 بايت لكل بكسل) بدلاً من ARGB_8888 (4 بايت لكل بكسل) للصور الفوتوغرافية والصور المصغّرة غير الشفافة.

  3. رفع ترميز الصور النقطية خارج provideContent في Jetpack Glance: عند استخدام SizeMode.Responsive أو SizeMode.Exact، يستدعي Glance دالة lambda provideContent مرة واحدة لكل مجموعة حجم. يجب فك ترميز كل Bitmap مشترَك مرة واحدة داخل provideGlance قبل استدعاء provideContent لكي تشير جميع مجموعات الأحجام إلى مثيل Bitmap نفسه في RemoteViews.mBitmapCache.

  4. استخدام طلبات updateAppWidget الكاملة عند استبدال الصور: في عمليات التنفيذ الكلاسيكية لـ AppWidgetProvider، تجنَّب طلب AppWidgetManager.partiallyUpdateAppWidget لتبديل طرق عرض Bitmap أو Icon. تدمج التحديثات الجزئية الإجراءات الجديدة في شجرة RemoteViews الحالية في system_server بدون إزالة إجراءات الصور المخزّنة مؤقتًا سابقًا. يمكنك إنشاء تنسيق RemoteViews كامل واستدعاء updateAppWidget بدلاً من ذلك.

  5. توفير تنسيق احتياطي في حال حدوث خطأ: في Jetpack Glance، يمكنك إلغاء onCompositionError لعرض عنصر احتياطي RemoteViews بدون صور نقطية في حال تعذّر التحديث.

يمكنك فحص استخدام الذاكرة الحالي للصور النقطية المتسلسلة في التطبيق المصغّر على جهاز متصل من خلال تنفيذ ما يلي:

adb shell dumpsys appwidget

الوظيفة الأساسية

يتضمّن Android 17 التغييرات التالية التي تعدّل أو توسّع إمكانات أساسية متنوّعة في نظام Android.

تنفيذ جديد لـ MessageQueue بدون قفل

بدءًا من الإصدار 17 من نظام التشغيل Android، تحصل التطبيقات التي تستهدف الإصدار 17 من نظام التشغيل Android (المستوى 37 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث على تنفيذ جديد بدون قفل لـ android.os.MessageQueue. يؤدي التنفيذ الجديد إلى تحسين الأداء وتقليل اللقطات المفقودة، ولكنه قد يؤدي إلى تعطُّل البرامج التي تستخدم MessageQueue الحقول والأساليب الخاصة.

لمزيد من المعلومات، بما في ذلك استراتيجيات تخفيف الأثر، يُرجى الاطّلاع على إرشادات حول تغيير سلوك MessageQueue.

أصبحت الحقول النهائية الثابتة غير قابلة للتعديل الآن

Apps running on Android 17 or higher that target Android 17 (API level 37) or higher cannot change static final fields. If an app attempts to change a static final field by using reflection, it will cause an IllegalAccessException. Attempting to modify one of these fields through JNI APIs (such as SetStaticLongField()) will cause the app to crash.

تسهيل الاستخدام

يُجري Android 17 التغييرات التالية لتحسين ميزات تسهيل الاستخدام.

تسهيل استخدام لوحة المفاتيح الخارجية المعقّدة التي تستخدم أسلوب الإدخال (IME)

This feature introduces new AccessibilityEvent and TextAttribute APIs to enhance screen reader spoken feedback for CJKV language input. CJKV IME apps can now signal whether a text conversion candidate has been selected during text composition. Apps with edit fields can specify text change types when sending text changed accessibility events. For example, apps can specify that a text change occurred during text composition, or that a text change resulted from a commit. Doing this enables accessibility services such as screen readers to deliver more precise feedback based on the nature of the text modification.

App adoption

  • IME Apps: When setting composing text in edit fields, IMEs can use TextAttribute.Builder.setTextSuggestionSelected() to indicate whether a specific conversion candidate was selected.

  • Apps with Edit Fields: Apps that maintain a custom InputConnection can retrieve candidate selection data by calling TextAttribute.isTextSuggestionSelected(). These apps should then call AccessibilityEvent.setTextChangeTypes() when dispatching TYPE_VIEW_TEXT_CHANGED events. Apps targeting Android 17 (API level 37) that use the standard TextView will have this feature enabled by default. (That is, TextView will handle retrieving data from the IME and setting text change types when sending events to accessibility services).

  • Accessibility Services: Accessibility services that process TYPE_VIEW_TEXT_CHANGED events can call AccessibilityEvent.getTextChangeTypes() to identify the nature of the modification and adjust their feedback strategies accordingly.

الخصوصية

يتضمّن Android 17 التغييرات التالية لتحسين خصوصية المستخدم.

تم تفعيل بروتوكول ECH (Encrypted Client Hello)

Android 17 introduces platform support for Encrypted Client Hello (ECH), a TLS extension that enhances user privacy by encrypting the Server Name Indication (SNI) in the TLS handshake. This encryption helps prevent network observers from easily identifying the specific domain your app is connecting to.

For apps targeting Android 17 (API level 37) or higher, ECH is used for TLS connections. ECH is active only if the networking library used by the app (for example, HttpEngine, WebView, or OkHttp) has integrated ECH support and the remote server also supports the ECH protocol. If ECH cannot be negotiated, the client sends an ECH extension with randomized contents (a mechanism called ECH GREASE). See RFC 9849 for more details on how ECH GREASE works.

To allow apps to customize this behavior, Android 17 adds a new <domainEncryption> element to the Network Security Configuration file. Developers can use <domainEncryption> within <base-config> or <domain-config> tags to select an ECH mode (for example, "enabled" or "disabled") on a global or per-domain basis.

For more information, see the Encrypted Client Hello documentation.

إذن الوصول إلى الشبكة المحلية مطلوب للتطبيقات التي تستهدف الإصدار 17 من Android

يقدّم Android 17 إذن التشغيل ACCESS_LOCAL_NETWORK لحماية المستخدمين من الوصول غير المصرَّح به إلى الشبكة المحلية. بما أنّ هذا الإذن يندرج ضمن مجموعة أذونات NEARBY_DEVICES الحالية، لن يُطلب من المستخدمين الذين سبق لهم منح أذونات NEARBY_DEVICES أخرى منح هذا الإذن مرة أخرى. يمنع هذا الشرط الجديد التطبيقات الضارة من استغلال الوصول غير المقيّد إلى الشبكة المحلية لتتبُّع المستخدمين بشكل خفي واستكشاف تفاصيل أجهزتهم. من خلال الإفصاح عن هذا الإذن وطلبه، يمكن لتطبيقك اكتشاف الأجهزة المتصلة بشبكة الاتصال المحلية (LAN) والاتصال بها، مثل الأجهزة المنزلية الذكية أو أجهزة استقبال البث.

أمام التطبيقات التي تستهدف الإصدار 17 من Android (مستوى واجهة برمجة التطبيقات 37) أو الإصدارات الأحدث الآن طريقتان للحفاظ على الاتصال بأجهزة شبكة LAN: استخدام أدوات اختيار الأجهزة التي يتوسّطها النظام والتي تحافظ على الخصوصية لتخطّي طلب الإذن، أو طلب هذا الإذن الجديد صراحةً أثناء وقت التشغيل للحفاظ على الاتصال بالشبكة المحلية.

لمزيد من المعلومات، يُرجى الاطّلاع على مستندات إذن الشبكة المحلية.

إخفاء كلمات المرور من الأجهزة الفعلية

إذا كان التطبيق يستهدف الإصدار 17 من نظام التشغيل Android (المستوى 37 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث وكان المستخدم يستخدم جهاز إدخال ماديًا (مثل لوحة مفاتيح خارجية)، يطبّق نظام التشغيل Android الإعداد الجديد show_passwords_physical على جميع الأحرف في حقل كلمة المرور. يؤدي هذا الإعداد تلقائيًا إلى إخفاء جميع أحرف كلمة المرور.

يعرض نظام Android آخر حرف تم كتابته في كلمة المرور لمساعدة المستخدم في معرفة ما إذا كان قد أخطأ في كتابة كلمة المرور. ومع ذلك، فإن هذا أقل ضرورة مع لوحات المفاتيح الخارجية الأكبر حجمًا. بالإضافة إلى ذلك، غالبًا ما تحتوي الأجهزة التي تتضمّن لوحات مفاتيح خارجية على شاشات أكبر، ما يزيد من خطر رؤية شخص ما لكلمة المرور التي تتم كتابتها.

إذا كان المستخدم يستخدم شاشة الجهاز التي تعمل باللمس، يطبّق النظام الإعداد الجديد show_passwords_touch.

حماية كلمات المرور الصالحة لمرة واحدة (OTP) في رسائل SMS العادية

Beginning with Android 17, Android is extending its SMS OTP protection to apply to standard SMS messages (SMS messages containing an OTP that do not use the WebOTP or SMS Retriever formats). For most apps targeting Android 17 (API level 37) or higher, these SMS messages do not become available until three hours after receipt. This delay is intended to help prevent OTP hijacking. During this three hour delay, the SMS_RECEIVED_ACTION broadcast is withheld and SMS provider database queries are filtered. The SMS message is available to these apps after the delay.

Certain apps such as the default SMS assistant app, connected device companion apps, etc., are exempted from this delay. All apps that rely on reading SMS messages for OTP extraction should transition to using SMS Retriever or SMS User Consent APIs to ensure continued functionality.

الأمان

يقدّم Android 17 التحسينات التالية على أمان الأجهزة والتطبيقات.

أمان النشاط

In Android 17, the platform continues its shift toward a "secure-by-default" architecture, introducing a suite of enhancements designed to mitigate high-severity exploits such as phishing, interaction hijacking, and confused deputy attacks. This update requires developers to explicitly opt in to new security standards to maintain app compatibility and user protection.

Key impacts for developers include:

  • BAL hardening & improved opt-in: We are refining Background Activity Launch (BAL) restrictions by extending protections to IntentSender. Developers must migrate away from the legacy MODE_BACKGROUND_ACTIVITY_START_ALLOWED constant. Instead, you should adopt granular controls like MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE, which restricts activity starts to scenarios where the calling app is visible, significantly reducing the attack surface.
  • Adoption tools: Developers should utilize strict mode and updated lint checks to identify legacy patterns and ensure readiness for future target SDK requirements.

تفعيل شفافية الشهادة تلقائيًا

إذا كان التطبيق يستهدف الإصدار 17 من نظام التشغيل Android (المستوى 37 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، يتم تفعيل ميزة شفافية الشهادات (CT) تلقائيًا. (في Android 16، تتوفّر ميزة "الشفافية في الشهادات"، ولكن كان على التطبيقات الموافقة على استخدامها).

Safer Native DCL—C

إذا كان تطبيقك يستهدف الإصدار 17 من نظام التشغيل Android (المستوى 37 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، فإنّ ميزة "الحماية الأكثر أمانًا لتحميل الرموز البرمجية الديناميكية" التي تم تقديمها في الإصدار 14 من نظام التشغيل Android لملفات DEX وJAR تمتد الآن لتشمل المكتبات المجمّعة من رموز برمجية أصلية.

يجب وضع علامة "للقراءة فقط" على جميع الملفات الأصلية التي يتم تحميلها باستخدام System.load(). وإلا، سيعرض النظام UnsatisfiedLinkError.

ننصح بأن تتجنّب التطبيقات تحميل الرموز البرمجية ديناميكيًا كلما أمكن ذلك، لأنّ ذلك يزيد بشكل كبير من خطر اختراق التطبيق من خلال حقن الرموز البرمجية أو التلاعب بها.

تقييد حقول معلومات تحديد الهوية الشخصية في عرض بيانات CP2

بالنسبة إلى التطبيقات التي تستهدف الإصدار 17 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 37) والإصدارات الأحدث، يفرض مقدِّم جهات الاتصال 2 (CP2) قيودًا على بعض الأعمدة التي تحتوي على معلومات تكشف الهوية الشخصية (PII) في عرض البيانات. عند تفعيل هذا التغيير، تتم إزالة هذه الأعمدة من عرض البيانات لتعزيز خصوصية المستخدم. تشمل الأعمدة المحظورة ما يلي:

يمكن للتطبيقات التي تستخدم هذه الأعمدة من ContactsContract.Data استخراجها من ContactsContract.RawContacts بدلاً من ذلك، من خلال الانضمام إلى RAW_CONTACT_ID.

فرض عمليات تحقّق صارمة من SQL في CP2

For apps targeting Android 17 (API level 37) and higher, Contacts Provider 2 (CP2) enforces strict SQL query validation when the ContactsContract.Data table is accessed without READ_CONTACTS permission.

With this change, if an app doesn't have READ_CONTACTS permission, StrictColumns and StrictGrammar options are set when querying the ContactsContract.Data table. If a query uses a pattern that isn't compatible with these, it will be rejected and cause an exception to be thrown.

Intelligence

يتضمّن Android 17 التغييرات التالية على ذكاء النظام.

إيقاف setContentCaptureEnabled نهائيًا

يتم تفعيل ميزة "التقاط المحتوى" تلقائيًا على أجهزة معيّنة للسماح لميزات تستخدم الذكاء الاصطناعي على الجهاز فقط بتحليل محتوى الشاشة لتقديم تجارب ذكية.

اعتبارًا من الإصدار 17 من نظام التشغيل Android، سيتم إيقاف طريقة واجهة برمجة التطبيقات ContentCaptureManager.setContentCaptureEnabled(boolean) نهائيًا. بالنسبة إلى التطبيقات التي تستهدف الإصدار 17 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 37) أو الإصدارات الأحدث، لن يؤدي استدعاء setContentCaptureEnabled(false) إلى إيقاف ميزة "التقاط المحتوى".

إذا كان تطبيقك بحاجة إلى مواصلة إيقاف ميزة "التقاط المحتوى" أو حظر التقاط محتوى الشاشة من قِبل النظام، عليك الانتقال إلى استخدام مَعلمة تنسيق النافذة FLAG_SECURE.

لإيقاف ميزة "التقاط المحتوى"، اضبط العلامة FLAG_SECURE على نافذتك كما هو موضّح في المثال التالي:

Kotlin

window.setFlags(
    WindowManager.LayoutParams.FLAG_SECURE,
    WindowManager.LayoutParams.FLAG_SECURE
)

Java

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_SECURE,
    WindowManager.LayoutParams.FLAG_SECURE
);

لمزيد من التفاصيل، يُرجى الاطّلاع على المستندات المرجعية حول WindowManager.LayoutParams.FLAG_SECURE.

الوسائط

يتضمّن Android 17 التغييرات التالية في سلوك الوسائط.

تعزيز أمان الصوت في الخلفية

اعتبارًا من الإصدار 17 من نظام التشغيل Android، يفرض إطار عمل الصوت قيودًا على التفاعلات الصوتية في الخلفية، بما في ذلك تشغيل الصوت وطلبات التركيز على الصوت وواجهات برمجة التطبيقات لتغيير مستوى الصوت، وذلك لضمان بدء هذه التغييرات عن قصد من قِبل المستخدم.

تنطبق بعض القيود على الصوت في جميع التطبيقات. ومع ذلك، تكون القيود أكثر صرامة إذا كان التطبيق يستهدف Android 17 (المستوى 37 من واجهة برمجة التطبيقات). إذا كان أحد هذه التطبيقات يتفاعل مع الصوت أثناء تشغيله في الخلفية، يجب أن تكون هناك خدمة تعمل في المقدّمة. بالإضافة إلى ذلك، يجب أن يستوفي التطبيق أحد هذين الشرطين أو كليهما:

  • يجب أن تتوفّر في الخدمة التي تعمل في المقدّمة إمكانات "أثناء الاستخدام" (WIU).
  • يجب أن يحصل التطبيق على إذن المنبّه الدقيق وأن يتفاعل مع البث الصوتي USAGE_ALARM.

لمزيد من المعلومات، بما في ذلك استراتيجيات التخفيف من آثار هذه المشكلة، يُرجى الاطّلاع على تعزيز أمان الصوت في الخلفية.

أشكال الأجهزة

يتضمّن Android 17 التغييرات التالية لتحسين تجربة المستخدم على مجموعة من أحجام الأجهزة وأشكالها.

تغييرات في واجهة برمجة التطبيقات الخاصة بالمنصة لتجاهل قيود اتجاه الشاشة وإمكانية تغيير الحجم ونسبة العرض إلى الارتفاع على الشاشات الكبيرة (أصغر عرض يساوي 600 وحدة بكسل مستقلة الكثافة أو أكثر)

We introduced Platform API changes in Android 16 to ignore orientation, resizability, and aspect ratio restrictions on large screens (sw >= 600dp) for apps targeting API level 36 or higher. Developers have the option to opt out of these changes with SDK 36, but this opt-out will no longer be available for apps that target Android 17 (API level 37) or higher.

For more information, see Restrictions on orientation and resizability are ignored.

إمكانية الاتصال

يقدّم Android 17 التغيير التالي لتحسين الاتساق والتوافق مع سلوك Java InputStream العادي لمقابس بلوتوث من نوع RFCOMM.

سلوك ثابت للدالة read()‎ الخاصة بـ BluetoothSocket في RFCOMM

For apps targeting Android 17 (API level 37), the read() method of the InputStream obtained from an RFCOMM-based BluetoothSocket now returns -1 when the socket is closed or the connection is dropped.

This change makes RFCOMM socket behavior consistent with LE CoC sockets and aligns with the standard InputStream.read() documentation, which states that -1 is returned when the end of the stream is reached.

Apps that rely solely on catching an IOException to break out of a read loop may be impacted by this change and should update the BluetoothSocket read loops to explicitly check for a return value of -1. This ensures the loop terminates correctly when the remote device disconnects or the socket is closed. For an example of the recommended implementation, see the code snippet in the Transfer Bluetooth data guide.