Perubahan Perilaku Android 8.0

Bersama fitur dan kemampuan baru, Android 8.0 menyertakan berbagai macam perubahan sistem dan perubahan perilaku API. Dokumen ini menyoroti beberapa perubahan utama yang harus dipahami dan diperhitungkan dalam aplikasi Anda.

Sebagian besar perubahan ini memengaruhi semua aplikasi, apa pun versi Android yang ditargetkan. Akan tetapi, sejumlah perubahan hanya memengaruhi aplikasi yang menargetkan Android 8.0. Agar lebih jelas, halaman ini dibagi menjadi dua bagian: Aplikasi yang menargetkan semua API level dan Aplikasi yang menargetkan Android 8.0.

Aplikasi yang menargetkan semua API level

Perubahan perilaku ini berlaku pada semua aplikasi bila aplikasi itu dijalankan pada platform Android 8.0, apa pun API level yang ditargetkannya. Semua developer harus meninjau perubahan ini dan memodifikasi aplikasinya untuk mendukungnya dengan benar, bila memungkinkan pada aplikasi.

Batas eksekusi latar belakang

Karena salah satu perubahan yang diperkenalkan oleh Android 8.0 adalah untuk meningkatkan daya tahan baterai, bila aplikasi Anda memasuki keadaan di-cache, tanpa komponen yang aktif, sistem akan melepas semua wakelock yang disimpan aplikasi.

Selain itu, untuk meningkatkan kinerja perangkat, sistem membatasi perilaku tertentu pada aplikasi yang tidak berjalan di latar depan. Khususnya:

  • Aplikasi yang dijalankan di latar belakang kini memiliki batas pada seberapa bebas aplikasi bisa mengakses layanan latar belakang.
  • Aplikasi tidak bisa menggunakan manifesnya untuk mendaftar ke siaran yang paling implisit (yaitu, siaran yang tidak ditargetkan khusus di aplikasi).

Secara default, pembatasan ini hanya berlaku pada aplikasi yang menargetkan O. Akan tetapi, pengguna bisa mengaktifkan pembatasan ini bagi aplikasi apa saja dari layar Settings, sekalipun aplikasi tersebut tidak menargetkan O.

Android 8.0 juga menyertakan perubahan berikut pada metode tertentu:

  • Metode startService() sekarang melontarkan sebuah IllegalStateException jika aplikasi yang menargetkan Android 8.0 mencoba menggunakan metode itu ketika tidak diizinkan membuat layanan latar belakang.
  • Metode Context.startForegroundService() baru akan memulai layanan latar depan. Sistem memungkinkan aplikasi memanggil Context.startForegroundService() bahkan saat aplikasi di latar belakang. Akan tetapi, aplikasi harus memanggil metode startForeground() layanan itu dalam waktu lima detik setelah layanan dibuat.

Untuk informasi selengkapnya, lihat Batas Eksekusi Latar Belakang.

Batas lokasi latar belakang Android

Untuk menghemat baterai, pengalaman pengguna, dan kesehatan sistem, aplikasi latar belakang akan semakin sedikit menerima pembaruan lokasi bila digunakan pada perangkat yang menjalankan Android 8.0. Perubahan perilaku ini memengaruhi semua aplikasi yang menerima pembaruan lokasi, termasuk Google Play Services.

Perubahan ini memengaruhi API berikut:

  • Fused Location Provider (FLP)
  • Pembatasan Wilayah
  • Pengukuran GNSS
  • Pengelola Lokasi
  • Pengelola Wi-Fi

Untuk memastikan aplikasi Anda berjalan seperti yang diharapkan, lakukan langkah-langkah berikut:

  • Tinjau logika aplikasi dan pastikan Anda menggunakan API lokasi terbaru.
  • Uji apakah aplikasi Anda menunjukkan perilaku yang diharapkan untuk setiap kasus penggunaan.
  • Pertimbangkan penggunaan Fused Location Provider (FLP) atau pembatasan wilayah untuk menangani kasus penggunaan yang bergantung pada lokasi pengguna saat ini.

Untuk informasi selengkapnya tentang perubahan ini, lihat Batas Lokasi Latar Belakang.

Pintasan aplikasi

Android 8.0 menyertakan perubahan berikut ke pintasan aplikasi:

  • Siaran com.android.launcher.action.INSTALL_SHORTCUT tidak lagi memiliki pengaruh pada aplikasi Anda, karena sekarang menjadi siaran implisit privat. Sebagai gantinya, Anda harus membuat pintasan aplikasi dengan menggunakan metode requestPinShortcut() dari kelas ShortcutManager.
  • Maksud ACTION_CREATE_SHORTCUT kini bisa membuat pintasan aplikasi yang Anda kelola dengan menggunakan kelas ShortcutManager. Maksud ini juga membuat pintasan peluncur lawas yang tidak berinteraksi dengan ShortcutManager. Sebelumnya, maksud ini hanya bisa membuat pintasan peluncur lawas.
  • Pintasan yang dibuat menggunakan requestPinShortcut() dan pintasan yang dibuat dalam aktivitas yang menangani maksud ACTION_CREATE_SHORTCUT kini menjadi pintasan aplikasi yang matang. Hasilnya, aplikasi kini bisa memperbaruinya dengan menggunakan berbagai metode di ShortcutManager.
  • Pintasan lawas tetap mempertahankan fungsionalitasnya dari Android versi sebelumnya, namun Anda harus mengonversinya menjadi pintasan aplikasi secara manual di aplikasi.

Untuk mempelajari lebih lanjut tentang berbagai perubahan pada pintasan aplikasi, lihat panduan fitur pratinjau Penyematan Pintasan dan Widget.

Lokal dan internasionalisasi

Android 7.0 (API level 24) memperkenalkan konsep kemampuan untuk menetapkan Category Locale default, namun beberapa API masih menggunakan metode Locale.getDefault() generik, tanpa argumen, bila harus menggunakan kategori Locale DISPLAY default sebagai gantinya. Di Android 8.0, metode berikut kini menggunakan Locale.getDefault(Category.DISPLAY) sebagai ganti Locale.getDefault():

Locale.getDisplayScript(Locale) juga akan melakukan fallback ke Locale.getDefault() bila nilai displayScript yang ditetapkan untuk argumen Locale tidak tersedia.

Perubahan yang terkait lokal dan internasionalisasi tambahan adalah seperti berikut:

  • Pemanggilan Currency.getDisplayName(null) akan melontarkan NullPointerException, sesuai dengan perilaku yang didokumentasikan.
  • Parsing nama zona waktu telah berubah. Sebelumnya, perangkat Android menggunakan nilai jam sistem yang diambil pada waktu booting untuk membuat cache nama zona waktu yang digunakan untuk mem-parse waktu tanggal. Sebagai hasilnya, parsing bisa terpengaruh negatif jika jam sistem salah pada waktu booting atau di kasus langka lainnya.

    Sekarang, dalam kasus umum, logika parsing menggunakan ICU dan nilai jam sistem saat ini ketika mem-parse nama zona waktu. Perubahan ini memberikan hasil lebih tepat, yang mungkin berbeda dengan versi Android terdahulu bila aplikasi Anda menggunakan kelas seperti SimpleDateFormat.

  • Android 8.0 meng-update versi ICU ke versi 58.

Jendela pemberitahuan

Jika aplikasi menggunakan izin SYSTEM_ALERT_WINDOW dan menggunakan salah satu tipe jendela berikut untuk mencoba menampilkan jendela pemberitahuan di atas jendela aplikasi lain dan jendela sistem:

...maka jendela ini akan selalu tampak di bawah jendela yang menggunakan tipe jendela TYPE_APPLICATION_OVERLAY. Jika menargetkan Android 8.0, aplikasi akan menggunakan tipe jendela TYPE_APPLICATION_OVERLAY untuk menampilkan jendela pemberitahuan.

Untuk informasi selengkapnya, lihat bagian Tipe jendela umum untuk jendela pemberitahuan di dalam perubahan perilaku untuk Aplikasi yang menargetkan Android 8.0.

Masukan dan navigasi

Bersama kehadiran aplikasi Android di Chrome OS dan faktor bentuk yang besar lainnya, seperti tablet, kita melihat adanya kebangkitan penggunaan navigasi keyboard dalam aplikasi Android. Dalam Android 8.0, kita telah membahas kembali penggunaan keyboard sebagai perangkat masukan navigasi, yang menghasilkan model yang lebih bisa diandalkan dan diperkirakan untuk navigasi berbasis panah dan tab.

Khususnya, kami telah melakukan perubahan berikut pada perilaku fokus elemen:

  • Jika Anda belum mendefinisikan warna keadaan fokus untuk objek View (baik sumber daya dapat digambar latar depan maupun latar belakang), kini framework menyetel warna sorot fokus default untuk View. Penandaan fokus ini adalah sumber daya dapat digambar berupa riak yang berdasarkan pada tema aktivitas.

    Jika Anda tidak ingin objek View menggunakan penandaan default saat menerima fokus, setel atribut android:defaultFocusHighlightEnabled ke false dalam file XML layout yang berisi View, atau teruskan false ke setDefaultFocusHighlightEnabled() dalam logika UI aplikasi Anda.

  • Untuk menguji bagaimana pengaruh masukan keyboard pada fokus elemen UI, Anda bisa mengaktifkan opsi developer Drawing > Show layout bounds. Di Android 8.0, opsi ini menampilkan ikon "X" di atas elemen yang saat ini memiliki fokus.

Semua elemen toolbar di Android 8.0 adalah juga kluster navigasi keyboard secara otomatis, sehingga memudahkan pengguna untuk membuka atau menutup setiap toolbar sebagai satu kesatuan.

Untuk mempelajari lebih lanjut tentang cara meningkatkan dukungan untuk navigasi keyboard dalam aplikasi Anda, baca panduan Mendukung Navigasi Keyboard.

Formulir web dan isiotomatis

Kini setelah Framework IsiOtomatis Android menyediakan dukungan bawaan untuk fungsionalitas isiotomatis, metode berikut yang terkait dengan objek WebView telah berubah untuk aplikasi yang diinstal pada perangkat yang menjalankan Android 8.0:

WebSettings
WebViewDatabase
  • Memanggil clearFormData() tidak lagi memiliki efek apa pun.
  • Kini metode hasFormData() mengembalikan false. Sebelumnya, metode ini mengembalikan true bila formulir berisi data.

Aksesibilitas

Layanan aksesibilitas kini mengetahui semua instance ClickableSpan dalam objek TextView aplikasi Anda.

Untuk mempelajari lebih lanjut tentang cara membuat aplikasi Anda lebih mudah diakses, lihat Aksesibilitas.

Jaringan dan konektivitas HTTP(S)

Android 8.0 menyertakan perubahan perilaku berikut pada jaringan dan konektivitas HTTP(S):

  • Permintaan OPTIONS tanpa isi memiliki header Content-Length: 0. Sebelumnya, permintaan ini tidak memiliki header Content-Length.
  • HttpURLConnection menormalkan URL yang berisi jalur kosong dengan menambahkan garis miring setelah host atau nama otoritas dengan garis miring. Misalnya, HttpURLConnection mengonversi http://example.com menjadi http://example.com/.
  • Pemilih proxy khusus yang disetel melalui ProxySelector.setDefault() hanya menargetkan alamat (skema, host, dan porta) URL yang diminta. Sebagai hasilnya, pemilihan proxy hanya bisa berdasarkan nilai-nilai itu. URL yang diteruskan ke pemilih proxy khusus tidak menyertakan jalur, parameter kueri, atau fragmen URL yang diminta.
  • URI tidak boleh berisi label kosong.

    Sebelumnya, platform mendukung solusi untuk menerima label kosong di nama host, yang merupakan penggunaan URI yang tidak sah. Solusi ini digunakan untuk kompatibilitas dengan rilis libcore lama. Developer yang menggunakan API dengan tidak benar akan melihat pesan ADB: "URI example..com has empty labels in the hostname. This is malformed and will not be accepted in future Android releases." Android 8.0 membuang solusi ini; sistem mengembalikan null untuk URI yang formatnya salah.

  • Implementasi Android 8.0 untuk HttpsURLConnection tidak melakukan fallback versi protokol TLS/SSL yang tidak aman.
  • Penanganan koneksi HTTP(S) tunneling telah berubah seperti berikut:
    • Saat tunneling koneksi HTTPS melalui koneksi, sistem akan menempatkan nomor porta (:443) dengan benar di baris Host saat mengirimkan informasi ini ke server perantara. Sebelumnya, nomor porta hanya ditampilkan di baris CONNECT.
    • Sistem tidak lagi mengirimkan header user-agent dan proxy-authorization dari permintaan yang disalurkan ke server proxy.

      Sistem tidak lagi mengirimkan header proxy-authorization pada Http(s)URLConnection yang disalurkan ke proxy saat mempersiapkan saluran. Sebagai gantinya, sistem akan menghasilkan header proxy-authorization dan mengirimkannya ke proxy bila proxy itu mengirimkan HTTP 407 sebagai respons terhadap permintaan awal.

      Demikian juga, sistem tidak lagi menyalin header user-agent dari permintaan yang disalurkan ke permintaan proxy yang mempersiapkan saluran. Sebagai gantinya, pustaka akan menghasilkan header user-agent untuk permintaan itu.

  • Metode send(java.net.DatagramPacket) melontarkan SocketException jika metode connect() yang dieksekusi sebelumnya gagal.
    • DatagramSocket.connect() menyetel pendingSocketException jika ada kesalahan internal. Sebelum Android 8.0, panggilan recv() selanjutnya melontarkan SocketException meskipun panggilan send() kemungkinan akan berhasil. Agar konsisten, kedua panggilan sekarang melontarkan SocketException.
  • InetAddress.isReachable() mencoba ICMP sebelum melakukan fallback ke protokol TCP Echo.
    • Beberapa host yang memblokir porta 7 (TCP Echo), misalnya google.com, sekarang mungkin bisa diakses jika menerima protokol ICMP Echo.
    • Untuk host yang benar-benar tidak bisa diakses, perubahan ini berarti jumlah waktu yang dihabiskan sebelum panggilan dikembalikan akan bertambah dua kali lipat.

Bluetooth

Android 8.0 membuat perubahan berikut pada panjang data yang diambil oleh metode ScanRecord.getBytes():

  • Metode getBytes() tidak membuat asumsi berapa jumlah byte yang diterima. Oleh karena itu, aplikasi tidak boleh bergantung pada jumlah byte minimum atau maksimum yang dikembalikan. Sebagai gantinya, aplikasi harus mengevaluasi panjang larik yang dihasilkan.
  • Perangkat yang kompatibel dengan Bluetooth 5 mungkin mengembalikan panjang data yang melampaui maksimum ~60 byte sebelumnya.
  • Jika perangkat jauh tidak memberikan respons pemindaian, kurang dari 60 byte mungkin akan dikembalikan juga.

Konektivitas Mulus

Android 8.0 melakukan sejumlah peningkatan pada Wi-Fi Settings guna memudahkannya memilih jaringan Wi-Fi yang menawarkan pengalaman pengguna terbaik. Perubahan spesifik meliputi:

  • Peningkatan stabilitas dan reliabilitas.
  • UI yang lebih mudah dibaca secara intuitif.
  • Menu Wi-Fi Preferences tunggal yang terkonsolidasi.
  • Pada perangkat yang kompatibel, aktivasi otomatis Wi-Fi bila ada di sekitar jaringan tersimpan berkualitas tinggi.

Keamanan

Android 8.0 menyertakan perubahan terkait keamanan berikut:

  • Platform tidak lagi mendukung SSLv3.
  • Saat membuat koneksi HTTPS ke server yang salah mengimplementasikan negosiasi versi protokol TLS, HttpsURLConnection tidak lagi mencoba solusi berupa fallback ke versi protokol TLS yang lebih lama dan mencoba lagi.
  • Android 8.0 menerapkan filter Secure Computing (SECCOMP) ke semua aplikasi. Daftar syscall yang diizinkan dibatasi untuk syscall yang diekspos melalui bionic. Walaupun ada sejumlah syscall lain yang disediakan untuk kompatibilitas mundur, kami menyarankan menentang penggunaannya.
  • Objek WebView aplikasi Anda kini berjalan di mode multiproses. Konten web ditangani dalam proses terisolasi yang terpisah dari proses aplikasi yang mencakupnya untuk meningkatkan keamanan.
  • Anda tidak bisa lagi beranggapan bahwa APK berada di direktori yang namanya berakhiran -1 atau -2. Aplikasi harus menggunakan sourceDir untuk mendapatkan direktori, dan tidak bergantung pada format direktori secara langsung.
  • Untuk informasi tentang penyempurnaan keamanan yang berkaitan dengan penggunaan koleksi asli, lihat Koleksi Asli.

Untuk panduan tambahan mengenai pembuatan aplikasi yang lebih aman, lihat Keamanan untuk Developer Android.

Privasi

Android 8.0 membuat perubahan terkait privasi berikut pada platform.

  • Platform kini menangani identifier secara berbeda.
    • Untuk aplikasi yang diinstal sebelum OTA ke versi Android 8.0 (API level 26), nilai ANDROID_ID tetap sama kecuali jika di-uninstal lalu diinstal ulang setelah OTA. Untuk mempertahankan nilai pada proses uninstal setelah OTA, developer bisa menghubungkan nilai lama dan baru dengan menggunakan Key/Value Backup.
    • Untuk aplikasi yang diinstal pada perangkat yang menjalankan Android 8.0, nilai ANDROID_ID sekarang menjadi cakupan per kunci penandatanganan aplikasi, juga per pengguna. Nilai ANDROID_ID bersifat unik untuk setiap kombinasi kunci penandatanganan aplikasi, pengguna, dan perangkat. Akibatnya, aplikasi dengan kunci penandatanganan berbeda yang dijalankan pada perangkat yang sama tidak lagi melihat ID Android yang sama (bahkan untuk pengguna yang sama).
    • Nilai ANDROID_ID tidak berubah pada penginstalan atau instal ulang paket, selama kunci penandatanganannya sama (dan aplikasi tidak diinstal sebelum OTA ke versi O).
    • Nilai ANDROID_ID tidak berubah bahkan jika update sistem menyebabkan kunci penandatanganan paket berubah.
    • Bagi sistem sederhana dan standar untuk memonetisasi aplikasi, gunakan ID Iklan. ID Iklan adalah ID unik yang bisa disetel ulang oleh pengguna untuk iklan, yang disediakan oleh Google Play Services.

  • Kueri properti sistem net.hostname menghasilkan null.

Pencatatan log atas pengecualian yang tidak tertangkap

Jika aplikasi menginstal Thread.UncaughtExceptionHandler yang tidak memanggil ke Thread.UncaughtExceptionHandler default, sistem tidak akan mematikan aplikasi saat terjadi pengecualian yang tidak tertangkap. Mulai Android 8.0, sistem mencatat log stacktrace pengecualian dalam situasi ini; di versi platform sebelumnya, sistem tidak akan mencatat log stacktrace pengecualian.

Kami menyarankan agar implementasi Thread.UncaughtExceptionHandler khusus selalu memanggil penangan default; aplikasi yang mengikuti saran ini tidak terpengaruh oleh perubahan di Android 8.0.

Perubahan statistik penggunaan penyedia kontak

Di Android versi sebelumnya, komponen Contacts Provider memungkinkan developer mendapatkan data penggunaan untuk setiap kontak. Data penggunaan ini mengekspos informasi untuk setiap alamat email dan setiap nomor telepon yang dikaitkan dengan sebuah kontak, termasuk berapa kali kontak dihubungi dan waktu terakhir kontak dihubungi. Aplikasi yang meminta izin READ_CONTACTS bisa membaca data ini.

Aplikasi masih bisa membaca data ini jika meminta izin READ_CONTACTS. Mulai Android 8.0, kueri untuk data penggunaan mengembalikan perkiraan, bukannya nilai persis. Sistem Android mempertahankan nilai persisnya secara internal, sehingga perubahan ini tidak memengaruhi API pelengkapan otomatis.

Perubahan perilaku ini memengaruhi parameter kueri berikut:

Penanganan kumpulan

AbstractCollection.removeAll() dan AbstractCollection.retainAll() kini selalu melontarkan NullPointerException; sebelumnya, NullPointerException tidak dilontarkan bila koleksi tersebut kosong. Perubahan ini menjadikan perilaku konsisten dengan dokumentasi.

Android enterprise

Android 8.0 mengubah perilaku sebagian API dan fitur untuk aplikasi enterprise, termasuk pengontrol kebijakan perangkat (DPC). Perubahan tersebut meliputi:

  • Perilaku baru untuk membantu aplikasi mendukung profil kerja pada perangkat yang sepenuhnya dikelola.
  • Perubahan pada penanganan update sistem, verifikasi aplikasi, dan autentikasi untuk meningkatkan integritas sistem dan perangkat.
  • Peningkatan pada pengalaman pengguna untuk penyediaan, notifikasi, layar Recents, dan Always-On VPN.

Untuk melihat semua perubahan enterprise di Android 8.0 dan mempelajari caranya memengaruhi aplikasi Anda, baca Android di Enterprise.

Aplikasi yang menargetkan Android 8.0

Perubahan perilaku ini berlaku secara eksklusif pada aplikasi yang menargetkan platform O atau yang lebih tinggi. Aplikasi yang dikompilasi untuk Android 8.0 atau yang lebih tinggi atau menyetel targetSdkVersion ke Android 8.0 atau yang lebih tinggi, harus dimodifikasi untuk mendukung perilaku ini dengan benar, bila memungkinkan bagi aplikasi.

Jendela pemberitahuan

Aplikasi yang menggunakan izin SYSTEM_ALERT_WINDOW tidak bisa lagi menggunakan tipe jendela berikut untuk menampilkan jendela pemberitahuan di atas aplikasi lain dan jendela sistem:

Sebagai gantinya, aplikasi harus menggunakan tipe jendela baru yang disebut TYPE_APPLICATION_OVERLAY.

Saat menggunakan tipe jendela TYPE_APPLICATION_OVERLAY untuk menampilkan jendela peringatan untuk aplikasi Anda, pertimbangkan karakteristik tipe jendela baru berikut:

  • Jendela peringatan aplikasi selalu muncul pada jendela sistem yang kritis, misalnya bilah status dan IME.
  • Sistem bisa memindahkan atau mengubah ukuran jendela yang menggunakan tipe jendela TYPE_APPLICATION_OVERLAY untuk meningkatkan presentasi layar.
  • Dengan membuka menu notifikasi, pengguna bisa mengakses setelan untuk memblokir aplikasi agar tidak menampilkan jendela pemberitahuan yang ditampilkan menggunakan tipe jendela TYPE_APPLICATION_OVERLAY.

Notifikasi perubahan konten

Android 8.0 mengubah cara perilaku ContentResolver.notifyChange() dan registerContentObserver(Uri, boolean, ContentObserver) untuk aplikasi yang menargetkan Android 8.0.

Semua API ini sekarang mengharuskan ContentProvider yang valid didefinisikan untuk otoritas dalam semua URI. Mendefinisikan ContentProvider yang valid bersama izin yang relevan akan membantu melindungi aplikasi Anda dari perubahan materi akibat aplikasi jahat, dan mencegah Anda membocorkan data yang mungkin bersifat privat kepada aplikasi jahat.

Fokus tampilan

Objek View yang bisa diklik saat ini juga bisa difokus secara default. Jika Anda ingin objek View bisa diklik namun tidak bisa difokus, setel atribut android:focusable ke false dalam file XML layout yang berisi View, atau teruskan false ke setFocusable() dalam logika UI aplikasi Anda.

Keamanan

Jika konfigurasi keamanan jaringan aplikasi Anda berhenti mendukung traffic cleartext, maka objek WebView aplikasi Anda tidak bisa mengakses situs web melalui HTTP. Setiap objek WebView harus menggunakan HTTPS sebagai gantinya.

Untuk panduan tambahan mengenai pembuatan aplikasi yang lebih aman, lihat Keamanan untuk Developer Android.

Akses akun dan visibilitas

Aplikasi tidak bisa lagi mendapatkan akses ke akun pengguna kecuali jika autentikator memiliki akun tersebut atau pengguna memberikan akses itu. Izin GET_ACCOUNTS tidak lagi mencukupi. Agar diberi akses ke akun, aplikasi harus menggunakan AccountManager.newChooseAccountIntent() atau metode khusus autentikator. Setelah mendapatkan akses ke akun, sebuah aplikasi bisa memanggil AccountManager.getAccounts() untuk mengaksesnya.

Android 8.0 tidak lagi menggunakan LOGIN_ACCOUNTS_CHANGED_ACTION. Sebagai gantinya, aplikasi harus menggunakan addOnAccountsUpdatedListener() untuk mendapatkan pembaruan tentang akun selama waktu proses.

Untuk informasi tentang API dan metode baru yang ditambahkan untuk akses akun dan visibilitas, lihat Akses Akun dan Visibilitas di bagian API Baru di dokumen ini.

Privasi

Perubahan berikut memengaruhi privasi di Android 8.0.

  • Properti sistem net.dns1, net.dns2, net.dns3, dan net.dns4 tidak lagi tersedia, sebuah perubahan yang meningkatkan privasi di platform.
  • Untuk mendapatkan informasi jaringan seperti server DNS, aplikasi yang memiliki izin ACCESS_NETWORK_STATE bisa mendaftarkan objek NetworkRequest atau NetworkCallback. Kelas ini tersedia di Android 5.0 (API level 21) dan yang lebih tinggi.
  • Build.SERIAL tidak digunakan lagi. Aplikasi yang perlu mengetahui nomor seri hardware harus menggunakan metode Build.getSerial() baru, yang memerlukan izin READ_PHONE_STATE.
  • LauncherApps API tidak lagi memungkinkan aplikasi profil kerja untuk mendapatkan informasi tentang profil utama. Bila pengguna berada dalam profil kerja, LauncherApps API berperilaku seolah-olah tidak ada aplikasi yang dipasang di profil lain dalam grup profil yang sama. Seperti sebelumnya, upaya untuk mengakses profil yang tidak berkaitan akan menyebabkan SecurityExceptions.

Izin

Sebelum Android 8.0, jika aplikasi meminta izin pada waktu proses dan izin diberikan, sistem juga akan salah memberikan izin lain kepada aplikasi yang berada di grup izin yang sama dan yang didaftarkan dalam manifes.

Untuk aplikasi yang menargetkan Android 8.0, perilaku ini telah dikoreksi. Aplikasi hanya diberikan izin yang telah dimintanya secara eksplisit. Akan tetapi, begitu pengguna memberikan izin ke aplikasi, semua permintaan izin setelahnya di grup izin tersebut akan diberikan secara otomatis.

Misalnya, sebuah aplikasi mencantumkan READ_EXTERNAL_STORAGE dan WRITE_EXTERNAL_STORAGE dalam manifesnya. Aplikasi meminta READ_EXTERNAL_STORAGE dan pengguna memberikannya. Jika aplikasi menargetkan API level 24 atau yang lebih rendah, sistem juga akan memberikan WRITE_EXTERNAL_STORAGE di saat yang sama, karena aplikasi dimiliki oleh grup izin STORAGE yang sama dan juga terdaftar di manifes. Jika aplikasi menargetkan Android 8.0, sistem hanya akan memberikan READ_EXTERNAL_STORAGE pada waktu itu, akan tetapi, jika aplikasi nanti meminta WRITE_EXTERNAL_STORAGE, sistem akan langsung memberikan izin tersebut tanpa mengonfirmasi pengguna.

Media

  • Framework melakukan penurunan audio. Aplikasi tidak kehilangan fokus sehubungan dengan AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK. API baru tersedia untuk aplikasi yang perlu menghentikan sementara sebagai ganti penurunan audio. Perhatikan, perilaku ini tidak diimplementasikan di rilis Android 8.0 1.
  • Bila pengguna menjawab panggilan telepon, streaming media aktif akan dimatikan suaranya selama panggilan.
  • Semua API terkait audio harus menggunakan AudioAttributes bukan tipe streaming audio untuk menjelaskan kasus penggunaan pemutaran audio. Terus menggunakan tipe streaming audio hanya untuk kontrol volume. Penggunaan tipe streaming lain (misalnya, AudioTrack constructor yang tidak digunakan lagi) masih bisa dilakukan, namun sistem mencatatnya dalam log sebagai error.
  • Saat menggunakan AudioTrack, jika aplikasi meminta buffering audio yang cukup besar, framework akan mencoba menggunakan keluaran buffering yang dalam jika tersedia.
  • Di Android 8.0, penanganan kejadian tombol media berbeda:
    1. Penanganan tombol media dalam aktivitas UI belum berubah: aktivitas latar depan masih mendapatkan prioritas dalam menangani tombol media.
    2. Jika aktivitas latar depan tidak menangani tombol media, sistem akan merutekan tombol media ke aplikasi yang terakhir memutar audio secara lokal. Status aktif, flag, dan keadaan pemutaran sesi media tidak lagi dipertimbangkan saat menentukan aplikasi mana yang menerima kejadian tombol media. Sesi media bisa menerima kejadian tombol media bahkan setelah aplikasi memanggil setActive(false).
    3. Jika sesi media aplikasi telah dirilis, sistem akan mengirimkan kejadian tombol media ke MediaButtonReceiver aplikasi, jika ada.
    4. Untuk setiap kasus lainnya, sistem menghapus kejadian tombol media. Lebih baik tidak memutar apa pun sama sekali daripada mulai memutar aplikasi yang salah.

    Logika perutean tombol media baru dirangkum dalam diagram berikut:

    Perutean Tombol Media

Pustaka asli

Dalam aplikasi yang menargetkan Android 8.0, koleksi asli tidak lagi dimuat jika berisi segmen muatan apa pun yang dapat ditulisi dan dieksekusi. Beberapa aplikasi bisa berhenti beroperasi akibat perubahan ini jika memiliki pustaka asli dengan segmen muatan yang tidak benar. Ini adalah tindakan pengetatan keamanan.

Untuk informasi selengkapnya, lihat Segmen yang Dapat Ditulisi dan Dieksekusi.

Sebagaimana dengan rilis pratinjau-developer sebelumnya, Android 8.0 juga membuat semua masalah yang berkaitan dengan linker menjadi lebih jelas terlihat. Perubahan linker dikaitkan ke API level yang ditargetkan aplikasi. Jika ada perubahan linker pada API level yang ditargetkan, aplikasi tidak bisa memuat pustaka. Jika Anda menargetkan API level yang lebih rendah dari API level tempat perubahan linker terjadi, logcat akan menampilkan peringatan. Selama rilis pratinjau, masalah yang terkait dengan linker tidak hanya muncul di logcat, tetapi juga ditampilkan sebagai toast. Perubahan ini meningkatkan visibilitas masalah sebelum API level tempat peringatan menjadi error.

Penanganan kumpulan

Di Android 8.0, Collections.sort() diimplementasikan di atas List.sort(). Hal sebaliknya juga berlaku di Android 7.x (API level 24 dan 25): Implementasi default List.sort() disebut Collections.sort().

Perubahan ini memungkinkan Collections.sort() untuk memanfaatkan implementasi List.sort() yang dioptimalkan, namun memiliki pembatasan berikut:

  • Implementasi List.sort() tidak boleh memanggil Collections.sort(), karena hal itu akan mengakibatkan stack overflow akibat rekursi tanpa batas. Sebagai gantinya, jika Anda ingin perilaku default di implementasi List, Anda harus menghindari penggantian sort().

    Jika kelas induk mengimplementasikan sort() dengan tidak benar, biasanya tidak mengapa untuk mengganti List.sort() dengan implementasi yang dibuat di atas List.toArray(), Arrays.sort(), dan ListIterator.set(). Misalnya:

    @Override
    public void sort(Comparator<? super E> c) {
      Object[] elements = toArray();
      Arrays.sort(elements, c);
      ListIterator<E> iterator = (ListIterator<Object>) listIterator();
      for (Object element : elements) {
        iterator.next();
        iterator.set((E) element);
      }
    }
    

    Biasanya, Anda juga bisa mengganti List.sort() dengan implementasi yang didelegasikan ke implementasi default berbeda yang bergantung pada API level. Misalnya:

    @Override
    public void sort(Comparator<? super E> comparator) {
      if (Build.VERSION.SDK_INT <= 25) {
        Collections.sort(this);
      } else {
        super.sort(comparator);
      }
    }
    

    Jika Anda melakukan yang terakhir hanya karena Anda ingin membuat metode sort() tersedia di semua API level, pertimbangkan untuk memberinya nama unik, misalnya sortCompat(), daripada mengganti sort().

  • Collections.sort() sekarang dianggap sebagai modifikasi struktural di implementasi List yang memanggil sort(). Misalnya, di versi platform sebelum Android 8.0, melakukan iterasi pada ArrayList dan memanggil sort() di tengah proses iterasi akan melontarkan ConcurrentModificationException jika pengurutan yang dilakukan dengan memanggil List.sort(). Collections.sort() tidak melontarkan pengecualian.

    Perubahan ini membuat perilaku platform lebih konsisten: Setiap pendekatan kini menghasilkan ConcurrentModificationException.

Perilaku pemuatan kelas

Android 8.0 memeriksa untuk memastikan loader kelas tidak merusak asumsi waktu proses saat memuat kelas baru. Pemeriksaan ini dilakukan untuk mengetahui apakah kelas tersebut direferensikan dari Java (dari forName()), Dalvik bytecode, maupun JNI. Platform tidak mencegat panggilan langsung dari Java ke metode loadClass(), maupun memeriksa hasilnya dari panggilan tersebut. Perilaku ini tidak boleh memengaruhi fungsi loader kelas yang berperilaku-baik.

Platform akan memeriksa apakah deskriptor kelas yang dikembalikan oleh loader kelas sesuai dengan deskriptor yang diharapkan. Jika deskriptor yang dikembalikan tidak sesuai, platform akan melontarkan error NoClassDefFoundError, dan dalam pengecualian akan disimpan pesan detail kesalahan tersebut.

Platform juga akan memeriksa apakah deskriptor kelas yang diminta memang valid. Pemeriksaan ini akan menangkap panggilan JNI yang secara tidak langsung memuat kelas-kelas seperti GetFieldID(), dengan meneruskan deskriptor tidak valid ke kelas-kelas tersebut. Misalnya, kolom dengan tanda tangan java/lang/String tidak ditemukan karena tanda tangan itu tidak valid; seharusnya Ljava/lang/String;.

Hal ini berbeda dengan panggilan JNI ke FindClass() dengan java/lang/String merupakan nama valid yang benar-benar memenuhi syarat.

Android 8.0 tidak mendukung banyak loader kelas, cobalah definisikan kelas menggunakan objek DexFile yang sama. Upaya untuk melakukannya menyebabkan waktu proses Android melontarkan error InternalError dengan pesan "Attempt to register dex file <filename> with multiple class loaders".

DexFile API sekarang tidak digunakan lagi, Anda sangat disarankan untuk menggunakan salah satu classloader platform, termasuk PathClassLoader atau BaseDexClassLoader sebagai gantinya.

Catatan: Anda bisa membuat beberapa loader kelas yang mereferensikan kontainer file APK atau JAR yang sama dari sistem file. Biasanya cara ini tidak mengakibatkan overhead memori yang besar. Jika file DFX dalam kontainer disimpan sebagai ganti dikompresi, platform bisa melakukan operasi mmap padanya daripada mengekstraknya secara langsung. Akan tetapi, jika platform harus mengekstrak file DFX dari kontainer, merujuk file DFX dengan cara ini bisa memakan banyak memori.

Di Android, semua loader kelas dianggap berkemampuan sejajar. Bila sejumlah thread berlomba memuat satu kelas dengan loader kelas yang sama, thread pertama yang akan memenangkan operasi, dan hasilnya akan digunakan untuk thread yang lain. Perilaku ini terjadi terlepas apakah loader kelas telah mengembalikan kelas yang sama, mengembalikan kelas berbeda, atau melontarkan pengecualian. Platform secara diam-diam mengabaikan pengecualian semacam ini.

Perhatian: Di platform dengan versi lebih rendah dari Android 8.0, merusak asumsi ini bisa berakibat pendefinisian kelas yang sama beberapa kali, korupsi heap akibat kebingungan kelas, dan efek-efek yang tidak diinginkan.