Android 7.0 では、新機能に加えて、システムや API の動作に関するさまざまな変更が行われています。このドキュメントでは、アプリで理解および考慮すべき主な変更点について説明します。
以前に Android 向けアプリを公開したことがある場合は、プラットフォームのこうした変更によってアプリが影響を受ける可能性があることに留意してください。
バッテリーとメモリ
Android 7.0 では、デバイスのバッテリー駆動時間の改善と RAM 使用量の削減を目的として、システム動作が変更されています。これらの変更は、システム リソースへのアプリのアクセスだけでなく、特定の暗黙的インテントを介してアプリが他のアプリとやり取りする方法にも影響する可能性があります。
Doze
Android 6.0(API レベル 23)で導入された Doze は、ユーザーがデバイスを電源から外して静止状態にし、画面をオフにした状態で CPU とネットワーク アクティビティを遅らせることで、バッテリー駆動時間を改善します。Android 7.0 では、デバイスが電源に接続されていない(ハンドセットが固定されていない状態で)デバイスを電源から外しているときに、CPU とネットワークの制限のサブセットを適用することで、さらなる強化が行われています。
デバイスがバッテリー駆動の状態で画面がしばらくオフになっていると、デバイスは Doze モードになり、制限の最初のサブセットが適用されます。つまり、アプリのネットワーク アクセスがオフになり、ジョブと同期が延期されます。Doze モードに移行した後、デバイスが一定時間静止状態になると、残りの Doze 制限は PowerManager.WakeLock
、AlarmManager
アラーム、GPS、Wi-Fi スキャンに適用されます。一部またはすべての Doze 制限が適用されているかどうかに関係なく、短時間のメンテナンス時間枠のためデバイスがスリープ状態から復帰します。その間、アプリはネットワークへのアクセスを許可され、遅延したジョブや同期を実行できます。
画面をオンにするかデバイスを電源に接続すると、Doze モードは終了し、これらの処理制限が解除されます。この追加の動作は、 Doze とアプリ スタンバイの最適化で説明されているように、Android 6.0(API レベル 23)で導入された以前のバージョンの Doze にアプリを適応させる際の推奨事項とベスト プラクティスには影響しません。その場合でも、Firebase Cloud Messaging(FCM)を使用してメッセージを送受信するなどの推奨事項に従い、追加の Doze 動作に対応するための更新を計画する必要があります。
Project Svelte: バックグラウンド処理の最適化
Android 7.0 では、メモリ使用量と消費電力の両方を最適化するために、3 つの暗黙的なブロードキャストが削除されました。この変更が必要となるのは、暗黙的ブロードキャストによって、バックグラウンドでブロードキャストをリッスンするように登録されているアプリが頻繁に起動されるためです。これらのブロードキャストを削除すると、デバイスのパフォーマンスとユーザー エクスペリエンスが大幅に向上します。
モバイル デバイスでは、Wi-Fi とモバイルデータを切り替えるときなど、接続が頻繁に変更されます。現在、アプリはマニフェストに暗黙的な CONNECTIVITY_ACTION
ブロードキャストのレシーバを登録することで、接続の変更をモニタリングできます。多くのアプリは、このブロードキャストの受信登録を行っているため、1 回のネットワーク切り替えですべてのアプリが同時に復帰して処理される場合があります。
同様に、以前のバージョンの Android では、カメラなどの他のアプリから暗黙的な ACTION_NEW_PICTURE
ブロードキャストと ACTION_NEW_VIDEO
ブロードキャストを受信するようにアプリを登録できました。ユーザーがカメラアプリで写真を撮影すると、これらのアプリが起動してブロードキャストを処理します。
こうした問題を軽減するために、Android 7.0 では以下の最適化を行っています。
- Android 7.0(API レベル 24)以降を対象とするアプリは、マニフェストでブロードキャスト レシーバを宣言している場合は、
CONNECTIVITY_ACTION
ブロードキャストを受信しません。アプリがContext.registerReceiver()
でBroadcastReceiver
を登録し、コンテキストがまだ有効である場合、アプリは引き続きCONNECTIVITY_ACTION
ブロードキャストを受信します。 - システムが
ACTION_NEW_PICTURE
ブロードキャストまたはACTION_NEW_VIDEO
ブロードキャストを送信しなくなりました。この最適化は、Android 7.0 をターゲットとするアプリだけでなく、すべてのアプリに影響します。
アプリでこれらのインテントを使用している場合は、Android 7.0 デバイスを適切にターゲットにできるように、できるだけ早くそれらの依存関係を削除してください。
Android フレームワークには、これらの非明示的ブロードキャストの必要性を緩和するソリューションがいくつか用意されています。たとえば、JobScheduler
API は、指定された条件(定額制ネットワークへの接続など)が満たされたときにネットワーク操作をスケジューリングする堅牢なメカニズムを提供します。JobScheduler
を使用して、コンテンツ プロバイダの変更に対応することもできます。
Android 7.0(API レベル 24)におけるバックグラウンド処理の最適化と、アプリを適応させる方法について詳しくは、バックグラウンド処理の最適化をご覧ください。
権限の変更
Android 7.0 には、アプリに影響する可能性のある権限の変更が含まれています。
ファイル システムの権限の変更
プライベート ファイルのセキュリティを強化するため、Android 7.0 以降を対象とするアプリのプライベート ディレクトリへのアクセスが制限されています(0700
)。この設定により、プライベート ファイルのメタデータ(サイズや存在など)が漏洩しなくなります。この権限の変更には、次のような複数の副作用があります。
-
オーナーは非公開ファイルのファイル権限を緩和しないでください。
MODE_WORLD_READABLE
やMODE_WORLD_WRITEABLE
を使用して緩和しようとすると、SecurityException
がトリガーされます。注: 現時点では、この制限は完全には適用されていません。アプリは引き続き、ネイティブ API または
File
API を使用してプライベート ディレクトリの権限を変更できます。ただし、プライベート ディレクトリに対する権限を緩和しないことを強くおすすめします。 -
パッケージ ドメインの外部に
file://
URI を渡すと、レシーバーのパスにアクセスできない可能性があります。したがって、file://
URI を渡そうとすると、FileUriExposedException
がトリガーされます。非公開ファイルの内容を共有するには、FileProvider
を使用することをおすすめします。 -
DownloadManager
は、非公開に保存されているファイルをファイル名で共有できなくなりました。以前のアプリケーションでCOLUMN_LOCAL_FILENAME
にアクセスすると、パスにアクセスできない可能性があります。Android 7.0 以降をターゲットとするアプリがCOLUMN_LOCAL_FILENAME
にアクセスしようとすると、SecurityException
がトリガーされます。DownloadManager.Request.setDestinationInExternalFilesDir()
またはDownloadManager.Request.setDestinationInExternalPublicDir()
を使用してダウンロード先を一般公開されている場所に設定する以前のアプリでも、COLUMN_LOCAL_FILENAME
内のパスにアクセスできますが、この方法はおすすめしません。DownloadManager
によって公開されるファイルにアクセスする場合は、ContentResolver.openFileDescriptor()
を使用することをおすすめします。
アプリ間でのファイル共有
Android 7.0 をターゲットとするアプリの場合、Android フレームワークは file://
URI をアプリ外で公開することを禁止する StrictMode
API ポリシーを適用します。ファイル URI を含むインテントがアプリから離れると、アプリは FileUriExposedException
例外で失敗します。
アプリ間でファイルを共有するには、content://
URI を送信し、その URI に対する一時的なアクセス権を付与する必要があります。この権限を付与する最も簡単な方法は、FileProvider
クラスを使用することです。権限とファイルの共有の詳細については、ファイルを共有するをご覧ください。
ユーザー補助機能の改善
Android 7.0 には、ロービジョンまたは視覚障がいのあるユーザー向けのプラットフォームのユーザビリティを改善することを目的とした変更が含まれています。通常、これらの変更ではアプリのコードを変更する必要はありませんが、これらの機能を確認し、アプリでテストして、ユーザー エクスペリエンスへの潜在的な影響を評価する必要があります。
画面のズーム
Android 7.0 では、表示サイズを設定して、画面上のすべての要素を拡大または縮小できます。これにより、ロービジョンのユーザー向けのデバイスの利便性が向上します。 sw320dp の最小画面幅(一般的な中型スマートフォンである Nexus 4 の幅)を超えて画面を拡大することはできません。
デバイス密度が変更されると、次の方法で実行中のアプリに通知します。
- API レベル 23 以前をターゲットとしているアプリの場合、システムはすべてのバックグラウンド プロセスを自動的に強制終了します。つまり、ユーザーがこのようなアプリから切り替えて [設定] 画面を開き、[表示サイズ] 設定を変更すると、メモリ不足の場合と同じ方法でアプリが強制終了されます。アプリにフォアグラウンド プロセスがある場合、デバイスの向きが変更された場合と同様に、実行時の変更の処理で説明されているように、これらのプロセスに対して構成の変更が通知されます。
- Android 7.0 をターゲットとするアプリの場合は、実行時の変更の処理で説明しているように、構成の変更がすべてのプロセス(フォアグラウンドとバックグラウンド)に通知されます。
Android のベスト プラクティスに沿っていれば、ほとんどのアプリでこの機能をサポートするために変更を加える必要はありません。具体的な確認事項:
- 画面幅が
sw320dp
のデバイスでアプリをテストし、適切に動作することを確認してください。 - デバイス構成が変更されたときは、キャッシュされたビットマップやネットワークから読み込まれたリソースなど、密度に依存するキャッシュ情報を更新します。アプリが一時停止状態から再開したら、構成の変更を確認します。
注: 構成に依存するデータをキャッシュに保存する場合は、そのデータに適した画面サイズやピクセル密度など、関連するメタデータを含めることをおすすめします。このメタデータを保存すると、構成の変更後にキャッシュ データを更新する必要があるかどうかを決定できます。
- 画面密度に合わせて拡大縮小されないため、px 単位で寸法を指定しないでください。代わりに、密度非依存ピクセル(
dp
)の単位を使用して寸法を指定します。
セットアップ ウィザードの [Vision Settings]
Android 7.0 には、ウェルカム画面に [Vision Settings] があります。これにより、ユーザーは新しいデバイスの拡大操作、フォントサイズ、表示サイズ、TalkBack のユーザー補助設定をセットアップできます。この変更により、さまざまな画面設定に関連するバグが目に留まりやすくなります。この機能の影響を評価するには、これらの設定を有効にしてアプリをテストする必要があります。設定には [設定] > [ユーザー補助] を選択します。
プラットフォーム ライブラリにリンクしている NDK アプリ
Android 7.0 以降では、アプリが NDK 以外のライブラリを動的にリンクできないようになっています。これにより、アプリがクラッシュする可能性があります。この動作変更は、プラットフォーム アップデートやさまざまなデバイスで一貫したアプリ エクスペリエンスを提供することを目的としています。コードがプライベート ライブラリにリンクしていなくても、アプリ内のサードパーティの静的ライブラリがリンクしている可能性があります。したがって、すべてのデベロッパーは、Android 7.0 搭載デバイスでアプリがクラッシュしないことを確認する必要があります。アプリでネイティブ コードを使用する場合は、パブリック NDK API のみを使用してください。
アプリがプライベート プラットフォーム API にアクセスしようとする方法は 3 つあります。
- アプリがプライベート プラットフォーム ライブラリに直接アクセスしている。これらのライブラリの独自のコピーを含めるようにアプリを更新するか、パブリック NDK API を使用する必要があります。
- プライベート プラットフォーム ライブラリにアクセスするサードパーティ ライブラリをアプリが使用している。アプリがプライベート ライブラリに直接アクセスしないことが確実であっても、このシナリオについてアプリをテストする必要があります。
- アプリが APK に含まれていないライブラリを参照しています。たとえば、OpenSSL を独自にコピーして使用しようとしたものの、それをアプリの APK にバンドルし忘れた場合に発生します。
libcrypto.so
を含むバージョンの Android プラットフォームでは、アプリは通常どおり実行できます。ただし、このライブラリが含まれていない新しいバージョンの Android(Android 6.0 以降など)では、アプリがクラッシュする可能性があります。この問題を解決するには、NDK 以外のライブラリをすべて APK にバンドルしてください。
NDK に含まれていないネイティブ ライブラリは、Android のバージョン間で変更または削除される可能性があるため、アプリでは使用しないでください。OpenSSL から BoringSSL への切り替えは、そのような変更の例です。また、NDK に含まれていないプラットフォーム ライブラリには互換性要件がないため、デバイスによって互換性レベルが異なる場合があります。
この制限が現在リリースされているアプリに及ぼす影響を軽減するために、API レベル 23 以下をターゲットとするアプリの場合、Android 7.0(API レベル 24)では、頻繁に使用されるライブラリのセット(libandroid_runtime.so
、libcutils.so
、libcrypto.so
、libssl.so
など)に一時的にアクセスできます。アプリがこのようなライブラリを読み込むと、logcat が警告を生成し、ターゲット デバイスにトーストを表示して通知します。これらの警告が表示された場合は、これらのライブラリの独自のコピーを含めるか、パブリック NDK API のみを使用するようにアプリを更新する必要があります。Android プラットフォームの今後のリリースでは、プライベート ライブラリの使用が完全に制限され、アプリがクラッシュする可能性があります。
どのアプリも、公開されていない API や一時的にアクセスできない API を呼び出すと、ランタイム エラーを生成します。その結果、System.loadLibrary
と dlopen(3)
はどちらも NULL
を返し、アプリがクラッシュする可能性があります。アプリコードを確認して非公開プラットフォーム API の使用を削除し、Android 7.0(API レベル 24)を搭載したデバイスまたはエミュレータでアプリを十分にテストする必要があります。アプリがプライベート ライブラリを使用しているかどうか不明な場合は、logcat を確認してランタイム エラーを特定できます。
プライベート ネイティブ ライブラリの使用と対象 API レベル(android:targetSdkVersion
)に応じてアプリで想定される動作を次の表に示します。
ライブラリ | 対象 API レベル | ダイナミック リンカーを介したランタイム アクセス | Android 7.0(API レベル 24)の動作 | 今後の Android プラットフォームの動作 |
---|---|---|---|---|
NDK パブリック | すべて | ユーザー補助 | 期待どおりに動作 | 期待どおりに動作 |
個人用(一時的にアクセス可能な個人用ライブラリ) | 23 以下 | 一時的にアクセス可能 | 想定どおりに機能しますが、logcat 警告が表示されます。 | ランタイム エラー |
個人用(一時的にアクセス可能な個人用ライブラリ) | 24 以上 | 制限付き | ランタイム エラー | ランタイム エラー |
非公開(その他) | すべて | 制限付き | ランタイム エラー | ランタイム エラー |
アプリがプライベート ライブラリを使用しているかどうかを確認する
プライベート ライブラリの読み込みに関する問題を特定しやすくするために、logcat で警告やランタイム エラーが生成されることがあります。たとえば、API レベル 23 以前をターゲットとしているアプリが、Android 7.0 を搭載しているデバイスのプライベート ライブラリにアクセスしようとすると、次のような警告が表示されることがあります。
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so" ("/system/lib/libandroid_runtime.so") needed or dlopened by "/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible for the namespace "classloader-namespace" - the access is temporarily granted as a workaround for http://b/26394120
この logcat 警告は、どのライブラリが非公開プラットフォーム API にアクセスしようとしているかを示しますが、アプリがクラッシュを引き起こすことはありません。ただし、API レベル 24 以降をターゲットとしているアプリの場合、logcat で次のランタイム エラーが生成され、アプリがクラッシュする可能性があります。
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so" ("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace" at java.lang.Runtime.loadLibrary0(Runtime.java:977) at java.lang.System.loadLibrary(System.java:1602)
また、プライベート プラットフォーム API に動的にリンクするサードパーティ ライブラリをアプリが使用している場合も、このような logcat 出力が表示されることがあります。Android 7.0DK の readelf ツールを使用すると、次のコマンドを実行すると、特定の .so
ファイルに動的にリンクされたすべての共有ライブラリのリストを生成できます。
aarch64-linux-android-readelf -dW libMyLibrary.so
アプリを更新する
このタイプのエラーを修正し、今後のプラットフォーム アップデートでアプリがクラッシュしないようにする手順を以下に示します。
- アプリでプライベート プラットフォーム ライブラリを使用している場合は、ライブラリを更新してそのライブラリ独自のコピーを組み込むか、パブリック NDK API を使用する必要があります。
- プライベート シンボルにアクセスするサードパーティ ライブラリをアプリで使用している場合は、ライブラリの作成者に連絡してライブラリを更新してください。
- NDK 以外のライブラリはすべて APK にパッケージ化してください。
libandroid_runtime.so
のgetJavaVM
とgetJNIEnv
の代わりに、標準の JNI 関数を使用します。AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or JavaVM::AttachCurrentThread from <jni.h>.
libcutils.so
のプライベートproperty_get
シンボルの代わりに__system_property_get
を使用します。これを行うには、次のインクルードを指定して__system_property_get
を使用します。#include <sys/system_properties.h>
注: システム プロパティの可用性と内容は、CTS ではテストされません。これらのプロパティを完全に使用しないことをおすすめします。
libcrypto.so
のSSL_ctrl
シンボルのローカル バージョンを使用します。たとえば、.so
ファイル内でlibcyrpto.a
を静的にリンクするか、BoringSSL/OpenSSL の動的にリンクされたバージョンのlibcrypto.so
をインクルードして APK にパッケージ化します。
Android for Work
Android 7.0 では、Android for Work をターゲットとするアプリに関して、証明書のインストール、パスワードの再設定、セカンダリ ユーザーの管理、デバイス ID へのアクセスなどに関する変更が行われています。Android for Work 環境向けのアプリを作成する場合は、変更内容を確認し、適宜アプリを修正する必要があります。
- DPC で委任証明書インストーラを設定する前に、委任証明書インストーラをインストールする必要があります。Android 7.0(API レベル 24)を対象とするプロファイル アプリとデバイス所有者アプリの両方で、Device Policy Controller(DPC)が
DevicePolicyManager.setCertInstallerPackage()
を呼び出す前に、委任証明書インストーラをインストールする必要があります。インストーラがまだインストールされていない場合、IllegalArgumentException
がスローされます。 - デバイス管理者のパスワードの再設定制限がプロファイル オーナーに適用されるようになりました。デバイス管理者は、
DevicePolicyManager.resetPassword()
を使用してパスワードをクリアしたり、設定済みのパスワードを変更したりできなくなりました。デバイス管理者は、デバイスにパスワード、PIN、パターンが設定されていない場合にのみパスワードを設定できます。 - 制限が設定されていても、デバイス オーナーとプロファイル オーナーはアカウントを管理できます。デバイス所有者とプロファイル所有者は、
DISALLOW_MODIFY_ACCOUNTS
ユーザー制限が設定されている場合でも、Account Management API を呼び出すことができます。 - デバイス所有者は、セカンダリ ユーザーをより簡単に管理できます。デバイスがデバイス所有者モードで実行されている場合は、
DISALLOW_ADD_USER
制限が自動的に設定されます。これにより、ユーザーが管理対象外のセカンダリ ユーザーを作成できなくなります。また、CreateUser()
メソッドとcreateAndInitializeUser()
メソッドのサポートが終了し、新しいDevicePolicyManager.createAndManageUser()
メソッドに置き換えられました。 - デバイス所有者はデバイス ID にアクセスできます。デバイス オーナーは、
DevicePolicyManager.getWifiMacAddress()
を使用してデバイスの Wi-Fi MAC アドレスにアクセスできます。デバイスで Wi-Fi が有効にされたことがない場合、このメソッドはnull
の値を返します。 - ワークモードの設定により、仕事用アプリへのアクセスが管理されます。仕事用モードがオフの場合、システム ランチャーは仕事用アプリをグレー表示して使用できないことを示します。ワークモードを再度有効にすると、通常の動作が復元されます。
- クライアント証明書チェーンと対応する秘密鍵を含む PKCS #12 ファイルを設定 UI からインストールすると、チェーン内の CA 証明書が信頼できる認証情報ストレージにインストールされなくなります。後でアプリがクライアント証明書チェーンを取得しようとしたときの
KeyChain.getCertificateChain()
の結果には影響しません。必要に応じて、設定 UI から CA 証明書を信頼できる認証情報ストレージに別途インストールする必要があります。その際、DER エンコード形式の .crt または .cer ファイル拡張子を使用します。 - Android 7.0 以降、指紋の登録と保存はユーザーごとに管理されます。Android 7.0(API レベル 24)を搭載したデバイスで、プロファイル所有者のデバイス ポリシー クライアント(DPC)が API レベル 23 以前をターゲットとしている場合、ユーザーはデバイスに指紋を設定できますが、仕事用アプリはデバイスのフィンガープリントにアクセスできません。DPC が API レベル 24 以降をターゲットとしている場合、ユーザーは [設定] > [セキュリティ] > [仕事用プロファイルのセキュリティ] に移動して、仕事用プロファイル専用の指紋を設定できます。
DevicePolicyManager.getStorageEncryptionStatus()
によって新しい暗号化ステータスENCRYPTION_STATUS_ACTIVE_PER_USER
が返されます。これは、暗号化が有効で、暗号鍵がユーザーに関連付けられていることを示します。新しいステータスは、DPC の対象が API レベル 24 以降である場合にのみ返されます。それより前の API レベルをターゲットとするアプリの場合、暗号鍵がユーザーやプロファイルに固有のものであっても、ENCRYPTION_STATUS_ACTIVE
が返されます。- Android 7.0 では、個別のワーク チャレンジで仕事用プロファイルがデバイスにインストールされている場合、通常はデバイス全体に影響するいくつかのメソッドの動作が変わります。これらのメソッドはデバイス全体ではなく、仕事用プロファイルにのみ適用されます。(このようなメソッドの完全なリストは、
DevicePolicyManager.getParentProfileInstance()
ドキュメントにあります)。たとえば、DevicePolicyManager.lockNow()
と指定すると、デバイス全体ではなく、仕事用プロファイルのみがロックされます。これらの各メソッドについて、DevicePolicyManager
の親インスタンスでメソッドを呼び出すことで、以前の動作を取得できます。この親を取得するには、DevicePolicyManager.getParentProfileInstance()
を呼び出します。たとえば、親インスタンスのlockNow()
メソッドを呼び出すと、デバイス全体がロックされます。
アノテーションの保持
Android 7.0 では、アノテーションの表示が無視されていたバグが修正されました。この問題により、ランタイムが本来はアクセスできないはずのアノテーションにアクセスできました。これらのアノテーションには次のものが含まれていました。
VISIBILITY_BUILD
: ビルド時にのみ表示されることを想定しています。VISIBILITY_SYSTEM
: 実行時に表示されますが、基盤となるシステムにのみ表示されます。
アプリがこの動作に依存している場合は、実行時に利用できるようにする必要があるアノテーションに保持ポリシーを追加してください。そのためには、@Retention(RetentionPolicy.RUNTIME)
を使用します。
TLS/SSL のデフォルト構成の変更
Android 7.0 では、アプリが HTTPS や他の TLS/SSL トラフィックに使用するデフォルトの TLS/SSL 構成が次のように変更されています。
- RC4 暗号スイートが無効になりました。
- CHACHA20-POLY1305 暗号スイートが有効になりました。
RC4 がデフォルトで無効になっている場合、サーバーが最新の暗号スイートをネゴシエートしない場合、HTTPS 接続または TLS/SSL 接続が切断される可能性があります。 推奨される修正は、サーバーの設定を改善して、より強力で最新の暗号スイートとプロトコルを有効にすることです。理想的には、TLSv1.2 と AES-GCM を有効にして、前方秘匿性暗号スイート(ECDHE)を有効にして優先します。
または、カスタムの SSLSocketFactory
を使用してサーバーと通信するようにアプリを変更することもできます。ファクトリは、デフォルトの暗号スイートに加えて、サーバーが必要とする暗号スイートの一部が有効になった SSLSocket
インスタンスを作成するように設計する必要があります。
注: これらの変更は WebView
には関係ありません。
Android 7.0 をターゲットとするアプリ
これらの動作変更は、Android 7.0(API レベル 24)以降をターゲットとするアプリにのみ適用されます。Android 7.0 でコンパイルするアプリや、targetSdkVersion
を Android 7.0 以降に設定するアプリは、必要に応じてアプリを変更して、上記の動作を適切にサポートする必要があります。
シリアル化の変更
Android 7.0(API レベル 24)では、デフォルトの serialVersionUID の計算で仕様と一致しないバグを修正しました。
Serializable
を実装し、明示的な serialVersionUID
フィールドを指定していないクラスでは、デフォルトの serialVersionUID が変更され、以前のバージョンでシリアル化されたクラスまたは以前のバージョンをターゲットとするアプリによってシリアル化されたクラスのインスタンスを逆シリアル化しようとすると、例外がスローされます。次のようなエラー メッセージが表示されます。
local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567
これらの問題を修正するには、影響を受けるすべてのクラスに、エラー メッセージの stream classdesc
serialVersionUID
の値(この場合は 1234
)とともに serialVersionUID
フィールドを追加する必要があります。この変更は、シリアル化コードの記述に関するすべてのおすすめの方法を遵守しており、Android のすべてのバージョンで機能します。
修正された特定のバグは、静的初期化メソッド(<clinit>
)の存在に関連するものでした。この仕様では、クラス内の静的初期化メソッドの有無が、そのクラスに対して計算されたデフォルトの serialVersionUID に影響します。バグの修正前、クラスに静的イニシャライザがない場合は、スーパークラスに静的イニシャライザがあるかどうかもチェックされていました。
明確に言うと、この変更は、API レベル 23 以前をターゲットとするアプリ、serialVersionUID
フィールドを持つクラス、または静的イニシャライザ メソッドを持つクラスには影響しません。
その他の重要事項
- アプリが Android 7.0 で実行されているものの、ターゲット API レベルが低い場合、ユーザーがディスプレイ サイズを変更すると、アプリプロセスは強制終了されます。アプリは、このシナリオを適切に処理できる必要があります。そうしないと、ユーザーが [最近] から復元したときにクラッシュします。
アプリをテストして、この動作が発生しないことを確認する必要があります。これを行うには、DDMS を介してアプリを手動で強制終了するときに同じクラッシュを発生させます。
Android 7.0(API レベル 24)以降をターゲットとするアプリは、密度を変更しても自動的に強制終了されることはありませんが、構成の変更には適切に反応しない場合があります。
- Android 7.0 上のアプリは構成の変更を適切に処理でき、その後の起動時にクラッシュしないようにする必要があります。アプリの動作を確認するには、フォントサイズを変更して([設定] > [ディスプレイ] > [フォントサイズ])、[履歴] からアプリを復元します。
-
以前のバージョンの Android のバグにより、メインスレッドの TCP ソケットへの書き込みは厳格モード違反として報告されませんでした。このバグは Android 7.0 で修正されています。
この動作を示すアプリは、
android.os.NetworkOnMainThreadException
をスローするようになりました。 通常、メインスレッドでネットワーク オペレーションを実行することはおすすめできません。これらのオペレーションでは通常、レイテンシが高く、ANR やジャンクが発生します。 -
メソッドの
Debug.startMethodTracing()
ファミリーはデフォルトで、SD カードの最上位ではなく、共有ストレージのパッケージ固有のディレクトリに出力を保存するようになりました。つまり、これらの API を使用するために、アプリがWRITE_EXTERNAL_STORAGE
権限をリクエストする必要がなくなりました。 -
多くのプラットフォーム API で、
Binder
トランザクションで送信される大きなペイロードのチェックが開始され、システムはTransactionTooLargeExceptions
を通知なくロギングまたは抑制するのではなく、RuntimeExceptions
として再スローするようになりました。一般的な例としては、Activity.onSaveInstanceState()
に保存しているデータが多すぎることが挙げられます。これにより、アプリが Android 7.0 をターゲットとする場合、ActivityThread.StopInfo
がRuntimeException
をスローします。 -
アプリが
Runnable
タスクをView
に送信し、View
がウィンドウにアタッチされていない場合、システムはRunnable
タスクをView
でキューに登録します。Runnable
タスクは、View
がウィンドウに接続されるまで実行されません。この動作により、次のバグが修正されます。 -
DELETE_PACKAGES
権限を持つ Android 7.0 のアプリがパッケージを削除しようとしたときに、別のアプリがそのパッケージをインストールしていた場合、システムはユーザーの確認を必要とします。このシナリオでは、アプリがPackageInstaller.uninstall()
を呼び出したときの戻りステータスとしてSTATUS_PENDING_USER_ACTION
を想定する必要があります。 - Crypto という JCA プロバイダは非推奨となりました。このプロバイダの唯一のアルゴリズム SHA1PRNG は暗号的に弱いためです。このプロバイダが利用できなくなったため、アプリは SHA1PRNG を使用して(安全でない状態で)鍵を導出できなくなりました。詳しくは、Android N でサポートが終了したセキュリティ「暗号」プロバイダのブログ投稿をご覧ください。