व्यवहार में बदलाव: Android 14 या उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन

पिछली रिलीज़ की तरह, Android 14 में भी कुछ ऐसे बदलाव किए गए हैं जिनका असर आपके ऐप्लिकेशन पर पड़ सकता है. यहां दिए गए बदलाव, सिर्फ़ उन ऐप्लिकेशन पर लागू होते हैं जो Android 14 (एपीआई लेवल 34) या इसके बाद के वर्शन को टारगेट कर रहे हैं. अगर आपका ऐप्लिकेशन, Android 14 या उसके बाद के वर्शन को टारगेट कर रहा है, तो आपको अपने ऐप्लिकेशन में बदलाव करना चाहिए, ताकि वह इन व्यवहारों को ठीक से सपोर्ट कर सके. हालांकि, यह बदलाव सिर्फ़ उन मामलों में करना होगा जहां यह लागू होता है.

Android 14 पर काम करने वाले सभी ऐप्लिकेशन पर असर डालने वाले बदलावों की सूची भी ज़रूर देखें. इससे कोई फ़र्क़ नहीं पड़ता कि ऐप्लिकेशन का targetSdkVersion क्या है.

मुख्य फ़ंक्शन

फ़ोरग्राउंड सेवा के टाइप की जानकारी देना ज़रूरी है

अगर आपका ऐप्लिकेशन Android 14 (एपीआई लेवल 34) या उसके बाद के वर्शन को टारगेट करता है, तो उसे अपने ऐप्लिकेशन में मौजूद हर फ़ोरग्राउंड सेवा के लिए, कम से कम एक फ़ोरग्राउंड सेवा टाइप की जानकारी देनी होगी. आपको फ़ोरग्राउंड सेवा का ऐसा टाइप चुनना चाहिए जो आपके ऐप्लिकेशन के इस्तेमाल के उदाहरण के बारे में बताता हो. सिस्टम को उम्मीद है कि किसी खास तरह की फ़ोरग्राउंड सेवाएं, इस्तेमाल के किसी खास उदाहरण के हिसाब से काम करेंगी.

अगर आपके ऐप्लिकेशन का कोई इस्तेमाल का उदाहरण, इनमें से किसी भी टाइप से जुड़ा नहीं है, तो हमारा सुझाव है कि आप अपने लॉजिक को WorkManager या उपयोगकर्ता के शुरू किए गए डेटा ट्रांसफ़र जॉब का इस्तेमाल करने के लिए माइग्रेट करें.

BluetoothAdapter में BLUETOOTH_CONNECT अनुमति लागू करना

Android 14 (एपीआई लेवल 34) या उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, BluetoothAdapter getProfileConnectionState() तरीके को कॉल करते समय Android 14, BLUETOOTH_CONNECT अनुमति को लागू करता है.

इस तरीके के लिए BLUETOOTH_CONNECT अनुमति की ज़रूरत पहले से ही थी. हालांकि, ऐसा करना ज़रूरी नहीं किया गया. पक्का करें कि आपके ऐप्लिकेशन की AndroidManifest.xml फ़ाइल में, BLUETOOTH_CONNECT के बारे में जानकारी दी गई हो. यह जानकारी, यहां दिए गए स्निपेट में दिखाई गई है. साथ ही, getProfileConnectionState को कॉल करने से पहले, देख लें कि उपयोगकर्ता ने अनुमति दी है या नहीं.

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

OpenJDK 17 के अपडेट

Android 14 में, Android की मुख्य लाइब्रेरी को अपडेट करने की प्रोसेस जारी है, ताकि इसे OpenJDK LTS के नए वर्शन की सुविधाओं के साथ अलाइन किया जा सके. इसमें, ऐप्लिकेशन और प्लैटफ़ॉर्म डेवलपर के लिए, लाइब्रेरी के अपडेट और Java 17 भाषा की सहायता, दोनों शामिल हैं.

इनमें से कुछ बदलावों का असर, ऐप्लिकेशन के साथ काम करने की सुविधा पर पड़ सकता है:

  • रेगुलर एक्सप्रेशन में बदलाव: OpenJDK के सेमेंटेक्स को ज़्यादा बारीकी से फ़ॉलो करने के लिए, अब अमान्य ग्रुप रेफ़रंस का इस्तेमाल करने की अनुमति नहीं है. आपको ऐसे नए मामले दिख सकते हैं जहां java.util.regex.Matcher क्लास से IllegalArgumentException ट्रिगर होता है. इसलिए, रेगुलर एक्सप्रेशन का इस्तेमाल करने वाले हिस्सों के लिए, अपने ऐप्लिकेशन की जांच करना न भूलें. जांच के दौरान इस बदलाव को चालू या बंद करने के लिए, कंपैटिबिलिटी फ़्रेमवर्क टूल का इस्तेमाल करके, DISALLOW_INVALID_GROUP_REFERENCE फ़्लैग को टॉगल करें.
  • यूनीक आइडेंटिफ़ायर (यूयूआईडी) मैनेज करना: java.util.UUID.fromString() तरीका अब इनपुट आर्ग्युमेंट की पुष्टि करते समय, ज़्यादा सख्त जांच करता है. इसलिए, आपको डेसिरियलाइज़ेशन के दौरान IllegalArgumentException दिख सकता है. टेस्टिंग के दौरान इस बदलाव को चालू या बंद करने के लिए, साथ काम करने की सुविधा वाले फ़्रेमवर्क टूल का इस्तेमाल करके, ENABLE_STRICT_VALIDATION फ़्लैग को टॉगल करें.
  • ProGuard से जुड़ी समस्याएं: कुछ मामलों में, ProGuard का इस्तेमाल करके अपने ऐप्लिकेशन को छोटा करने, उसे कोड करने, और ऑप्टिमाइज़ करने पर, java.lang.ClassValue क्लास जोड़ने से समस्या आ सकती है. यह समस्या, Kotlin की एक लाइब्रेरी की वजह से होती है. यह लाइब्रेरी, Class.forName("java.lang.ClassValue") के क्लास दिखाने या न दिखाने के आधार पर, रनटाइम के व्यवहार में बदलाव करती है. अगर आपका ऐप्लिकेशन, रनटाइम के पुराने वर्शन के लिए डेवलप किया गया था और उसमें java.lang.ClassValue क्लास उपलब्ध नहीं थी, तो इन ऑप्टिमाइज़ेशन की वजह से java.lang.ClassValue से ली गई क्लास से computeValue तरीका हट सकता है.

JobScheduler, कॉलबैक और नेटवर्क के व्यवहार को बेहतर बनाता है

शुरुआत के बाद से, JobScheduler को उम्मीद है कि आपका ऐप्लिकेशन onStartJob या onStopJob कुछ सेकंड में. Android 14 से पहले के वर्शन अगर कोई काम ज़्यादा समय तक चलता है, तो काम रुक जाता है और बिना किसी आवाज़ के पूरा नहीं हो पाता. अगर आपका ऐप्लिकेशन Android 14 (एपीआई लेवल 34) या उसके बाद के वर्शन को टारगेट करता है और मुख्य थ्रेड पर तय समय से ज़्यादा समय लेता है, तो ऐप्लिकेशन "onStartJob पर कोई जवाब नहीं" या "onStopJob पर कोई जवाब नहीं" गड़बड़ी मैसेज के साथ एएनआर को ट्रिगर करता है.

यह ANR, इन दो स्थितियों की वजह से हो सकता है: 1. मुख्य थ्रेड को ब्लॉक करने वाला कोई काम है, जिसकी वजह से कॉलबैक onStartJob या onStopJob तय समयसीमा के अंदर लागू नहीं हो पा रहे हैं और पूरे नहीं हो पा रहे हैं. 2. डेवलपर JobScheduler में ब्लॉक करने का काम चला रहा है onStartJob या onStopJob कॉलबैक, जो कॉलबैक को रोक रहा है तय समयसीमा में पूरा हो जाता है.

#1 को ठीक करने के लिए, आपको यह पता लगाना होगा कि एएनआर होने पर मुख्य थ्रेड को क्या ब्लॉक कर रहा है. एएनआर होने पर टॉम्बस्टोन ट्रैक पाने के लिए, ApplicationExitInfo#getTraceInputStream() का इस्तेमाल करें. अगर एएनआर को मैन्युअल तरीके से दोहराया जा सकता है, तो सिस्टम ट्रेस रिकॉर्ड किया जा सकता है. साथ ही, Android Studio या Perfetto का इस्तेमाल करके, ट्रेस की जांच की जा सकती है. इससे यह बेहतर तरीके से समझा जा सकता है कि एएनआर होने पर मुख्य थ्रेड पर क्या चल रहा है. ध्यान दें कि यह सीधे तौर पर JobScheduler API का इस्तेमाल करने या androidx लाइब्रेरी WorkManager का इस्तेमाल करने पर हो सकता है.

#2 को ठीक करने के लिए, WorkManager पर माइग्रेट करें. यह प्लैटफ़ॉर्म onStartJob या onStopJob में किसी भी प्रोसेसिंग को रैप करने के लिए सहायता एसिंक्रोनस थ्रेड में है.

JobScheduler में, setRequiredNetworkType या setRequiredNetwork कंस्ट्रेंट का इस्तेमाल करने पर, ACCESS_NETWORK_STATE अनुमति का एलान करने की ज़रूरत भी शामिल की गई है. अगर आपका ऐप्लिकेशन, टास्क शेड्यूल करते समय ACCESS_NETWORK_STATE अनुमति का एलान नहीं करता है और Android 14 या उसके बाद के वर्शन को टारगेट करता है, तो आपको SecurityException दिखेगा.

Tiles Launch API

14 साल और उससे ज़्यादा उम्र के लोगों को टारगेट करने वाले ऐप्लिकेशन के लिए, TileService#startActivityAndCollapse(Intent) के इस्तेमाल पर रोक लगा दी गई है और अब यह गड़बड़ी कर रहा है एक अपवाद हो सकता है. अगर आपका ऐप्लिकेशन टाइल से गतिविधियां लॉन्च करता है, तो इस्तेमाल करें इसके बजाय, TileService#startActivityAndCollapse(PendingIntent) का इस्तेमाल करें.

निजता

फ़ोटो और वीडियो का सीमित ऐक्सेस

Android 14 में, चुनिंदा फ़ोटो का ऐक्सेस देने की सुविधा जोड़ी गई है. इसकी मदद से, उपयोगकर्ता किसी खास तरह के सभी मीडिया का ऐक्सेस देने के बजाय, ऐप्लिकेशन को अपनी लाइब्रेरी में मौजूद चुनिंदा फ़ोटो और वीडियो का ऐक्सेस दे सकते हैं.

यह बदलाव सिर्फ़ तब चालू होता है, जब आपका ऐप्लिकेशन Android 14 (एपीआई लेवल 34) या उसके बाद के वर्शन को टारगेट करता है. अगर आपने अब तक फ़ोटो पिकर का इस्तेमाल नहीं किया है, तो हमारा सुझाव है कि आप इसे अपने ऐप्लिकेशन में लागू करें. इससे, उपयोगकर्ताओं को इमेज और वीडियो चुनने का बेहतर अनुभव मिलेगा. साथ ही, स्टोरेज से जुड़ी अनुमतियों का अनुरोध किए बिना, उपयोगकर्ता की निजता को भी बेहतर बनाया जा सकेगा.

अगर आपने स्टोरेज की अनुमतियों का इस्तेमाल करके, अपना गैलरी पिकर बनाया है और आपको इसे लागू करने पर पूरा कंट्रोल रखना है, तो नई READ_MEDIA_VISUAL_USER_SELECTED अनुमति का इस्तेमाल करने के लिए, अपने ऐप्लिकेशन को लागू करने के तरीके में बदलाव करें. अगर आपका ऐप्लिकेशन नई अनुमति का इस्तेमाल नहीं करता है, तो सिस्टम आपके ऐप्लिकेशन को काम करने के तरीके के हिसाब से बनाए गए मोड में चलाता है.

उपयोगकर्ता अनुभव

फ़ुल-स्क्रीन पर सूचनाएं दिखाने के सुरक्षित तरीके

With Android 11 (API level 30), it was possible for any app to use Notification.Builder.setFullScreenIntent to send full-screen intents while the phone is locked. You could auto-grant this on app install by declaring USE_FULL_SCREEN_INTENT permission in the AndroidManifest.

Full-screen intent notifications are designed for extremely high-priority notifications demanding the user's immediate attention, such as an incoming phone call or alarm clock settings configured by the user. For apps targeting Android 14 (API level 34) or higher, apps that are allowed to use this permission are limited to those that provide calling and alarms only. The Google Play Store revokes default USE_FULL_SCREEN_INTENT permissions for any apps that don't fit this profile. The deadline for these policy changes is May 31, 2024.

This permission remains enabled for apps installed on the phone before the user updates to Android 14. Users can turn this permission on and off.

You can use the new API NotificationManager.canUseFullScreenIntent to check if your app has the permission; if not, your app can use the new intent ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT to launch the settings page where users can grant the permission.

सुरक्षा

इंप्लिसिट और लंबित इंटेंट पर पाबंदियां

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 (एपीआई लेवल 34) या उसके बाद के वर्शन को टारगेट करने वाले और कॉन्टेक्स्ट के हिसाब से रजिस्टर किए गए रिसीवर का इस्तेमाल करने वाले ऐप्लिकेशन और सेवाओं को एक फ़्लैग तय करना होगा. इससे यह पता चलता है कि रिसीवर को डिवाइस पर मौजूद अन्य सभी ऐप्लिकेशन में एक्सपोर्ट किया जाना चाहिए या नहीं. इसके लिए, RECEIVER_EXPORTED या RECEIVER_NOT_EXPORTED में से कोई एक विकल्प चुना जा सकता है. इस ज़रूरी शर्त से, Android 13 में इन रिसीवर के लिए उपलब्ध सुविधाओं का फ़ायदा उठाकर, ऐप्लिकेशन को सुरक्षा से जुड़ी जोखिम से बचाने में मदद मिलती है.

सिर्फ़ सिस्टम ब्रॉडकास्ट पाने वाले लोगों के लिए अपवाद

अगर आपका ऐप्लिकेशन सिर्फ़ सिस्टम ब्रॉडकास्ट के लिए, Context#registerReceiver() जैसे Context#registerReceiver तरीकों से रिसीवर रजिस्टर कर रहा है, तो उसे रिसीवर रजिस्टर करते समय कोई फ़्लैग नहीं देना चाहिए.

डाइनैमिक कोड को ज़्यादा सुरक्षित तरीके से लोड करना

अगर आपका ऐप्लिकेशन Android 14 (एपीआई लेवल 34) या उसके बाद के वर्शन को टारगेट करता है और डाइनैमिक कोड लोडिंग (डीसीएल) का इस्तेमाल करता है, तो डाइनैमिक तौर पर लोड होने वाली सभी फ़ाइलों को रीड-ओनली के तौर पर मार्क किया जाना चाहिए. ऐसा न होने पर, सिस्टम अपवाद की जानकारी देता है. हमारा सुझाव है कि ऐप्लिकेशन इस्तेमाल करने से बचें डाइनैमिक तौर पर लोड होने वाला कोड जब मुमकिन होता है, क्योंकि ऐसा करने से किसी ऐप्लिकेशन के कोड इंजेक्शन या कोड से छेड़छाड़ करके छेड़छाड़ की गई हो.

अगर आपको डाइनैमिक तौर पर कोड लोड करना पड़ता है, तो नीचे दिए गए तरीके का इस्तेमाल करके डाइनैमिक तौर पर लोड होने वाली फ़ाइल (जैसे कि DEX, JAR या APK फ़ाइल), सिर्फ़ पढ़ने के लिए जैसे ही फ़ाइल खोली जाती है और कॉन्टेंट लिखे जाने से पहले:

Kotlin

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)

Java

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 (एपीआई लेवल 34) या उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, सिस्टम ने बैकग्राउंड से गतिविधियां शुरू करने की अनुमति देने के समय पर और पाबंदी लगाई है:

  • जब कोई ऐप्लिकेशन PendingIntent#send() या मिलते-जुलते तरीकों का इस्तेमाल करके PendingIntent भेजता है, तो उसे ऑप्ट-इन करना होगा. ऐसा इसलिए, ताकि वह बैकग्राउंड में गतिविधि शुरू करने की अनुमतियां दे सके और बाकी बचे इंटेंट को शुरू कर सके. ऑप्ट-इन करने के लिए, ऐप्लिकेशन को setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED) के साथ ActivityOptions बंडल पास करना होगा.
  • जब कोई ऐप्लिकेशन, bindService() तरीके का इस्तेमाल करके, बैकग्राउंड में चल रहे किसी दूसरे ऐप्लिकेशन की सेवा को बांधता है, तो उसे अब ऑप्ट-इन करना होगा. ऐसा तब करना होगा, जब उसे बांधी गई सेवा को बैकग्राउंड में चल रही गतिविधि को लॉन्च करने की अनुमतियां देनी हों. ऑप्ट इन करने के लिए, ऐप्लिकेशन को bindService() तरीके को कॉल करते समय, BIND_ALLOW_ACTIVITY_STARTS फ़्लैग शामिल करना चाहिए.

इन बदलावों से, पाबंदियों के मौजूदा सेट को बढ़ाया गया है. इससे उपयोगकर्ताओं को सुरक्षित रखने के लिए, नुकसान पहुंचाने वाले ऐप्लिकेशन को बैकग्राउंड से परेशान करने वाली गतिविधियां शुरू करने के लिए, एपीआई का गलत इस्तेमाल करने से रोका जा सकेगा.

ज़िप पाथ ट्रेवर्सल

Android 14 (एपीआई लेवल 34) या उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, Android इस तरह से ZIP पाथ ट्रेवर्सल की समस्या को रोकता है: अगर ज़िप फ़ाइल एंट्री के नाम में ".." शामिल है या "/" से शुरू होते हैं, तो ZipFile(String) और ZipInputStream.getNextEntry(), ZipException को दिखाता है.

ऐप्लिकेशन, dalvik.system.ZipPathValidator.clearCallback() को कॉल करके इस पुष्टि से ऑप्ट-आउट कर सकते हैं.

For apps targeting Android 14 (API level 34) or higher, a SecurityException is thrown by MediaProjection#createVirtualDisplay in either of the following scenarios:

Your app must ask the user to give consent before each capture session. A single capture session is a single invocation on MediaProjection#createVirtualDisplay, and each MediaProjection instance must be used only once.

Handle configuration changes

If your app needs to invoke MediaProjection#createVirtualDisplay to handle configuration changes (such as the screen orientation or screen size changing), you can follow these steps to update the VirtualDisplay for the existing MediaProjection instance:

  1. Invoke VirtualDisplay#resize with the new width and height.
  2. Provide a new Surface with the new width and height to VirtualDisplay#setSurface.

Register a callback

Your app should register a callback to handle cases where the user doesn't grant consent to continue a capture session. To do this, implement Callback#onStop and have your app release any related resources (such as the VirtualDisplay and Surface).

If your app doesn't register this callback, MediaProjection#createVirtualDisplay throws an IllegalStateException when your app invokes it.

गैर-एसडीके से जुड़ी पाबंदियां अपडेट की गईं

Android 14 में, पाबंदी वाले गैर-एसडीके इंटरफ़ेस की अपडेट की गई सूचियां शामिल हैं. ये सूचियां, Android डेवलपर के साथ मिलकर काम करने और हाल ही में हुई इंटरनल टेस्टिंग के आधार पर बनाई गई हैं. हम यह पक्का करते हैं कि गैर-एसडीके इंटरफ़ेस को प्रतिबंधित करने से पहले, सार्वजनिक विकल्प उपलब्ध हों.

अगर आपका ऐप्लिकेशन Android 14 को टारगेट नहीं करता है, तो हो सकता है कि इनमें से कुछ बदलावों का असर आप पर तुरंत न पड़े. हालांकि, फ़िलहाल कुछ गैर-एसडीके इंटरफ़ेस (आपके ऐप्लिकेशन के टारगेट एपीआई लेवल के हिसाब से) इस्तेमाल किए जा सकते हैं. हालांकि, किसी भी गैर-एसडीके तरीके या फ़ील्ड का इस्तेमाल करने से, आपके ऐप्लिकेशन के काम न करने का जोखिम हमेशा ज़्यादा होता है.

अगर आपको पक्का नहीं है कि आपका ऐप्लिकेशन, गैर-एसडीके इंटरफ़ेस का इस्तेमाल करता है या नहीं, तो यह पता लगाने के लिए अपने ऐप्लिकेशन की जांच करें. अगर आपका ऐप्लिकेशन, गैर-एसडीके इंटरफ़ेस पर निर्भर करता है, तो आपको एसडीके के विकल्पों पर माइग्रेट करने की योजना बनानी चाहिए. हालांकि, हम समझते हैं कि कुछ ऐप्लिकेशन के पास, गैर-एसडीके इंटरफ़ेस इस्तेमाल करने के लिए मान्य वजहें होती हैं. अगर आपको अपने ऐप्लिकेशन में किसी सुविधा के लिए, गैर-एसडीके इंटरफ़ेस के इस्तेमाल का कोई विकल्प नहीं मिल रहा है, तो आपको नया सार्वजनिक एपीआई का अनुरोध करना चाहिए.

Android के इस रिलीज़ में हुए बदलावों के बारे में ज़्यादा जानने के लिए, Android 14 में, SDK टूल के अलावा अन्य इंटरफ़ेस से जुड़ी पाबंदियों में हुए अपडेट देखें. आम तौर पर, SDK टूल के बाहर के इंटरफ़ेस के बारे में ज़्यादा जानने के लिए, SDK टूल के बाहर के इंटरफ़ेस पर लगी पाबंदियां देखें.