تغییرات رفتار: برنامه‌هایی که اندروید 14 یا بالاتر را هدف قرار می‌دهند، تغییرات رفتار: برنامه‌هایی که اندروید 14 یا بالاتر را هدف قرار می‌دهند، تغییرات رفتار: برنامه‌هایی که اندروید 14 یا بالاتر را هدف قرار می‌دهند، تغییرات رفتار: برنامه‌هایی که اندروید 14 یا بالاتر را هدف قرار می‌دهند.

مانند نسخه های قبلی، Android 14 شامل تغییرات رفتاری است که ممکن است بر برنامه شما تأثیر بگذارد. تغییرات رفتاری زیر منحصراً برای برنامه‌هایی اعمال می‌شود که Android 14 (سطح API 34) یا بالاتر را هدف قرار می‌دهند. اگر برنامه شما اندروید 14 یا بالاتر را هدف قرار می دهد، باید برنامه خود را تغییر دهید تا در صورت لزوم از این رفتارها به درستی پشتیبانی کند.

حتماً فهرستی از تغییرات رفتاری را نیز مرور کنید که بر همه برنامه‌های در حال اجرا در Android 14 بدون توجه به targetSdkVersion برنامه تأثیر می‌گذارد.

عملکرد اصلی

انواع خدمات پیش زمینه مورد نیاز است

If your app targets Android 14 (API level 34) or higher, it must specify at least one foreground service type for each foreground service within your app. You should choose a foreground service type that represents your app's use case. The system expects foreground services that have a particular type to satisfy a particular use case.

If a use case in your app isn't associated with any of these types, it's strongly recommended that you migrate your logic to use WorkManager or user-initiated data transfer jobs.

اجرای مجوز BLUETOOTH_CONNECT در آداپتور بلوتوث

Android 14 مجوز BLUETOOTH_CONNECT را هنگام فراخوانی روش BluetoothAdapter getProfileConnectionState() برای برنامه‌هایی که Android 14 (سطح API 34) یا بالاتر را هدف قرار می‌دهند، اعمال می‌کند.

این روش قبلاً به مجوز BLUETOOTH_CONNECT نیاز داشت، اما اجرا نشد. مطمئن شوید که برنامه شما BLUETOOTH_CONNECT را در فایل AndroidManifest.xml برنامه شما همانطور که در قطعه زیر نشان داده شده است، اعلام کرده و بررسی کنید که یک کاربر قبل از تماس با getProfileConnectionState مجوز را داده است .

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

به روز رسانی OpenJDK 17

Android 14 به کار تازه کردن کتابخانه‌های اصلی Android ادامه می‌دهد تا با ویژگی‌های جدیدترین نسخه OpenJDK LTS، از جمله به‌روزرسانی‌های کتابخانه و پشتیبانی از زبان جاوا 17 برای توسعه‌دهندگان برنامه‌ها و پلت‌فرم‌ها، هماهنگ شود.

تعدادی از این تغییرات می تواند بر سازگاری برنامه تأثیر بگذارد:

  • تغییرات در عبارات منظم : ارجاعات گروه نامعتبر اکنون مجاز نیستند تا معنایی OpenJDK را با دقت بیشتری دنبال کنند. ممکن است موارد جدیدی را مشاهده کنید که در آن یک IllegalArgumentException توسط کلاس java.util.regex.Matcher پرتاب می شود، بنابراین مطمئن شوید که برنامه خود را برای مناطقی که از عبارات منظم استفاده می کنند آزمایش کنید. برای فعال یا غیرفعال کردن این تغییر در حین آزمایش، پرچم DISALLOW_INVALID_GROUP_REFERENCE را با استفاده از ابزارهای چارچوب سازگاری تغییر دهید.
  • مدیریت UUID : متد java.util.UUID.fromString() اکنون بررسی های دقیق تری را هنگام تأیید آرگومان ورودی انجام می دهد، بنابراین ممکن است در حین deserialization یک IllegalArgumentException را مشاهده کنید. برای فعال یا غیرفعال کردن این تغییر در حین آزمایش، پرچم ENABLE_STRICT_VALIDATION را با استفاده از ابزارهای چارچوب سازگاری تغییر دهید.
  • مشکلات ProGuard : در برخی موارد، افزودن کلاس java.lang.ClassValue باعث ایجاد مشکل می شود اگر بخواهید برنامه خود را با استفاده از ProGuard کوچک کنید، مبهم کنید و بهینه کنید. مشکل از یک کتابخانه Kotlin سرچشمه می گیرد که رفتار زمان اجرا را بر اساس اینکه Class.forName("java.lang.ClassValue") یک کلاس را برمی گرداند یا نه، تغییر می دهد. اگر برنامه شما بر اساس نسخه قدیمی‌تری از زمان اجرا بدون کلاس java.lang.ClassValue در دسترس است، این بهینه‌سازی‌ها ممکن است متد computeValue را از کلاس‌های مشتق‌شده از java.lang.ClassValue حذف کنند.

JobScheduler رفتار برگشت به تماس و شبکه را تقویت می کند

Since its introduction, JobScheduler expects your app to return from onStartJob or onStopJob within a few seconds. Prior to Android 14, if a job runs too long, the job is stopped and fails silently. If your app targets Android 14 (API level 34) or higher and exceeds the granted time on the main thread, the app triggers an ANR with the error message "No response to onStartJob" or "No response to onStopJob".

This ANR may be a result of 2 scenarios: 1. There is work blocking the main thread, preventing the callbacks onStartJob or onStopJob from executing and completing within the expected time limit. 2. The developer is running blocking work within the JobScheduler callback onStartJob or onStopJob, preventing the callback from completing within the expected time limit.

To address #1, you will need to further debug what is blocking the main thread when the ANR occurs, you can do this using ApplicationExitInfo#getTraceInputStream() to get the tombstone trace when the ANR occurs. If you're able to manually reproduce the ANR, you can record a system trace and inspect the trace using either Android Studio or Perfetto to better understand what is running on the main thread when the ANR occurs. Note that this can happen when using JobScheduler API directly or using the androidx library WorkManager.

To address #2, consider migrating to WorkManager, which provides support for wrapping any processing in onStartJob or onStopJob in an asynchronous thread.

JobScheduler also introduces a requirement to declare the ACCESS_NETWORK_STATE permission if using setRequiredNetworkType or setRequiredNetwork constraint. If your app does not declare the ACCESS_NETWORK_STATE permission when scheduling the job and is targeting Android 14 or higher, it will result in a SecurityException.

کاشی‌ها API را راه‌اندازی می‌کنند

For apps targeting 14 and higher, TileService#startActivityAndCollapse(Intent) is deprecated and now throws an exception when called. If your app launches activities from tiles, use TileService#startActivityAndCollapse(PendingIntent) instead.

حریم خصوصی

دسترسی جزئی به عکس ها و فیلم ها

Android 14 introduces Selected Photos Access, which allows users to grant apps access to specific images and videos in their library, rather than granting access to all media of a given type.

This change is only enabled if your app targets Android 14 (API level 34) or higher. If you don't use the photo picker yet, we recommend implementing it in your app to provide a consistent experience for selecting images and videos that also enhances user privacy without having to request any storage permissions.

If you maintain your own gallery picker using storage permissions and need to maintain full control over your implementation, adapt your implementation to use the new READ_MEDIA_VISUAL_USER_SELECTED permission. If your app doesn't use the new permission, the system runs your app in a compatibility mode.

تجربه کاربری

اعلان‌های Intent تمام صفحه را ایمن کنید

با Android 11 (سطح API 30)، برای هر برنامه ای امکان استفاده از Notification.Builder.setFullScreenIntent برای ارسال اهداف تمام صفحه در حالی که گوشی قفل است وجود داشت. می‌توانید با اعلام مجوز USE_FULL_SCREEN_INTENT در AndroidManifest، این را در نصب برنامه به طور خودکار اعطا کنید.

اعلان‌های تمام صفحه برای اعلان‌های با اولویت بسیار طراحی شده‌اند که توجه فوری کاربر را می‌طلبد، مانند تماس تلفنی دریافتی یا تنظیمات ساعت زنگ دار که توسط کاربر پیکربندی شده است. برای برنامه‌هایی که Android 14 (سطح API 34) یا بالاتر را هدف قرار می‌دهند، برنامه‌هایی که مجاز به استفاده از این مجوز هستند محدود به برنامه‌هایی هستند که فقط تماس و زنگ هشدار ارائه می‌کنند. فروشگاه Google Play مجوزهای USE_FULL_SCREEN_INTENT پیش‌فرض را برای هر برنامه‌ای که با این نمایه مطابقت ندارد لغو می‌کند. مهلت این تغییرات خط مشی 31 مه 2024 است.

این مجوز برای برنامه‌های نصب‌شده روی تلفن قبل از به‌روزرسانی کاربر به Android 14 فعال باقی می‌ماند. کاربران می‌توانند این مجوز را روشن و خاموش کنند.

می توانید از API جدید NotificationManager.canUseFullScreenIntent استفاده کنید تا بررسی کنید که آیا برنامه شما مجوز دارد یا خیر. در غیر این صورت، برنامه شما می‌تواند از هدف جدید ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT برای راه‌اندازی صفحه تنظیمات استفاده کند که در آن کاربران می‌توانند مجوز را صادر کنند.

امنیت

محدودیت برای مقاصد ضمنی و معلق

For apps targeting Android 14 (API level 34) or higher, Android restricts apps from sending implicit intents to internal app components in the following ways:

  • Implicit intents are only delivered to exported components. Apps must either use an explicit intent to deliver to unexported components, or mark the component as exported.
  • If an app creates a mutable pending intent with an intent that doesn't specify a component or package, the system throws an exception.

These changes prevent malicious apps from intercepting implicit intents that are intended for use by an app's internal components.

For example, here is an intent filter that could be declared in your app's manifest file:

<activity
    android:name=".AppActivity"
    android:exported="false">
    <intent-filter>
        <action android:name="com.example.action.APP_ACTION" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

If your app tried to launch this activity using an implicit intent, an ActivityNotFoundException exception would be thrown:

Kotlin

// Throws an ActivityNotFoundException exception when targeting Android 14.
context.startActivity(Intent("com.example.action.APP_ACTION"))

Java

// Throws an ActivityNotFoundException exception when targeting Android 14.
context.startActivity(new Intent("com.example.action.APP_ACTION"));

To launch the non-exported activity, your app should use an explicit intent instead:

Kotlin

// This makes the intent explicit.
val explicitIntent =
        Intent("com.example.action.APP_ACTION")
explicitIntent.apply {
    package = context.packageName
}
context.startActivity(explicitIntent)

Java

// This makes the intent explicit.
Intent explicitIntent =
        new Intent("com.example.action.APP_ACTION")
explicitIntent.setPackage(context.getPackageName());
context.startActivity(explicitIntent);

گیرنده های پخش ثبت شده در زمان اجرا باید رفتار صادراتی را مشخص کنند

برنامه‌ها و سرویس‌هایی که Android 14 (سطح API 34) یا بالاتر را هدف قرار می‌دهند و از گیرنده‌های ثبت شده در زمینه استفاده می‌کنند، باید پرچمی را مشخص کنند تا نشان دهد گیرنده باید به همه برنامه‌های دیگر دستگاه صادر شود یا نه: به ترتیب RECEIVER_EXPORTED یا RECEIVER_NOT_EXPORTED . . این نیاز به محافظت از برنامه‌ها در برابر آسیب‌پذیری‌های امنیتی با استفاده از ویژگی‌های این گیرنده‌های معرفی‌شده در Android 13 کمک می‌کند.

استثنا برای گیرنده هایی که فقط پخش سیستم را دریافت می کنند

اگر برنامه شما فقط برای پخش‌های سیستمی از طریق روش‌های Context#registerReceiver ، مانند Context#registerReceiver() یک گیرنده را ثبت می‌کند، پس نباید هنگام ثبت گیرنده پرچمی را مشخص کند.

بارگیری کد پویا ایمن تر

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

اگر باید کد را به صورت پویا بارگیری کنید، از روش زیر استفاده کنید تا فایل بارگذاری شده پویا (مانند فایل DEX، JAR، یا APK) را به‌محض باز شدن فایل و قبل از نوشتن هر محتوایی فقط خواندنی تنظیم کنید:

کاتلین

val jar = File("DYNAMICALLY_LOADED_FILE.jar")
val os = FileOutputStream(jar)
os.use {
    // Set the file to read-only first to prevent race conditions
    jar.setReadOnly()
    // Then write the actual file content
}
val cl = PathClassLoader(jar, parentClassLoader)

جاوا

File jar = new File("DYNAMICALLY_LOADED_FILE.jar");
try (FileOutputStream os = new FileOutputStream(jar)) {
    // Set the file to read-only first to prevent race conditions
    jar.setReadOnly();
    // Then write the actual file content
} catch (IOException e) { ... }
PathClassLoader cl = new PathClassLoader(jar, parentClassLoader);

مدیریت فایل‌های بارگذاری شده پویا که از قبل وجود دارند

برای جلوگیری از ایجاد استثنا برای فایل‌های موجود که به صورت پویا بارگذاری شده‌اند، توصیه می‌کنیم قبل از بارگیری مجدد آنها به صورت پویا در برنامه خود، فایل‌ها را حذف و دوباره ایجاد کنید. همانطور که فایل ها را دوباره ایجاد می کنید، دستورالعمل های قبلی را برای علامت گذاری فایل ها به صورت فقط خواندنی در زمان نوشتن دنبال کنید. همچنین، می‌توانید فایل‌های موجود را دوباره به‌عنوان فقط خواندنی برچسب‌گذاری کنید، اما در این مورد، اکیداً توصیه می‌کنیم که ابتدا یکپارچگی فایل‌ها را تأیید کنید (مثلاً با بررسی امضای فایل در برابر یک مقدار قابل اعتماد)، برای کمک به محافظت برنامه شما از اقدامات مخرب

محدودیت های اضافی برای شروع فعالیت ها از پس زمینه

برای برنامه‌هایی که Android 14 (سطح API 34) یا بالاتر را هدف قرار می‌دهند، سیستم زمانی را محدود می‌کند که برنامه‌ها مجاز به شروع فعالیت‌ها از پس‌زمینه باشند:

  • وقتی یک برنامه با استفاده از PendingIntent#send() یا روش‌های مشابه، یک PendingIntent ارسال می‌کند، اگر برنامه می‌خواهد امتیازات راه‌اندازی فعالیت پس‌زمینه خود را برای شروع هدف معلق اعطا کند، باید آن را انتخاب کند. برای شرکت کردن، برنامه باید یک بسته ActivityOptions با setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED) ارسال کند.
  • هنگامی که یک برنامه قابل مشاهده، سرویس برنامه دیگری را که در پس‌زمینه است با استفاده از روش bindService() متصل می‌کند، برنامه قابل مشاهده اگر می‌خواهد امتیازات راه‌اندازی فعالیت پس‌زمینه خود را به سرویس محدود اعطا کند، اکنون باید شرکت کند. برای شرکت کردن، برنامه باید هنگام فراخوانی متد bindService() پرچم BIND_ALLOW_ACTIVITY_STARTS را داشته باشد.

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

پیمایش مسیر زیپ

For apps targeting Android 14 (API level 34) or higher, Android prevents the Zip Path Traversal Vulnerability in the following way: ZipFile(String) and ZipInputStream.getNextEntry() throws a ZipException if zip file entry names contain ".." or start with "/".

Apps can opt-out from this validation by calling dalvik.system.ZipPathValidator.clearCallback().

برای برنامه‌هایی که Android 14 (سطح API 34) یا بالاتر را هدف قرار می‌دهند، یک SecurityException توسط MediaProjection#createVirtualDisplay در یکی از سناریوهای زیر ایجاد می‌شود:

برنامه شما باید قبل از هر جلسه عکسبرداری از کاربر بخواهد رضایت بدهد. یک جلسه ضبط یک فراخوانی واحد در MediaProjection#createVirtualDisplay است و هر نمونه MediaProjection باید فقط یک بار استفاده شود.

کنترل تغییرات پیکربندی

اگر برنامه شما نیاز به فراخوانی MediaProjection#createVirtualDisplay برای مدیریت تغییرات پیکربندی دارد (مانند تغییر جهت صفحه یا اندازه صفحه)، می‌توانید این مراحل را برای به‌روزرسانی VirtualDisplay برای نمونه MediaProjection موجود دنبال کنید:

  1. VirtualDisplay#resize کنید.
  2. یک Surface جدید با عرض و ارتفاع جدید VirtualDisplay#setSurface ارائه دهید.

پاسخ تماس را ثبت کنید

برنامه شما باید برای رسیدگی به مواردی که کاربر برای ادامه جلسه ضبط رضایت نمی دهد، یک تماس پاسخ ثبت کند. برای انجام این کار، Callback#onStop را پیاده سازی کنید و از برنامه خود بخواهید منابع مرتبط (مانند VirtualDisplay و Surface ) را منتشر کند.

اگر برنامه شما این پاسخ تماس را ثبت نکند، MediaProjection#createVirtualDisplay هنگامی که برنامه شما آن را فراخوانی می کند، یک IllegalStateException ایجاد می کند.

محدودیت‌های غیر SDK به‌روزرسانی شد

Android 14 شامل لیست های به روز شده از رابط های غیر SDK محدود شده بر اساس همکاری با توسعه دهندگان اندروید و آخرین آزمایش داخلی است. در صورت امکان، قبل از اینکه رابط‌های غیر SDK را محدود کنیم، مطمئن می‌شویم که جایگزین‌های عمومی در دسترس هستند.

اگر برنامه شما اندروید 14 را هدف قرار نمی دهد، برخی از این تغییرات ممکن است فوراً روی شما تأثیر نگذارند. با این حال، در حالی که در حال حاضر می‌توانید از برخی رابط‌های غیر SDK ( بسته به سطح API هدف برنامه‌تان ) استفاده کنید، استفاده از هر روش یا فیلد غیر SDK همیشه خطر شکستن برنامه شما را بالا می‌برد.

اگر مطمئن نیستید که برنامه شما از رابط های غیر SDK استفاده می کند، می توانید برنامه خود را آزمایش کنید تا متوجه شوید. اگر برنامه شما به رابط‌های غیر SDK متکی است، باید برنامه‌ریزی برای انتقال به جایگزین‌های SDK را شروع کنید. با این وجود، می‌دانیم که برخی از برنامه‌ها دارای موارد استفاده معتبر برای استفاده از رابط‌های غیر SDK هستند. اگر نمی توانید جایگزینی برای استفاده از یک رابط غیر SDK برای یک ویژگی در برنامه خود پیدا کنید، باید یک API عمومی جدید درخواست کنید .

To learn more about the changes in this release of Android, see Updates to non-SDK interface restrictions in Android 14. To learn more about non-SDK interfaces generally, see Restrictions on non-SDK interfaces.