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

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

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

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

Android 15, Android सिस्टम की कई मुख्य सुविधाओं में बदलाव करता है या उन्हें बेहतर बनाता है.

फ़ोरग्राउंड सेवाओं में बदलाव

我们将对 Android 15 中的前台服务进行以下更改。

数据同步前台服务超时行为

Android 15 में, dataSync के लिए टाइम आउट का नया तरीका जोड़ा गया है. यह तरीका, Android 15 (एपीआई लेवल 35) या उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए है. यह व्यवहार, mediaProcessing फ़ोरग्राउंड सेवा के नए टाइप पर भी लागू होता है.

सिस्टम, किसी ऐप्लिकेशन की dataSync सेवाओं को 24 घंटे में कुल छह घंटे तक चलने की अनुमति देता है. इसके बाद, सिस्टम चल रही सेवा के Service.onTimeout(int, int) तरीके को कॉल करता है. इसे Android 15 में लॉन्च किया गया था. इस दौरान, सेवा के पास Service.stopSelf() को कॉल करने के लिए कुछ सेकंड होते हैं. Service.onTimeout() को कॉल करने के बाद, सेवा को फ़ोरग्राउंड सेवा नहीं माना जाता. अगर सेवा Service.stopSelf() को कॉल नहीं करती है, तो सिस्टम में कोई इंटरनल अपवाद दिखता है. अपवाद को Logcat में इस मैसेज के साथ लॉग किया जाता है:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"

इस बदलाव की वजह से होने वाली समस्याओं से बचने के लिए, इनमें से एक या एक से ज़्यादा काम किए जा सकते हैं:

  1. अपनी सेवा में Service.onTimeout(int, int) का नया तरीका लागू करें. जब आपके ऐप्लिकेशन को कॉलबैक मिल जाए, तो stopSelf() को कुछ सेकंड के अंदर कॉल करना न भूलें. (अगर ऐप्लिकेशन को तुरंत नहीं रोका जाता, तो सिस्टम गड़बड़ी जनरेट करता है.)
  2. पक्का करें कि आपके ऐप्लिकेशन की dataSync सेवाएं किसी भी 24 घंटे में कुल छह घंटे से ज़्यादा न चलें (जब तक कि उपयोगकर्ता टाइमर को रीसेट करके ऐप्लिकेशन से इंटरैक्ट न करे).
  3. dataSync फ़ोरग्राउंड सेवाओं को सिर्फ़ उपयोगकर्ता के सीधे इंटरैक्शन के ज़रिए शुरू करें. सेवा शुरू होने पर, आपका ऐप्लिकेशन फ़ोरग्राउंड में होता है. इसलिए, ऐप्लिकेशन के बैकग्राउंड में जाने के बाद भी, आपकी सेवा के पास पूरे छह घंटे होते हैं.
  4. dataSync फ़ोरग्राउंड सेवा का इस्तेमाल करने के बजाय, किसी अन्य एपीआई का इस्तेमाल करें.

अगर आपके ऐप्लिकेशन की dataSync फ़ोरग्राउंड सेवाएं पिछले 24 में छह घंटे तक चली हैं, तो आपके पास dataSync की दूसरी फ़ोरग्राउंड सेवा शुरू करने का विकल्प नहीं है. जब तक उपयोगकर्ता आपके ऐप्लिकेशन को फ़ोरग्राउंड में न ले जाए (इससे टाइमर रीसेट हो जाता है). किसी दूसरी dataSync फ़ोरग्राउंड सेवा को शुरू करने की कोशिश करने पर, सिस्टम ForegroundServiceStartNotAllowedException का गड़बड़ी का मैसेज दिखाता है. जैसे, "फ़ोरग्राउंड सेवा के लिए समयसीमा खत्म हो चुकी है" डेटा सिंक करें.

टेस्ट करना

अपने ऐप्लिकेशन के व्यवहार की जांच करने के लिए, डेटा सिंक टाइम आउट की सुविधा चालू की जा सकती है. भले ही, आपका ऐप्लिकेशन Android 15 को टारगेट न करता हो. हालांकि, यह ज़रूरी है कि ऐप्लिकेशन Android 15 वाले डिवाइस पर चल रहा हो. टाइम आउट की सुविधा चालू करने के लिए, यहां दिया गया adb निर्देश चलाएं:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

टाइम आउट की अवधि में भी बदलाव किया जा सकता है, ताकि यह आसानी से जांचा जा सके कि तय सीमा पूरी होने पर आपका ऐप्लिकेशन कैसा व्यवहार करता है. टाइम आउट की नई अवधि सेट करने के लिए, यह adb कमांड चलाएं:

adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds

新的媒体处理前台服务类型

Android 15 में, फ़ोरग्राउंड सेवा का एक नया टाइप mediaProcessing जोड़ा गया है. यह सेवा टाइप, मीडिया फ़ाइलों को ट्रांसकोड करने जैसे कामों के लिए सही है. उदाहरण के लिए, कोई मीडिया ऐप्लिकेशन किसी ऑडियो फ़ाइल को डाउनलोड कर सकता है और उसे चलाने से पहले, किसी दूसरे फ़ॉर्मैट में बदल सकता है. mediaProcessing फ़ोरग्राउंड सेवा का इस्तेमाल करके, यह पक्का किया जा सकता है कि ऐप्लिकेशन बैकग्राउंड में होने पर भी कन्वर्ज़न जारी रहे.

सिस्टम किसी ऐप्लिकेशन की mediaProcessing सेवाओं को 24 घंटों में कुल छह घंटे चलाने की अनुमति देता है. इसके बाद, सिस्टम, मौजूदा सेवा के Service.onTimeout(int, int) तरीके को कॉल करता है (Android 15 में शुरू किया गया). फ़िलहाल, Service.stopSelf() को कॉल करने के लिए सेवा को कुछ सेकंड मिलेंगे. अगर सेवा Service.stopSelf() को कॉल नहीं करती है, तो सिस्टम में कोई इंटरनल अपवाद दिखता है. अपवाद को Logcat में लॉग इन किया जाता है जिसमें यह मैसेज शामिल है:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"

अपवाद से बचने के लिए, इनमें से कोई एक काम किया जा सकता है:

  1. अपनी सेवा में Service.onTimeout(int, int) का नया तरीका लागू करें. जब आपके ऐप्लिकेशन को कॉलबैक मिलता है, तो कुछ सेकंड के अंदर stopSelf() को कॉल करना न भूलें. (अगर ऐप्लिकेशन को तुरंत नहीं रोका जाता, तो सिस्टम गड़बड़ी जनरेट करता है.)
  2. पक्का करें कि आपके ऐप्लिकेशन की mediaProcessing सेवाएं, 24 घंटे में कुल छह घंटे से ज़्यादा न चलें. ऐसा तब तक नहीं होगा, जब तक उपयोगकर्ता ऐप्लिकेशन के साथ इंटरैक्ट करके, टाइमर को रीसेट नहीं करता.
  3. सीधे उपयोगकर्ता के साथ इंटरैक्शन होने पर ही, mediaProcessing फ़ोरग्राउंड सेवाएं शुरू करें. सेवा शुरू होने के समय, आपका ऐप्लिकेशन फ़ोरग्राउंड में होता है. इसलिए, ऐप्लिकेशन के बैकग्राउंड में चलने के बाद, आपकी सेवा को पूरे छह घंटे तक चालू रखा जाता है.
  4. mediaProcessing फ़ोरग्राउंड सेवा का इस्तेमाल करने के बजाय, WorkManager जैसे अन्य एपीआई का इस्तेमाल करें.

अगर आपके ऐप्लिकेशन की mediaProcessing फ़ोरग्राउंड सेवाएं पिछले 24 में छह घंटों तक चली हैं, तो mediaProcessing फ़ोरग्राउंड सेवा को तब तक शुरू नहीं किया जा सकता, जब तक उपयोगकर्ता आपके ऐप्लिकेशन को फ़ोरग्राउंड में न ले जाए (इससे टाइमर रीसेट हो जाता है). अगर कोई दूसरी mediaProcessing फ़ोरग्राउंड सेवा शुरू करने की कोशिश की जाती है, तो सिस्टम ForegroundServiceStartNotAllowedException को गड़बड़ी का मैसेज दिखाता है. जैसे, "mediaProcessing टाइप की फ़ोरग्राउंड सेवा के लिए, समयसीमा पहले ही खत्म हो चुकी है".

mediaProcessing सेवा टाइप के बारे में ज़्यादा जानकारी के लिए, Android 15 के लिए फ़ोरग्राउंड सेवा टाइप में हुए बदलाव: मीडिया प्रोसेसिंग देखें.

टेस्ट करना

अपने ऐप्लिकेशन के काम करने के तरीके की जांच करने के लिए, मीडिया प्रोसेसिंग के टाइम आउट को चालू किया जा सकता है. भले ही, आपका ऐप्लिकेशन Android 15 को टारगेट न करता हो (जब तक कि ऐप्लिकेशन, Android 15 डिवाइस पर चल रहा हो). टाइम आउट की सुविधा चालू करने के लिए, यह adb कमांड चलाएं:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

टाइम आउट की अवधि में बदलाव भी किया जा सकता है. इससे यह जांचना आसान हो जाता है कि तय सीमा पूरी होने पर, आपका ऐप्लिकेशन कैसे काम करता है. टाइम आउट की नई अवधि सेट करने के लिए, यह adb कमांड चलाएं:

adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds

对启动前台服务的 BOOT_COMPLETED 广播接收器的限制

在启动 BOOT_COMPLETED 广播接收器方面存在新限制 前台服务。BOOT_COMPLETED 接收器能启动 以下类型的前台服务:

如果 BOOT_COMPLETED 接收器尝试启动任何上述类型的前台 服务,系统会抛出 ForegroundServiceStartNotAllowedException

测试

如需测试应用的行为,您可以启用这些新限制,即使您的应用并未以 Android 15 为目标平台(只要应用在 Android 15 设备上运行)也是如此。运行以下 adb 命令:

adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name

如需在不重启设备的情况下发送 BOOT_COMPLETED 广播,请运行以下 adb 命令:

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name

在应用拥有 SYSTEM_ALERT_WINDOW 权限时启动前台服务的限制

पहले, अगर किसी ऐप्लिकेशन के पास SYSTEM_ALERT_WINDOW अनुमति होती थी, तो वह फ़ोरग्राउंड सेवा को लॉन्च कर सकता था. भले ही, वह ऐप्लिकेशन फ़िलहाल बैकग्राउंड में हो. इस बारे में बैकग्राउंड में शुरू करने से जुड़ी पाबंदियों से छूट में बताया गया है.

अगर कोई ऐप्लिकेशन Android 15 को टारगेट करता है, तो अब यह छूट कम हो गई है. ऐप्लिकेशन को अब SYSTEM_ALERT_WINDOW की अनुमति की ज़रूरत होगी. साथ ही, उसमें भी एक दिखने वाला ओवरले विंडो भी होनी चाहिए. इसका मतलब है कि ऐप्लिकेशन को सबसे पहले TYPE_APPLICATION_OVERLAY विंडो लॉन्च करनी होगी और फ़ोरग्राउंड सेवा शुरू करने से पहले, विंडो दिखनी चाहिए.

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

अगर आपका ऐप्लिकेशन SYSTEM_ALERT_WINDOW अनुमति का एलान करता है और बैकग्राउंड से फ़ोरग्राउंड सेवाएं लॉन्च करता है, तो इस बदलाव का उस पर असर पड़ सकता है. अगर आपके ऐप्लिकेशन को ForegroundServiceStartNotAllowedException मिलता है, तो अपने ऐप्लिकेशन के काम करने का क्रम देखें और पक्का करें कि बैकग्राउंड से फ़ोरग्राउंड सेवा शुरू करने से पहले, आपके ऐप्लिकेशन में एक ऐक्टिव ओवरले विंडो हो. View.getWindowVisibility() को कॉल करके, यह देखा जा सकता है कि ओवरले विंडो फ़िलहाल दिख रही है या नहीं. इसके अलावा, View.onWindowVisibilityChanged() को बदलकर, यह भी सेट किया जा सकता है कि ओवरले विंडो दिखने या न दिखने पर सूचना मिलती रहे.

टेस्ट करना

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

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

'परेशान न करें' मोड की ग्लोबल सेटिंग में बदलाव करने की सुविधा को ऐप्लिकेशन के लिए उपलब्ध कराने से जुड़े बदलाव

Android 15 (एपीआई लेवल 35) और उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन, अब किसी डिवाइस पर 'परेशान न करें' (डीएनडी) मोड की ग्लोबल स्थिति या नीति को नहीं बदल सकते. ऐसा, उपयोगकर्ता की सेटिंग में बदलाव करके या डीएनडी मोड को बंद करके नहीं किया जा सकता. इसके बजाय, ऐप्लिकेशन को AutomaticZenRule का योगदान देना होगा. सिस्टम, इस योगदान को सबसे ज़्यादा पाबंदी वाली मौजूदा नीति के साथ मिलाकर, ग्लोबल नीति बनाता है. पहले जिन मौजूदा एपीआई कॉल से ग्लोबल स्टेटस (setInterruptionFilter, setNotificationPolicy) पर असर पड़ा था उनसे, एक 'असहमति' वाला AutomaticZenRule पैरामीटर बनता है या अपडेट होता है. यह पैरामीटर, उन एपीआई कॉल के कॉल-साइकल के हिसाब से टॉगल किया जाता है.

ध्यान दें कि इस बदलाव का असर सिर्फ़ तब पड़ता है, जब ऐप्लिकेशन setInterruptionFilter(INTERRUPTION_FILTER_ALL) को कॉल कर रहा हो और उसे उम्मीद हो कि उस कॉल से, AutomaticZenRule को बंद किया जा सकेगा. AutomaticZenRule को पहले उसके मालिकों ने चालू किया था.

OpenJDK API में हुए बदलाव

Android 15, Android की कोर लाइब्रेरी को रीफ़्रेश करने का काम जारी रखता है, ताकि उन्हें OpenJDK LTS की नई रिलीज़ में मौजूद सुविधाओं के साथ अलाइन किया जा सके.

इनमें से कुछ बदलावों का असर, Android 15 (एपीआई लेवल 35) को टारगेट करने वाले ऐप्लिकेशन की कंपैटिबिलिटी पर पड़ सकता है:

  • स्ट्रिंग फ़ॉर्मैट करने वाले एपीआई में बदलाव: अब String.format() और Formatter.format() एपीआई का इस्तेमाल करते समय, आर्ग्युमेंट इंडेक्स, फ़्लैग, चौड़ाई, और सटीक वैल्यू की पुष्टि ज़्यादा सख्ती से की जाएगी:

    उदाहरण के लिए, जब फ़ॉर्मैट स्ट्रिंग में 0 के आर्ग्युमेंट इंडेक्स (%0) का इस्तेमाल किया जाता है, तो यह अपवाद दिखता है:

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    इस मामले में, फ़ॉर्मैट स्ट्रिंग में %1 का आर्ग्युमेंट इंडेक्स 1 इस्तेमाल करके समस्या को ठीक किया जा सकता है.

  • Arrays.asList(...).toArray() के कॉम्पोनेंट टाइप में बदलाव: Arrays.asList(...).toArray() का इस्तेमाल करने पर, नतीजे के तौर पर मिलने वाले ऐरे का कॉम्पोनेंट टाइप अब Object है. यह, अंडरलाइंग ऐरे के एलिमेंट का टाइप नहीं है. इसलिए, नीचे दिया गया कोड ClassCastException दिखाता है:

    String[] elements = (String[]) Arrays.asList("one", "two").toArray();
    

    इस मामले में, नतीजे के तौर पर मिले ऐरे में String को कॉम्पोनेंट टाइप के तौर पर बनाए रखने के लिए, Collection.toArray(Object[]) का इस्तेमाल किया जा सकता है:

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • भाषा कोड हैंडल करने के तरीके में बदलाव: Locale API का इस्तेमाल करते समय, हिब्रू, येडिश, और इंडोनेशियाई भाषा के कोड अब उनके पुराने फ़ॉर्मैट में नहीं बदले जाएंगे (हिब्रू: iw, येडिश: ji, और इंडोनेशियाई: in). इनमें से किसी एक भाषा के लिए भाषा कोड तय करते समय, आईएसओ 639-1 से कोड इस्तेमाल करें (हिब्रू: he, येडिश: yi, और इंडोनेशियाई: id).

  • रैंडम इंट सीक्वेंसेस में बदलाव: https://bugs.openjdk.org/browse/JDK-8301574 में किए गए बदलावों के बाद, अब Random.ints() तरीके, Random.nextInt() तरीकों की तुलना में संख्याओं का अलग क्रम दिखाते हैं:

    आम तौर पर, इस बदलाव से ऐप्लिकेशन के काम करने के तरीके पर कोई असर नहीं पड़ता. हालांकि, आपके कोड को Random.ints() तरीकों से जनरेट किए गए क्रम के Random.nextInt() से मेल खाने की उम्मीद नहीं करनी चाहिए.

SequencedCollection एपीआई का इस्तेमाल करने के लिए, अपने ऐप्लिकेशन के बिल्ड कॉन्फ़िगरेशन में compileSdk को अपडेट करने के बाद, आपके ऐप्लिकेशन की कंपैटिबिलिटी पर असर पड़ सकता है. ऐसा तब होगा, जब ऐप्लिकेशन में Android 15 (एपीआई लेवल 35) का इस्तेमाल किया जा रहा हो:

  • kotlin-stdlib में MutableList.removeFirst() और MutableList.removeLast() एक्सटेंशन फ़ंक्शन के साथ टकराव

    Java में List टाइप को Kotlin में MutableList टाइप पर मैप किया जाता है. List.removeFirst() और List.removeLast() एपीआई, Android 15 (एपीआई लेवल 35) में पेश किए गए हैं. इसलिए, Kotlin कंपाइलर, फ़ंक्शन कॉल (जैसे कि list.removeFirst()) को kotlin-stdlib में मौजूद एक्सटेंशन फ़ंक्शन के बजाय, नए List एपीआई के लिए स्टैटिक तौर पर हल करता है.

    अगर किसी ऐप्लिकेशन को compileSdk को 35 पर सेट करके और minSdk को 34 या इससे कम पर सेट करके फिर से कंपाइल किया जाता है और फिर उस ऐप्लिकेशन को Android 14 और इससे पहले के वर्शन पर चलाया जाता है, तो रनटाइम गड़बड़ी होती है:

    java.lang.NoSuchMethodError: No virtual method
    removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
    

    Android Gradle प्लगिन में मौजूद NewApi lint विकल्प, एपीआई के इन नए इस्तेमाल का पता लगा सकता है.

    ./gradlew lint
    
    MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi]
          list.removeFirst()
    

    रनटाइम एक्सेप्शन और लिंट की गड़बड़ियों को ठीक करने के लिए, Kotlin में removeFirst() और removeLast() फ़ंक्शन कॉल को क्रमशः removeAt(0) और removeAt(list.lastIndex) से बदला जा सकता है. अगर Android Studio Ladybug | 2024.1.3 या इसके बाद के वर्शन का इस्तेमाल किया जा रहा है, तो इसमें इन गड़बड़ियों को तुरंत ठीक करने का विकल्प भी मिलता है.

    अगर लिंट का विकल्प बंद कर दिया गया है, तो @SuppressLint("NewApi") और lintOptions { disable 'NewApi' } हटाएं.

  • Java में अन्य तरीकों के साथ टकराव

    मौजूदा टाइप में नए तरीके जोड़े गए हैं. उदाहरण के लिए, List और Deque. ऐसा हो सकता है कि ये नए तरीके, अन्य इंटरफ़ेस और क्लास में एक ही नाम और आर्ग्युमेंट टाइप वाले तरीकों के साथ काम न करें. अगर किसी तरीके के सिग्नेचर में टकराव होता है और वह काम नहीं करता है, तो javac कंपाइलर, बिल्ड-टाइम की गड़बड़ी दिखाता है. उदाहरण के लिए:

    गड़बड़ी का पहला उदाहरण:

    javac MyList.java
    
    MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List
      public void removeLast() {
                  ^
      return type void is not compatible with Object
      where E is a type-variable:
        E extends Object declared in interface List
    

    गड़बड़ी का दूसरा उदाहरण:

    javac MyList.java
    
    MyList.java:7: error: types Deque<Object> and List<Object> are incompatible;
    public class MyList implements  List<Object>, Deque<Object> {
      both define reversed(), but with unrelated return types
    1 error
    

    गड़बड़ी का तीसरा उदाहरण:

    javac MyList.java
    
    MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible;
    public static class MyList implements List<Object>, MyInterface<Object> {
      class MyList inherits unrelated defaults for getFirst() from types List and MyInterface
      where E#1,E#2 are type-variables:
        E#1 extends Object declared in interface List
        E#2 extends Object declared in interface MyInterface
    1 error
    

    बिल्ड से जुड़ी इन गड़बड़ियों को ठीक करने के लिए, इन इंटरफ़ेस को लागू करने वाली क्लास को, मिलते-जुलते रिटर्न टाइप के साथ इस तरीके को बदलना चाहिए. उदाहरण के लिए:

    @Override
    public Object getFirst() {
        return List.super.getFirst();
    }
    

सुरक्षा

Android 15 में ऐसे बदलाव किए गए हैं जिनसे सिस्टम की सुरक्षा को बढ़ावा मिलता है. इससे ऐप्लिकेशन और उपयोगकर्ताओं को नुकसान पहुंचाने वाले ऐप्लिकेशन से बचाने में मदद मिलती है.

प्रतिबंधित टीएलएस वर्शन

Android 15, TLS के 1.0 और 1.1 वर्शन के इस्तेमाल पर पाबंदी लगाता है. इन वर्शन को पहले Android में बंद कर दिया गया था. हालांकि, अब Android 15 को टारगेट करने वाले ऐप्लिकेशन के लिए, इनका इस्तेमाल करने की अनुमति नहीं है.

बैकग्राउंड में सुरक्षित तरीके से गतिविधि शुरू करना

Android 15, उपयोगकर्ताओं को नुकसान पहुंचाने वाले ऐप्लिकेशन से सुरक्षित रखता है. साथ ही, उन्हें अपने डिवाइसों पर ज़्यादा कंट्रोल देता है. इसके लिए, Android 15 में ऐसे बदलाव किए गए हैं जिनसे बैकग्राउंड में काम करने वाले नुकसान पहुंचाने वाले ऐप्लिकेशन, अन्य ऐप्लिकेशन को फ़ोरग्राउंड में नहीं ला पाते. साथ ही, वे अपनी अनुमतियों को नहीं बढ़ा पाते और उपयोगकर्ता के इंटरैक्शन का गलत इस्तेमाल नहीं कर पाते. Android 10 (एपीआई लेवल 29) के बाद से, बैकग्राउंड में ऐप्लिकेशन लॉन्च करने पर पाबंदी लगा दी गई है.

अन्य बदलाव

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

ज़्यादा सुरक्षित इंटेंट

Android 15 针对 intent 引入了 StrictMode

如需查看有关 Intent 使用违规行为的详细日志,请使用以下方法:

Kotlin

fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

Java

public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

उपयोगकर्ता अनुभव और सिस्टम यूज़र इंटरफ़ेस (यूआई)

Android 15 में कुछ ऐसे बदलाव किए गए हैं जिनसे उपयोगकर्ताओं को बेहतर और आसान अनुभव मिलेगा.

विंडो इंसर्ट में बदलाव

Android 15 में, विंडो इनसेट से जुड़े दो बदलाव किए गए हैं: डिफ़ॉल्ट रूप से, स्क्रीन के किनारों तक विंडो दिखती है. साथ ही, कॉन्फ़िगरेशन में भी बदलाव किए गए हैं. जैसे, सिस्टम बार का डिफ़ॉल्ट कॉन्फ़िगरेशन.

एज-टू-एज एनफ़ोर्समेंट

如果应用以 Android 15(API 级别 35)为目标平台,则在搭载 Android 15 的设备上默认以无边框显示。

以 Android 14 为目标平台且在 Android 15 设备上不是全屏显示的应用。


以 Android 15(API 级别 35)为目标平台且在 Android 15 设备上实现全屏显示的应用。此应用主要使用会自动应用边衬区的 Material 3 Compose 组件。此屏幕不受 Android 15 强制执行的无边框措施的负面影响。

这是一项重大变更,可能会对应用的界面产生负面影响。这些更改会影响以下界面区域:

  • 手势提示条导航栏
    • 默认透明。
    • 底部偏移量处于停用状态,因此内容会绘制在系统导航栏后面,除非应用了边衬区。
    • setNavigationBarColorR.attr#navigationBarColor 已弃用,不会影响手势导航。
    • setNavigationBarContrastEnforcedR.attr#navigationBarContrastEnforced 继续对使用手势进行导航没有任何影响。
  • “三按钮”导航
    • 默认情况下,不透明度设置为 80%,颜色可能与窗口背景颜色一致。
    • 底部偏移量已停用,因此内容会绘制在系统导航栏后面,除非应用了边衬区。
    • setNavigationBarColorR.attr#navigationBarColor 默认设置为与窗口背景保持一致。窗口背景必须是颜色可绘制对象,才能应用此默认值。此 API 已弃用,但仍会影响三按钮导航。
    • setNavigationBarContrastEnforcedR.attr#navigationBarContrastEnforced 默认值为 true,这会在三按钮导航栏中添加 80% 不透明度的背景。
  • 状态栏
    • 默认透明。
    • 顶部偏移量处于停用状态,因此内容会绘制在状态栏后面,除非应用了边衬区。
    • setStatusBarColorR.attr#statusBarColor 已弃用,对 Android 15 没有影响。
    • setStatusBarContrastEnforcedR.attr#statusBarContrastEnforced 已废弃,但仍会对 Android 15 产生影响。
  • 刘海屏
    • 非浮动窗口的 layoutInDisplayCutoutMode 必须为 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYSSHORT_EDGESNEVERDEFAULT 会被解读为 ALWAYS,这样用户就不会看到因刘海屏而产生的黑条,并且应用会显示在屏幕边缘。

以下示例展示了应用在以 Android 15(API 级别 35)为目标平台之前和之后,以及在应用边衬区之前和之后的效果。此示例并不全面,在 Android Auto 上可能会显示不同的内容。

以 Android 14 为目标平台且在 Android 15 设备上不是全屏显示的应用。
以 Android 15(API 级别 35)为目标平台且在 Android 15 设备上实现全屏显示的应用。不过,由于 Android 15 强制执行全屏显示,许多元素现在会被状态栏、三按钮导航栏或刘海屏遮挡。隐藏界面包括 Material 2 顶部应用栏、悬浮操作按钮和列表项。
一款以 Android 15(API 级别 35)为目标平台的应用,在 Android 15 设备上采用全屏显示,并应用边衬区,以便界面不会被隐藏。
如果您的应用已实现全屏显示,需要检查哪些方面

如果您的应用已实现全屏显示并应用边衬区,则除了以下情形外,您基本上不会受到影响。不过,即使您认为自己不受影响,我们仍建议您测试应用。

  • 您有一个非浮动窗口,例如使用 SHORT_EDGESNEVERDEFAULT 而不是 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYSActivity。如果您的应用在启动时崩溃,这可能是由启动画面引起的。您可以将核心启动画面依赖项升级到 1.2.0-alpha01 或更高版本,也可以设置 window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
  • 可能存在流量较低且界面被遮挡的屏幕。验证这些访问频率较低的界面是否没有被遮挡的界面。低流量屏幕包括:
    • 初始配置或登录界面
    • “设置”页面
如果您的应用尚未实现全屏显示,需要检查哪些方面

如果您的应用尚未实现全屏显示,则很可能会受到影响。除了已实现全屏显示的边缘到边缘应用的相关场景之外,您还应考虑以下事项:

  • 如果您的应用在 Compose 中使用 Material 3 组件 (androidx.compose.material3),例如 TopAppBarBottomAppBarNavigationBar,这些组件可能不会受到影响,因为它们会自动处理边衬区。
  • 如果您的应用使用的是 Compose 中的 Material 2 组件 (androidx.compose.material),这些组件不会自动处理边衬区。不过,您可以获得边衬区的访问权限,然后手动应用边衬区。在 androidx.compose.material 1.6.0 及更高版本中,使用 windowInsets 参数可为 BottomAppBarTopAppBarBottomNavigationNavigationRail 手动应用边衬区。 同样,请为 Scaffold 使用 contentWindowInsets 参数。
  • 如果应用使用了视图和 Material 组件 (com.google.android.material),则大多数基于视图的 Material 组件(例如 BottomNavigationViewBottomAppBarNavigationRailViewNavigationView)都会处理边衬区,因此不需要执行额外的操作。不过,如果使用的是 AppBarLayout,则需要添加 android:fitsSystemWindows="true"
  • 对于自定义可组合项,请手动应用边衬区作为内边距。如果您的内容位于 Scaffold 内,则可以使用 Scaffold 内边距值来使用边衬区。否则,请使用 WindowInsets 之一应用内边距。
  • 如果应用使用的是视图和 BottomSheetSideSheet 或自定义容器,请使用 ViewCompat.setOnApplyWindowInsetsListener 应用内边距。对于 RecyclerView,请使用此监听器应用内边距,同时添加 clipToPadding="false"
如果您的应用必须提供自定义后台保护,您需要检查哪些方面

如果您的应用必须为三按钮导航或状态栏提供自定义背景保护,则应使用 WindowInsets.Type#tappableElement() 获取三按钮导航栏高度或 WindowInsets.Type#statusBars,在系统栏后面放置一个可组合项或视图。

其他全屏显示资源

如需了解有关应用边衬区的其他注意事项,请参阅全屏视图全屏 Compose 指南。

已弃用的 API

以下 API 已弃用,但未停用:

以下 API 已弃用并停用:

स्टेबल कॉन्फ़िगरेशन

如果您的应用以 Android 15(API 级别 35)或更高版本为目标平台,Configuration 不再排除系统栏。如果您在 Configuration 类中使用屏幕尺寸进行布局计算,则应根据需要将其替换为更好的替代方案,例如适当的 ViewGroupWindowInsetsWindowMetricsCalculator

Configuration 自 API 1 起便已开始提供。通常从 Activity.onConfigurationChanged 获取。它提供窗口密度、方向和大小等信息。从 Configuration 返回的窗口大小的一个重要特征是,它之前不包括系统栏。

配置大小通常用于资源选择(例如 /res/layout-h500dp),这仍然是一个有效的使用情形。不过,我们一直不建议使用它进行布局计算。如果您正在这样做,请立即远离该设备。您应根据自己的使用场景,将 Configuration 的使用替换为更合适的用法。

如果您使用它来计算布局,请使用适当的 ViewGroup,例如 CoordinatorLayoutConstraintLayout。如果您使用它来确定系统导航栏的高度,请使用 WindowInsets。如果您想知道应用窗口的当前大小,请使用 computeCurrentWindowMetrics

以下列表介绍了受此变更影响的字段:

elegantTextHeight एट्रिब्यूट डिफ़ॉल्ट रूप से सही पर सेट होता है

对于以 Android 15(API 级别 35)为目标平台的应用,elegantTextHeight TextView 属性默认会变为 true,将默认使用的紧凑字体替换为一些具有较大垂直测量的脚本,使其更易于阅读。紧凑字体旨在防止布局中断;Android 13(API 级别 33)允许文本布局利用 fallbackLineSpacing 属性拉伸垂直高度,从而防止许多此类中断。

在 Android 15 中,系统中仍保留了紧凑字体,因此您的应用可以将 elegantTextHeight 设置为 false 以获得与之前相同的行为,但即将发布的版本不太可能支持此字体。因此,如果您的应用支持以下脚本:阿拉伯语、老挝语、缅甸语、泰米尔语、古吉拉特语、卡纳达语、马拉雅拉姆语、奥里亚语、泰卢固语或泰语,请将 elegantTextHeight 设置为 true 以测试您的应用。

针对以 Android 14(API 级别 34)及更低版本为目标平台的应用的 elegantTextHeight 行为。
以 Android 15 为目标平台的应用的 elegantTextHeight 行为。

जटिल अक्षर के आकार के लिए, TextView की चौड़ाई में बदलाव होता है

Android के पिछले वर्शन में, पेचीदा आकार वाले कुछ कर्सिव फ़ॉन्ट या भाषाएं, पिछले या अगले वर्ण के एरिया में अक्षर खींच सकती हैं. कुछ मामलों में, ऐसे अक्षरों को शुरुआत या आखिर में काटकर छोटा किया गया था. Android 15 से, TextView ऐसे अक्षरों के लिए ज़रूरी जगह बनाने के लिए चौड़ाई तय करता है. साथ ही, क्लिप बनाने से रोकने के लिए, ऐप्लिकेशन बाईं ओर ज़्यादा पैडिंग (जगह) का अनुरोध कर सकते हैं.

इस बदलाव का असर इस बात पर पड़ता है कि TextView, चौड़ाई का फ़ैसला कैसे लेता है. इसलिए, अगर ऐप्लिकेशन Android 15 (एपीआई लेवल 35) या उसके बाद के वर्शन को टारगेट करता है, तो TextView डिफ़ॉल्ट रूप से ज़्यादा चौड़ाई तय करता है. setUseBoundsForWidth पर एपीआई को कॉल करके, इस सुविधा को चालू या बंद किया जा सकता है.TextView

बाईं ओर की पैडिंग जोड़ने से, हो सकता है कि मौजूदा लेआउट गलत तरीके से अलाइन हो जाएं. ऐसा होने पर, Android 15 या इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए भी पैडिंग (जगह) डिफ़ॉल्ट रूप से नहीं जोड़ी जाती. हालांकि, setShiftDrawingOffsetForStartOverhang को कॉल करके, क्लिपिंग को रोकने के लिए अतिरिक्त पैडिंग जोड़ी जा सकती है.

नीचे दिए गए उदाहरणों से पता चलता है कि इन बदलावों से कुछ फ़ॉन्ट और भाषाओं के लिए टेक्स्ट लेआउट को बेहतर कैसे बनाया जा सकता है.

कर्सिव फ़ॉन्ट में अंग्रेज़ी टेक्स्ट के लिए स्टैंडर्ड लेआउट. कुछ अक्षर काट दिए गए हैं. यहां उससे जुड़ा एक्सएमएल है:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
अंग्रेज़ी के उसी टेक्स्ट का लेआउट जिसमें ज़्यादा चौड़ाई और पैडिंग है. यहां उससे जुड़ा एक्सएमएल है:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
थाई टेक्स्ट के लिए स्टैंडर्ड लेआउट. कुछ अक्षर काटे गए हैं. यहां उससे जुड़ा एक्सएमएल है:

<TextView
    android:text="คอมพิวเตอร์" />
ज़्यादा चौड़ाई और पैडिंग वाले एक ही थाई टेक्स्ट का लेआउट. यहां उससे जुड़ा एक्सएमएल है:

<TextView
    android:text="คอมพิวเตอร์"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />

EditText के लिए, स्थान-भाषा के हिसाब से लाइन की ऊंचाई का डिफ़ॉल्ट मान

Android के पिछले वर्शन में, टेक्स्ट लेआउट, टेक्स्ट की ऊंचाई को बढ़ा देता था, ताकि मौजूदा स्थानीय भाषा से मैच करने वाले फ़ॉन्ट की लाइन की ऊंचाई पूरी की जा सके. उदाहरण के लिए, अगर कॉन्टेंट जैपनीज़ में था, तो टेक्स्ट की ऊंचाई थोड़ी ज़्यादा हो गई, क्योंकि जैपनीज़ फ़ॉन्ट की लाइन की ऊंचाई, लैटिन फ़ॉन्ट की लाइन की ऊंचाई से थोड़ी ज़्यादा होती है. हालांकि, लाइन हाइट में इन अंतरों के बावजूद, इस्तेमाल किए जा रहे स्थानीय भाषा के बावजूद, EditText एलिमेंट का साइज़ एक जैसा था, जैसा कि इस इमेज में दिखाया गया है:

EditText एलिमेंट दिखाने वाले तीन बॉक्स, जिनमें इंग्लिश (en), जैपनीज़ (ja), और बर्मीज़ (my) भाषा का टेक्स्ट हो सकता है. EditText की ऊंचाई एक जैसी है, भले ही इन भाषाओं की लाइन की ऊंचाई एक-दूसरे से अलग हो.

Android 15 (एपीआई लेवल 35) को टारगेट करने वाले ऐप्लिकेशन के लिए, EditText के लिए कम से कम लाइन हाइट तय की गई है. इससे, तय की गई लोकेल के रेफ़रंस फ़ॉन्ट से मैच करने में मदद मिलती है. इसकी जानकारी इस इमेज में दी गई है:

EditText एलिमेंट दिखाने वाले तीन बॉक्स, जिनमें इंग्लिश (en), जैपनीज़ (ja), और बर्मीज़ (my) भाषा का टेक्स्ट हो सकता है. EditText की ऊंचाई में अब इन भाषाओं के फ़ॉन्ट के लिए, डिफ़ॉल्ट लाइन की ऊंचाई को शामिल करने के लिए स्पेस शामिल है.

ज़रूरत पड़ने पर, आपका ऐप्लिकेशन useLocalePreferredLineHeightForMinimum एट्रिब्यूट को false पर सेट करके, पहले जैसा व्यवहार वापस ला सकता है. साथ ही, आपका ऐप्लिकेशन Kotlin और Java में setMinimumFontMetrics एपीआई का इस्तेमाल करके, कस्टम मिनिमम वर्टिकल मेट्रिक सेट कर सकता है.

कैमरा और मीडिया

Android 15 में, Android 15 या इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, कैमरा और मीडिया के काम करने के तरीके में ये बदलाव किए गए हैं.

ऑडियो फ़ोकस का अनुरोध करने से जुड़ी पाबंदियां

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

ऑडियो फ़ोकस के बारे में ज़्यादा जानने के लिए, ऑडियो फ़ोकस मैनेज करें पर जाएं.

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

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

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

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

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