Android 7.0 の動作の変更点

Android 7.0 には、新機能や新機能に加えて、さまざまなシステムと API の動作変更が含まれています。このドキュメントでは、アプリで理解して考慮する必要がある主な変更点について説明します。

以前に Android 向けアプリを公開したことがある場合は、プラットフォームの変更がアプリに影響する可能性があることに注意してください。

バッテリーとメモリ

Android 7.0 では、デバイスのバッテリー駆動時間を延ばし、RAM の使用量を削減することを目的として、システムの動作が変更されています。これらの変更は、アプリによるシステム リソースへのアクセスや、特定の暗黙的インテントを使用したアプリと他のアプリとの連携に影響する可能性があります。

Doze

Android 6.0(API レベル 23)で導入された Doze モードは、ユーザーがデバイスを電源に接続せず、静止状態で画面をオフにしているときに、CPU とネットワーク アクティビティを保留にすることで、電池寿命を延ばします。Android 7.0 では、デバイスが電源に接続されておらず、画面がオフになっているときに、CPU とネットワークの制限のサブセットを適用することで、Doze モードをさらに強化しています。この場合、デバイスは必ずしも静止状態である必要はありません。たとえば、ユーザーがポケットに入れて持ち歩いている場合などです。

Doze モードが第 1 レベルのシステム アクティビティ制限を適用してバッテリー駆動時間を改善する仕組みの図

図 1. Doze がシステム アクティビティの第 1 レベルの制限を適用してバッテリー駆動時間を改善する仕組みの図。

デバイスがバッテリー電源で動作しており、画面が一定時間オフになっていると、デバイスは Doze モードに入り、最初の制限のサブセットを適用します。つまり、アプリのネットワーク アクセスを遮断し、ジョブと同期を保留します。Doze に入ってから一定時間デバイスが静止している場合、システムは PowerManager.WakeLock、AlarmManager アラーム、GPS、Wi-Fi スキャンに Doze の残りの制限を適用します。Doze の制限の一部またはすべてが適用されているかどうかにかかわらず、システムは短いメンテナンスの時間枠のためにデバイスを復帰させます。この時間枠の間、アプリはネットワークにアクセスでき、延期されたジョブや同期を実行できます。

デバイスが一定時間静止した後に、Doze が第 2 レベルのシステム アクティビティ制限を適用する仕組みの図

図 2. デバイスが一定時間静止した後に、Doze が第 2 レベルのシステム アクティビティ制限を適用する仕組みの図。

なお、画面をオンにするか、デバイスを電源に接続すると、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 の幅)を超えてズームすることはできません。

Android 7.0 システム イメージを搭載したデバイスのズームされていない表示サイズを示す画面
Android 7.0 システム イメージを搭載したデバイスの表示サイズを拡大した効果を示す画面

図 3. 右側の画面は、Android 7.0 システム イメージを搭載したデバイスの表示サイズを大きくした場合の効果を示しています。

デバイスの密度が変化すると、システムは次の方法で実行中のアプリに通知します。

  • アプリが対象 API レベル 23 以下をターゲットとしている場合、システムはアプリのすべてのバックグラウンド プロセスを自動的に強制終了します。つまり、ユーザーがこのようなアプリから切り替えて [設定] 画面を開き、[表示サイズ] の設定を変更すると、システムはメモリ不足の場合と同じようにアプリを強制終了します。アプリにフォアグラウンド プロセスがある場合、システムは、実行時の変更の処理で説明されているように、デバイスの向きが変更された場合と同様に、構成の変更をそれらのプロセスに通知します。
  • アプリが Android 7.0 をターゲットとしている場合、実行時の変更の処理で説明されているように、すべてのプロセス(フォアグラウンドとバックグラウンド)に構成の変更が通知されます。

ほとんどのアプリは、Android のベスト プラクティスに沿っていれば、この機能をサポートするために変更を加える必要はありません。具体的な確認事項は次のとおりです。

  • 画面幅が sw320dp のデバイスでアプリをテストし、適切に動作することを確認します。
  • デバイス設定が変更されたら、キャッシュに保存されたビットマップやネットワークから読み込まれたリソースなど、密度に依存するキャッシュ情報を更新します。アプリが一時停止状態から再開したときに、構成の変更を確認します。

    注: 構成に依存するデータをキャッシュに保存する場合は、そのデータに適した画面サイズやピクセル密度などの関連メタデータを含めることをおすすめします。このメタデータを保存すると、構成の変更後にキャッシュに保存されたデータを更新する必要があるかどうかを判断できます。

  • px 単位で寸法を指定すると、画面密度に応じて拡大縮小されないため、px 単位での指定は避けてください。代わりに、密度非依存ピクセル(dp)単位でサイズを指定します。

設定ウィザードの視覚補助

Android 7.0 では、ウェルカム画面に視覚設定が含まれており、ユーザーは新しいデバイスで拡大操作、フォントサイズ、表示サイズ、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 に含まれていないプラットフォーム ライブラリには互換性要件がないため、デバイスによって互換性のレベルが異なる場合があります。

この制限が現在リリースされているアプリに及ぼす影響を軽減するため、libandroid_runtime.so、libcutils.so、libcrypto.so、libssl.so など、頻繁に使用される一連のライブラリは、API レベル 23 以下を対象 API レベルとするアプリ向けに、Android 7.0(API レベル 24)で一時的にアクセスできるようになっています。アプリがこれらのライブラリのいずれかを読み込むと、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 Public 指定なし バリアフリー 想定どおりに動作する 想定どおりに動作する
非公開(一時的にアクセス可能な非公開ライブラリ) 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.0 NDK の 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 を使用します。これを行うには、次の include を指定して __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 を対象とするアプリ向けの変更が含まれています。これには、証明書のインストール、パスワードの再設定、セカンダリ ユーザーの管理、デバイス識別子へのアクセスに関する変更が含まれます。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() メソッドに置き換えられました。
  • デバイス所有者はデバイス識別子にアクセスできます。デバイス所有者は、DevicePolicyManager.getWifiMacAddress() を使用してデバイスの Wi-Fi MAC アドレスにアクセスできます。デバイスで Wi-Fi が有効になったことがない場合、このメソッドは null の値を返します。
  • 仕事モードの設定では、仕事用アプリへのアクセスを管理します。仕事用モードがオフの場合、システム ランチャーは仕事用アプリをグレー表示にして、利用できないことを示します。仕事モードを再度有効にすると、通常の動作に戻ります。
  • 設定 UI から、クライアント証明書チェーンと対応する秘密鍵を含む PKCS #12 ファイルをインストールする場合、チェーン内の CA 証明書は信頼できる認証情報ストレージにインストールされなくなりました。これは、アプリが後でクライアント証明書チェーンを取得しようとしたときの KeyChain.getCertificateChain() の結果には影響しません。必要に応じて、CA 証明書を、設定 UI を使用して信頼できる認証情報ストレージに別途インストールする必要があります。その際、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

これらの問題を解決するには、影響を受けるクラスに serialVersionUID フィールドを追加し、エラー メッセージの stream classdesc serialVersionUID の値(この場合は 1234)を指定する必要があります。この変更は、シリアル化コードを記述するためのすべての推奨事項に準拠しており、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 がウィンドウにアタッチされるまで実行されません。この動作により、次のバグが修正されます。
    • アプリが目的のウィンドウの UI スレッド以外のスレッドから View にポストした場合、結果として Runnable が間違ったスレッドで実行される可能性があります。
    • Runnable タスクがルーパー スレッド以外のスレッドからポストされた場合、アプリは Runnable タスクを公開する可能性があります。
  • Android 7.0 で DELETE_PACKAGES 権限を持つアプリがパッケージを削除しようとしたときに、別のアプリがそのパッケージをインストールしていた場合、システムはユーザーに確認を求めます。このシナリオでは、アプリが PackageInstaller.uninstall() を呼び出すと、戻りステータスとして STATUS_PENDING_USER_ACTION が返されます。
  • Crypto という JCA プロバイダは、唯一のアルゴリズムである SHA1PRNG の暗号強度が弱いため、非推奨となっています。このプロバイダは利用できなくなったため、アプリは SHA1PRNG を使用して(安全でない方法で)鍵を導出できなくなりました。詳細については、ブログ投稿 Android N で非推奨となったセキュリティ「Crypto」プロバイダをご覧ください。