Android 7.0 の動作の変更点

新しい機能に加えて、Android 7.0 では、さまざまなシステムおよび API の動作が変更されています。このドキュメントでは、アプリ開発において把握しておくべき主な変更点について説明します。

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

電池とメモリ

Android 7.0 では、端末の電池寿命を改善したり、RAM の使用量を削減したりするために、システムの動作がいくつか変更されています。これらの変更は、システム リソースへのアプリのアクセスに加え、特定の暗黙的インテントを介して他のアプリとやり取りする方法に影響を及ぼす可能性があります。

Doze

Android 6.0(API レベル 23)で Doze が導入されました。これは、ユーザーが端末を電源と接続せずに静止状態にし、画面をオフにすると、CPU とネットワークのアクティビティを保留して電池の寿命を改善するものです。Android 7.0 では、Doze が改良されています。端末を電源と接続せずに画面をオフにすると、端末が静止していなくても(たとえば、ユーザーがハンドセットをポケットに入れて持ち歩いている場合)、CPU およびネットワーク制限のサブセットがアプリに適用されます。

図 1. Doze が第 1 レベルのシステム アクティビティ制限を適用して、電池の寿命を改善

端末が電池で動作しているときに画面をしばらくオフにすると、端末は Doze モードになり、第一段階の制限サブセットが適用されます。これにより、アプリのネットワーク アクセスが切断されてジョブと同期が保留されます。端末が Doze モードに入った後、しばらくの間静止状態が続くと、残りの Doze 制限が PowerManager.WakeLockAlarmManager アラーム、GPS、Wi-Fi スキャンに適用されます。適用される Doze 制限が一部であるか完全なものであるかには関係なく、端末は Doze モードから短時間抜け出し、メンテナンスの時間枠と呼ばれる状態になります。このとき、アプリはネットワーク アクセスを許可され、保留されたジョブや同期を実行することができます。

図 2. 端末がしばらくの間静止状態になると、Doze が第 2 レベルのシステム アクティビティ制限を適用する

画面をオンにするか、端末を電源に接続すると、Doze モードは解除され、これらの処理の制限は適用されなくなります。Doze とアプリ スタンバイ用に最適化するで説明したように、今回追加された動作は、Android 6.0(API レベル 23)で導入された以前のバージョンの Doze にアプリを対応させるための推奨事項とベスト プラクティスに影響するものではありません。メッセージの送受信に Google Cloud Messaging(GCM)を使用するなどの推奨事項を引き続き順守して、追加の Doze 動作に対応するためにアップデートを計画してください。

Project Svelte:バックグラウンド処理の最適化

Android 7.0 では、メモリ使用量と消費電力を最適化するために、3 つの暗黙的なブロードキャストが削除されています。この変更が必要になった理由は、暗黙的なブロードキャストが行われると、バックグラウンドでブロードキャストをリッスンするように登録されているアプリが頻繁に起動されるためです。これらのブロードキャストを削除すると端末のパフォーマンスとユーザー エクスペリエンスが大幅に向上します。

モバイル端末では、Wi-Fi とモバイルデータの切り替えなど、接続が頻繁に変化します。現在のアプリでは、暗黙的な CONNECTIVITY_ACTION ブロードキャストのレシーバーをマニフェストに登録することにより、接続状態の変化を監視できるようになっています。多くのアプリがこのブロードキャストを受信する登録を行っているので、一度ネットワークの切り替えが起こるだけですべてのアプリがアクティブになり、ブロードキャストが同時に処理されます。

同様に、旧バージョンの Android では、暗黙的な ACTION_NEW_PICTURE ブロードキャストと ACTION_NEW_VIDEO ブロードキャストをカメラなどの他のアプリから受信するよう登録できました。ユーザーがカメラアプリで写真を撮ると、これらのアプリがアクティブになり、ブロードキャストが処理されます。

Android 7.0 では、こういった問題を軽減するために、以下の最適化手法が適用されます。

  • Android 7.0 向けのアプリは、CONNECTIVITY_ACTION ブロードキャストを受信しません。これは、アプリにこれらのイベントの通知をリクエストするマニフェスト エントリがある場合も同様です。実行されているアプリが BroadcastReceiver で通知をリクエストした場合は、メインスレッドで CONNECTIVITY_CHANGE を引き続きリッスンできます。
  • アプリは、ACTION_NEW_PICTURE ブロードキャストまたは ACTION_NEW_VIDEO ブロードキャストを送受信できません。この最適化は、Android 7.0 向けのアプリだけでなく、すべてのアプリに影響を及ぼします。

アプリでこれらのインテントのいずれかを使用する場合は、Android 7.0 端末でも適切に動作するように、可能な限りインテントとの依存性を削除する必要があります。Android フレームワークは、これらの暗黙的なブロードキャストの必要性を軽減するいくつかのソリューションを提供します。たとえば、JobScheduler API は、従量制ではないネットワークへの接続など、指定された条件のときに、ネットワーク操作をスケジュールするための堅牢なメカニズムを提供します。また、JobScheduler を使用して、コンテンツ プロバイダの変更に対応することもできます。

Android N でのバックグラウンド処理の最適化や、アプリで必要となる対応の詳細については、バックグラウンド処理の最適化をご覧ください。

パーミッションの変更

Android 7.0 では、アプリに影響を及ぼす可能性のあるパーミッションが変更されています。

ファイル システムのパーミッションの変更

プライベート ファイルのセキュリティを強化するために、Android 7.0 以降向けのアプリのプライベート ディレクトリにはアクセス制限があります(0700)。この設定により、サイズや存在など、プライベート ファイルのメタデータの漏洩を防ぐことができます。このパーミッションの変更には、以下のような複数の副作用があります。

  • プライベート ファイルの所有者はこのファイル パーミッションを緩和することができず、MODE_WORLD_READABLEMODE_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 では、ディスプレイ サイズを設定して、画面上のすべての要素を拡大または縮小することができるので、視覚障害のあるユーザーに対する端末のユーザー補助機能が向上しています。ユーザーは、一般的な中くらいのサイズの携帯端末 Nexus 4 の幅である sw320dp の画面最小幅を超えて画面をズームできません。

図 3. 右側の画面では、Android 7.0 システム イメージを実行している端末のディスプレイ サイズを拡大している

端末の画面密度が変更されると、以下の方法で実行中のアプリに通知されます。

  • アプリが API レベル 23 以前をターゲットにしている場合は、すべてのバックグラウンド処理が自動的に強制終了します。つまり、ユーザーがそのようなアプリから移動して [Settings] 画面を開き、[Display size] の設定を変更すると、メモリ不足の場合と同じように、アプリが強制終了します。アプリになんらかのフォアグラウンド処理がある場合は、実行時の変更の処理に記載されている設定変更の処理が通知されます。これは、端末の画面の向きが変わったときの処理と同様です。
  • アプリが Android 7.0 をターゲットにしている場合、実行時の変更の処理に記載されているように、すべての処理(フォアグラウンド処理およびバックグラウンド処理)に対して設定変更が通知されます。

Android のベスト プラクティスに従っているほとんどのアプリでは、この機能をサポートするための変更を加える必要はありません。ただし、以下の点は確認する必要があります。

  • 画面幅 sw320dp の端末でアプリをテストして、適切に機能することを確認します。
  • 端末設定が変更された場合、キャッシュ済みのビットマップやネットワークから読み込まれるリソースなど、画面密度に依存するキャッシュ情報を更新してください。また、アプリが一時停止状態から再開された場合は、設定変更をチェックしてください。

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

  • ピクセル単位は画面密度に対応しないため、ピクセル単位で寸法を指定することは避けてください。その代わり、密度非依存ピクセルdp)単位で寸法を指定します。

セットアップ ウィザードの [Vision Settings]

Android 7.0 には、オープニング画面に [Vision Settings] が追加されています。ユーザーはこれを使用して、新しい端末でズーム操作フォントサイズディスプレイ サイズTalkBack のユーザー補助機能設定を設定できます。この変更により、さまざまな画面設定に関連するバグが顕在化する可能性があります。この機能が及ぼす影響を評価するには、これらの設定を有効にしてアプリをテストする必要があります。設定は、[Settings] > [Accessibility] にあります。

プラットフォーム ライブラリにリンクした NDK アプリ

Android 7.0 以降、NDK 以外のライブラリを動的にリンクできなくなります。その結果、アプリがクラッシュする可能性があります。この動作の変更は、プラットフォームが更新されたり、さまざまな端末で使用したときでもアプリの操作感に一貫性を持たせるためです。自作のコードでプライベート ライブラリにリンクしていなくても、アプリ内のサードパーティの静的ライブラリで 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.solibcutils.solibcrypto.solibssl.so など)は、API レベル 23 以下を対象とするアプリ向けに、Android N で一時的にアクセス可能になっています。アプリがこのようなライブラリを読み込むと、logcat で警告が生成され、対象の端末でトースト通知が表示されます。このような警告が表示されたら、目的のライブラリをコピーして含めるか、パブリック NDK API のみを使用するようにアプリを更新する必要があります。Android プラットフォームの今後のリリースではプライベート ライブラリの使用がすべて制限され、アプリがクラッシュする可能性があります。

パブリック ライブラリではなく一時的なアクセスもできない API を呼び出すと、必ずアプリでランタイムエラーが生成されます。その結果、System.loadLibrarydlopen(3)NULL が返され、アプリがクラッシュする可能性があります。アプリのコードを確認して、プライベート プラットフォーム API を削除し、プレビュー端末またはエミュレータを使用して、アプリを十分にテストしてください。アプリでプライベート ライブラリを使用しているか不明な場合は、logcat を確認してランタイム エラーを特定できます。

次の表に、プライベート ネイティブ ライブラリの使用状況とターゲット API レベル(android:targetSdkVersion)を確認するために調査すべき動作をまとめています。

ライブラリ ターゲット API レベル 動的リンカーからのランタイム アクセス N Developer Preview の動作 N 最終リリース版の動作 将来の Android プラットフォームの動作
NDK パブリック すべて アクセス可能 想定どおりの動作 想定どおりの動作 想定どおりの動作
プライベート(一時的にアクセス可能なプライベート ライブラリ) 23 以降 一時的にアクセス可能 想定どおりの動作。ただし logcat で警告が表示され、対象端末でメッセージが表示される。 想定どおりの動作。ただし 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.sogetJavaVM および getJNIEnv を、標準の JNI 関数で置き換えます。
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • libcutils.soproperty_get シンボルを __system_property_get に置き換えます。これを行うには、次の include 文とともに __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 には、証明書のインストール、パスワードの再設定、セカンダリ ユーザーの管理、端末識別子へのアクセスなど、Android for Work をターゲットにしているアプリに対する変更が含まれています。Android for Work 環境向けのアプリをビルドしている場合、これらの変更点を確認し、変更に応じてアプリを修正する必要があります。

  • DPC が代理証明書を設定する前に、代理証明書インストーラをインストールする必要があります。また、プロファイルと N SDK をターゲットにしているデバイス オーナー アプリに対して、デバイス ポリシー コントローラ(DPC)が DevicePolicyManager.setCertInstallerPackage() を呼び出す前に代理証明書インストーラをインストールする必要があります。このインストーラがインストールされていない場合、IllegalArgumentException がスローされます。
  • 端末管理者向けのパスワードの再設定制限がプロファイル オーナーに適用されます。端末管理者は、DevicePolicyManager.resetPassword() を使用して、既に設定されているパスワードを削除または変更できなくなりました。端末管理者は、端末にパスワード、PIN、またはパターンが設定されていない場合のみ、パスワードを設定できます。
  • デバイス オーナーとプロファイル オーナーは、制限が設定されている場合でもアカウントを管理することができます。デバイス オーナーとプロファイル オーナーは、DISALLOW_MODIFY_ACCOUNTS ユーザー制限が適用されている場合でも Account Management API を呼び出すことができます。
  • デバイス オーナーによるセカンダリ ユーザーの管理がさらに簡単になりました。端末がデバイス オーナー モードで実行されている場合は、DISALLOW_ADD_USER 制限が自動的に設定されます。これにより、管理されていないセカンダリ ユーザーが作成されることを防ぐことができます。また、CreateUser() メソッドと createAndInitializeUser() メソッドは廃止され、新しい DevicePolicyManager.createAndManageUser() メソッドに置き換えられました。
  • デバイス オーナーは、端末識別子にアクセスできます。また、デバイス オーナーは DevicePolicyManagewr.getWifiMacAddress() を使用して、端末の Wi-Fi MAC アドレスにもアクセスできます。端末で Wi-Fi が有効にされたことがない場合、このメソッドは null 値を返します。
  • ワークモード設定により、仕事用アプリへのアクセスが制御されます。ワークモードがオフになると、システム ランチャーは仕事用アプリをグレーアウトしてこれらが利用できないことを示します。ワークモードが再度有効になると、通常の動作に戻ります。
  • [Settings] UI から、クライアント証明書チェーンと対応するプライベート キーを含む PKCS #12 ファイルをインストールすると、それ以降、チェーン内の CA 証明書は信頼される認証情報ストレージにインストールされません。これによって、後でアプリがクライアント証明書チェーンを取得しようとしたとき、KeyChain.getCertificateChain() の結果に影響することはありません。必要に応じて、別途、[Settings] UI から CA 証明書を信頼できる認証情報ストレージにインストールする必要があります。その際は DER エンコード形式で .crt または .cer ファイル拡張子で保存します。
  • Android 7.0 以降、指紋の登録と保存はユーザー単位で管理されます。N 端末でプロファイル オーナーのデバイス ポリシー クライアント(DPC)が N より前のバージョンをターゲットにしている場合、ユーザーは引き続き端末で指紋を登録できますが、仕事用アプリは端末の指紋にアクセスできません。DPC が N 以上をターゲットにしている場合、ユーザーは [Settings] > [Security] > [Work profile security] にアクセスして、仕事用プロファイル専用の指紋を設定できます。
  • 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 での Android for Work の変更の詳細については、Android for Work のアップデートをご覧ください。

アノテーションの保持

Android 7.0 では、アノテーションの表示が無視されていたバグが修正されました。この問題によって、ランタイムがこれまでできなかったアノテーションへのアクセスが可能になっていました。対象となるアノテーションは以下のとおりです。

  • VISIBILITY_BUILD:ビルド時にのみ表示されます。
  • VISIBILITY_SYSTEM:実行時に表示されますが、基幹システムにのみ表示されます。

アプリでこの動作を利用している場合は、実行時に表示されるアノテーションに保持ポリシーを追加してください。これは @Retention(RetentionPolicy.RUNTIME) を使用して実行できます。

その他の重要事項

  • Android 7.0 上で低い API レベルをターゲットにしたアプリが実行されている場合、ユーザーがディスプレイ サイズを変更すると、アプリのプロセスは強制終了されます。アプリは、このシナリオを適切に処理する必要があります。適切に処理しないと、ユーザーが [Recents] からアプリを復元したときに、アプリがクラッシュします。

    この問題が発生しないようにアプリをテストしてください。このテストを行うには、DDMS から手動でアプリを強制終了して、同じクラッシュを発生させます。

    N 以上をターゲットにしたアプリは、画面密度の変更時に自動的に強制終了しませんが、設定変更への対応が不十分なままである可能性があります。

  • Android 7.0 上のアプリは設定変更を適切に処理し、次回の起動時にクラッシュしないようにする必要があります。フォントサイズを変更して([Setting] > [Display] > [Font size])、アプリを [Recents] から復元するとこの動作を確認できます。
  • 旧バージョンの Android では、バグにより、メインスレッドの TCP ソケットへの書き込みを厳格モード違反として報告していませんでした。Android 7.0 ではこのバグが修正されました。この動作が発生したアプリは、android.os.NetworkOnMainThreadException をスローするようになりました。通常、メインスレッドでネットワーク操作を実行することはお勧めできません。このような操作は一般的に ANR やジャンクを引き起こす大幅なテイル レイテンシが発生するためです。
  • メソッドの Debug.startMethodTracing() ファミリーが、SD カードのトップレベルではなく、共有ストレージ上のパッケージ固有のディレクトリの storing output にデフォルト設定されました。つまり、これらの API を使用するためにアプリで WRITE_EXTERNAL_STORAGE パーミッションをリクエストする必要はありません。
  • 多くのプラットフォーム API は、Binder トランザクションで送信される大きなペイロードをチェックし、暗黙的にログ記録したり、削除したりするのではなく TransactionTooLargeExceptionsRuntimeExceptions として再度スローするようになりました。一般的な例としては、Activity.onSaveInstanceState() で大量のデータを格納することです。これにより、アプリが Android 7.0 をターゲットにしている場合は、ActivityThread.StopInfoRuntimeException がスローされます。
  • アプリが Runnable タスクを View に渡し、View がウィンドウにアタッチされない場合は、Runnable タスクと View がキューに入れられます。Runnable タスクは View がウィンドウにアタッチされるまで実行されません。この動作は以下のバグを修正します。
    • 対象ウィンドウの UI スレッド以外のスレッドからアプリが View に渡すと、結果として不適切なスレッドで Runnable が実行される可能性があります。
    • Runnable タスクがルーパー スレッド以外のスレッドから渡されると、アプリは Runnable タスクを公開できました。
  • DELETE_PACKAGES パーミッションを持つ Android 7.0 上のアプリが、別のアプリがインストールしたパッケージを削除しようとすると、ユーザーは確認を求められます。このシナリオでは、アプリが PackageInstaller.uninstall() を呼び出した場合は、STATUS_PENDING_USER_ACTION をリターン ステータスとしてみなす必要があります。
  • Crypto という JCA プロバイダは廃止されました。このプロバイダの SHA1PRNG アルゴリズムが暗号学的に脆弱であるためです。このプロバイダが利用できなくなるため、アプリは SHA1PRNG を使用して(危険な方法で)キーを導出できなくなりました。詳細については、ブログ投稿の Security "Crypto" provider deprecated in Android N をご覧ください。