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 モードになってから一定の時間が経過するまでデバイスが静止状態になると、残りの Doze 制限が PowerManager.WakeLockAlarmManager アラーム、GPS、Wi-Fi スキャンに適用されます。適用されている 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 フレームワークによって StrictMode API ポリシーが適用され、file:// URI をアプリの外部に公開することが禁止されています。ファイル 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 のデバイスでアプリをテストし、適切に機能することを確認します。
  • デバイス構成が変更された場合は、キャッシュされたビットマップやネットワークから読み込まれたリソースなど、密度依存のキャッシュ情報を更新します。アプリが一時停止状態から再開したら、構成の変更を確認します。

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

  • 寸法は画面密度に応じて調整されないため、ピクセル単位では寸法を指定しないでください。代わりに、密度非依存ピクセル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 に含まれていないプラットフォーム ライブラリには互換性要件がないため、デバイスによって互換性レベルが異なる場合があります。

この制限が現在リリースされているアプリに及ぼす影響を軽減するために、API レベル 23 以前を対象とするアプリの場合、Android 7.0(API レベル 24)では、使用頻度が高い一連のライブラリ(libandroid_runtime.solibcutils.solibcrypto.solibssl.so など)に一時的にアクセスできます。アプリが上記のライブラリのいずれかを読み込むと、logcat が警告を生成し、ターゲット デバイスにトースト通知を表示します。この警告が表示された場合は、アプリを更新してこれらのライブラリの独自のコピーを含めるか、公開 NDK API のみを使用してください。Android プラットフォームの今後のリリースでは、プライベート ライブラリの使用が完全に制限され、アプリがクラッシュする可能性があります。

公開されていない API も、一時的にアクセスもできない API を呼び出した場合、すべてのアプリでランタイム エラーが発生します。その結果、System.loadLibrarydlopen(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.sogetJavaVMgetJNIEnv の代わりに標準 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.soSSL_ctrl シンボルのローカル バージョンを使用します。たとえば、.so ファイルで libcyrpto.a を静的にリンクするか、BoringSSL/OpenSSL の動的にリンクされた libcrypto.so バージョンを組み込んで APK にパッケージ化します。

Android for Work

Android 7.0 には、証明書のインストール、パスワードの再設定、二次的なユーザー管理、デバイス ID へのアクセスに関する変更など、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() メソッドに置き換えられました。
  • デバイス オーナーはデバイス ID にアクセスできます。デバイス オーナーは、DevicePolicyManager.getWifiMacAddress() を使用してデバイスの Wi-Fi MAC アドレスにアクセスできます。デバイスで Wi-Fi が有効にされたことがない場合、このメソッドは null 値を返します。
  • ワークモード設定では、仕事用アプリへのアクセスを制御します。仕事用モードがオフの場合、システム ランチャーは仕事用アプリがグレー表示になります。ワークモードを再度有効にすると、通常の動作が復元されます。
  • 設定 UI からクライアント証明書チェーンと対応する秘密鍵を含む PKCS #12 ファイルをインストールすると、チェーン内の CA 証明書が信頼できる認証情報ストレージにインストールされなくなります。後でアプリがクライアント証明書チェーンを取得しようとしたときの KeyChain.getCertificateChain() の結果には影響しません。必要に応じて、設定 UI から信頼できる認証情報ストレージに CA 証明書を別途インストールする必要があります。その際、DER エンコード形式で、拡張子が .crt または .cer の CA 証明書を使用します。
  • 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)を有効にして優先します。

もう 1 つの方法は、カスタム 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.StopInfoRuntimeException をスローします。
  • アプリが Runnable タスクを View に送信し、View がウィンドウにアタッチされていない場合、システムは Runnable タスクを View でキューに入れます。View がウィンドウにアタッチされるまで、Runnable タスクは実行されません。この動作により、次のバグが修正されます。
    • 目的のウィンドウの UI スレッド以外のスレッドからアプリが View に送信された場合、結果として Runnable が誤ったスレッドで実行される可能性があります。
    • Runnable タスクが Looper スレッド以外のスレッドから POST の場合、アプリは Runnable タスクを公開できます。
  • DELETE_PACKAGES 権限がある Android 7.0 のアプリがパッケージを削除しようとしたときに、別のアプリがそのパッケージをインストールしていた場合、システムはユーザーによる確認を要求します。このシナリオでは、アプリは、PackageInstaller.uninstall() を呼び出したときのリターン ステータスとして STATUS_PENDING_USER_ACTION を想定する必要があります。
  • Crypto という JCA プロバイダは非推奨になりました。これは、唯一のアルゴリズム SHA1PRNG が暗号的に脆弱であるためです。このプロバイダは利用できなくなったため、アプリは SHA1PRNG を使用して(安全でない)鍵を導出できなくなりました。詳細については、Android N でサポートが終了したセキュリティ「暗号」プロバイダのブログ投稿をご覧ください。