最新の記事アプリケーションアクティビティ、インテント、サービスについてデバイスAndroidでのデバイス制御について。地磁気センサ、加速度センサなどマルチメディアグラフィックス、音楽や動画再生などマルチメディア処理についてユーザインターフェースAndroidのユーザインターフェイスについて、またユーザインターフェイスを提供するコンポーネントの話題について。リソースAndroidでのアイコン、画像、文字列、ローカライゼーションなどHacksマッシュアップ開発環境Androidの開発環境など。CommentsTweetAndroidアプリからAPIをつかってスクリーンショットを撮影する方法を紹介します。Level.20以下)の端末では、Androidアプリからスクリーンショットを保存する汎用的なAPIはありませんでした。セキュリティが大きな要因です(記事の末尾に経緯を記載しました。読んでみてください)。APIを使うことで、スクリーンショットが撮影できます。GoogleのサンプルプロジェクトではBitmapの取得ではなく、SurfaceViewへの常時反映(ミラーリング、スクリーンキャプチャし続ける)の例があります。Fragmentをつかっており、サンプルとしてはやや複雑な構成です。本記事を読んだあとに参照するとスムーズでしょう。APIをつかってスクリーンショットを撮影します。取得したBitmapをImageViewで表示する簡易なアプリです。実際に使うには、自分自身がスクリーンショットに映り込むことを避けるため、アプリを一旦非表示にしたほうがよいでしょう(Windowを消したり、Service化するなど)。今回の記事からサンプルコードをGitHub上へ公開しています。続きからどうぞまず、MediaProjectionのまえにMediaProjectionManagerを取得します。画面のキャプチャには権限が必要なためです。OSによって自動的に表示される)。ユーザーは確認して許可/拒否を選択します。of..."が赤い下線で出るケースがあります。MediaProjectionの利用にはパーミッションが必要。...省略...}MediaProjectionManagerをgetSystemServiceメソッドから取得します。StudioがLintで警告してくる場合がありますが、ビルドできますのでこのサンプルでは無視してください。パーミッション(権限)の確認のため、ユーザーにダイアログを表示します。MediaProjectionManagerのcreateScreenCaptureIntentメソッドでIntentを取得します。OSに処理を渡しています。ユーザーが何を選んだかは、このあとの処理で結果を受け取ります。ユーザーがダイアログからキャプチャを許可すると、次のような表示が通知バーに追加されます(通知バーへのアイコン常駐と一覧、詳細表示)。「画面のキャスト」詳細MediaProjectionの取得とVirtualDisplayの生成Intentの結果は、MainActivityのonActivityForResultメソッドで受け取ります。キャプチャの許可があればスクリーンショットの準備を行い、拒否されていれば何もしません。...省略...}キャプチャが許可されていれば、getMediaProjectionメソッドでMediaProjectionを取得します。許可されていない場合は、メッセージを表示して終了します。次に取得したMediaProjectionは、そのままでは画面をキャプチャできません。スクリーンショットの撮影のため画面サイズに合わせたImageReaderを用意しています。このImageReaderを出力先として、VirtualDisplay(ミラーリングする仮想ディスプレイ)を作ります。MediaProjectionのcreateVirtualDisplayメソッドを使います。第1引数に名前、その後パラメータが続きますが、第5引数のフラグ(DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR)がどのような仮想ディスプレイかを決定づけるポイントとなります。次の表は仮想ディスプレイの属性を示すフラグです。独自のコンテンツを表示。暗号化対策が施されたセキュアなディスプレイフラグには、VIRTUAL_DISPLAY_FLAG_AUTO_MIRRORとVIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLYは排他であるなど細かい条件があります。詳細はリファンレスを参照してください。サンプルコードのImageReader部分がSurfaceViewであれば画面に表示する(常に端末の画面がキャプチャされSurfaceViewが更新される)、ということも可能です。このことからVirtualDisplayは実在するディスプレイを使わなくてもよい、柔軟性の高い仕組みでだとわかります。最後にボタンを押下したらスクリーンショットを撮る、という処理を追加します。撮影したスクリーンショットには通知バー、ソフトウェアキーが写っていることからも、画面全体をキャプチャできていることがわかります。}}サンプルではボタンを押したときのView.OnClickListenerを登録して、getScreenshotメソッドを呼んでいます。getScreenshotメソッドでは、ImageReaderから画面を取り出し、Bitmapを生成して返却します。このとき、ImageReaderのフォーマットにあわせてBitmapを調整しています。これで実装は完了です。スクリーンショットとセキュリティいままでアプリからスクリーンショットの撮影が実現できなかった理由として、セキュリティ上の問題がありました。無制限に実行できると、ユーザー操作の監視につながるためです(銀行口座へのアクセスを観察する、クレジットカード、個人情報の盗み見など)。今回、スクリーンショット(または動画撮影)できる契機となったのは、スマホのマルチプラットフォーム化、連携機能の強化という側面の影響があります。Castといった別のディスプレイに本体の表示をミラーリングする(または仮想的にセカンドディスプレイとして扱いたい)目的で開発されました。Googleは、これを「画面のキャスト」と表現しています。OSがダイアログを表示して、ユーザに利用可否を確認します。それでもなおスクリーンショット機能はユーザーにとっては脅威です。実装する場合は、必要性について十分に検討してください。デバッグ用途であればアプリ内のViewを取得する方法があります。多くの場合、アプリの責務を超えた画面全体のスクリーンショットは必要ありません。以上、おつかれさまでした。本記事の作成にあたり、Twitter上の発言を参考としています。@ta9marさん、@zaki50さん、@8796nさん、@adakodaさん、@l_b__さん、@noritsunaさん、@hamatzさん、ありがとうございました。Engineerだよ。Androidと組込とRe:VIEW。techbooster主宰。関する議論の土台となる本を」という著者陣の熱い思いから、ついにAndroidアプリ設計の決定版が登場!AndroidモダンプログラミングはKotlin&Gradleを特集した解説書です。Keynoteまとめ:現実にも検索を。TechBooster.TechBoosterについて。