[go: nahoru, domu]

この記事は Chrome プロダクト マネージャー、Emily Schechter による Google Online Security Blog の記事 "New Chrome Protections from Deception" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

Chrome は最初期のころから、セキュリティを意識して開発されてきました。先日リリースした、誤解を生じさせるウェブサイトからユーザーを保護するための 2 つの新機能についてご紹介します。Suspicious Site Reporter(疑わしいサイトの報告)拡張機能は、パワーユーザーが疑わしいサイトを簡単に Google セーフ ブラウジングに報告できるようにすることで、Chrome ユーザーのセキュリティを向上させます。また、誤解を生じさせる URL を持つサイトからユーザーを保護するための新しい警告機能も追加しました。

Chrome は、デフォルトでも安全に動作し、誰でも簡単に使えるような設計になっています。Google セーフ ブラウジングは、10 年以上にわたってフィッシング攻撃から Chrome ユーザーを守っています。ユーザーが危険なサイトを開いたり危険なファイルをダウンロードしたりする前に警告を表示することで、現在では、ブラウザやアプリを問わず毎日 40 億台以上の端末を保護しています。セーフ ブラウジングの改善は恒常的に続いていますが、今回、皆さんもそれに貢献できるようになりました。

セーフ ブラウジングは、Google 検索のウェブクローラが認識したウェブサイトを自動分析し、危険なサイトや誤解を生じさせるサイトのリストを作ることで動作しています。皆さんは、Suspicious Site Reporter 拡張機能を使って疑わしいサイトを報告することで、セーフ ブラウジングによるウェブユーザーの保護に貢献できます。拡張機能をインストールすると、疑わしいと思われるサイトにアイコンが表示され、詳細情報としてそのサイトが疑わしい理由も表示されます。アイコンをクリックすると、セーフ ブラウジングに安全でないサイトを報告し、詳しく評価してもらうことができます。サイトがセーフ ブラウジングのリストに追加されれば、Chrome ユーザーだけでなく、他のブラウザやウェブ全体も保護されることになります。


Suspicious Site Reporter 拡張機能で危険なサイトや誤解を生じさせるサイトを Google セーフ ブラウジングに報告することは、ウェブユーザーの保護に役立つ。

詐欺サイトがユーザーをだまそうとする方法の 1 つが、誤解を生じさせる URL です。たとえば、「go0gle.com」は「google.com」と混同しがちです。Chrome 75 では新しい警告が追加され、誤解を生じさせる URL を持つサイト に気付くよう、警告されるようになっています。


現在のバージョンの Chrome(75)以降では、ページの URL と最近アクセスしたサイトの URL を混同しがちな場合、警告が表示される。

この新しい警告は、現在のページの URL と最近アクセスしたページの URL を比較することで動作します。URL が似ており、混同したりだまされている可能性がある場合、安全なサイトに戻るための警告を表示します。

私たちは、セキュリティの専門家でなくてもウェブを安全に感じられるようにしたいと考えています。また、多くの Chrome のパワーユーザーが私たちのミッションを共有することで、あらゆる人にとって安全なウェブを作ることができると信じています。私たちは、Chrome を簡単かつ安全に使えるように、Chrome のセキュリティの改善を続けてまいります。その目的に向けて、コミュニティの皆さんと協力し合えることを楽しみにしています。協力いただける方は、新しい拡張機能をインストールして、安全なウェブを実現する活動に参加してください!


Reviewed by Eiji Kitamura - Developer Relations Team

この記事は Toni Klopfenstein による Google Developers Blog の記事 "Developer Preview of Local Home SDK" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

 投稿者: Toni Klopfenstein


先日の Google I/O では、新しい Local Home SDK を少しだけお見せしました。この SDK には、スマートホーム統合を強化する一連のローカル テクノロジーが含まれています。本日より、Local Home SDK がデベロッパー プレビューとして公開されます。私たちは、GE、LIFX、Philips Hue、TP-Link、Wemo[1] などのパートナーと連携し、懸命にこのプラットフォームのテストを行ってきました。そして今回、Google アシスタントにスマート端末を接続するテクノロジーを追加できることをうれしく思います。

図 1: ローカル実行パス


デベロッパーは、既存のスマートホーム プラットフォームをベースに、この SDK を使って Google Home スマート スピーカーや Nest スマート ディスプレイによるローカル実行パスを構築できます。それにより、スマート端末とアシスタントとの密接な統合が実現します。スマート スピーカーやスマート ディスプレイ上で JavaScript を動作させることで、新しいスマート端末や既存のスマート端末を制御するビジネス ロジックを実行できるので、遅延を減らし、高い信頼性を実現して、ユーザーにメリットをもたらすことができます。

動作の仕組み

SDK には、2 つの新しいインテント IDENTIFYREACHABLE_DEVICES が導入されています。ローカル ホーム プラットフォームは、mDNS、UDP、UPnP を使ってユーザーのホーム ネットワークをスキャンし、アシスタントに接続されているスマート端末を検出します。そして、IDENTIFY を呼び出し、端末 ID がおなじみの Smart Home API の SYNC インテントから返される端末 ID と一致することを検証します。検出した端末がハブまたはブリッジだった場合は、REACHABLE_DEVICES が呼び出され、ハブはローカル通信のプロキシ端末として扱われます。Google Home から端末へのローカル実行パスが確立すると、ホームグラフの端末プロパティが更新されます。



図 2: それぞれの実行パスに使われるインテント


ユーザーがローカル実行パスを持つスマートホームの Action を呼び出すと、アシスタントはデベロッパーのクラウド フルフィルメントではなく、Google Nest 端末に EXECUTE インテントを送ります。デベロッパーの JavaScript アプリが起動し、そのアプリが Local Home SDK を呼び出し、TCP、UDP ソケット、HTTP/HTTPS リクエストのいずれかを使ってスマート端末に制御コマンドを送ります。クラウドではなくローカル実行をデフォルトにすることで、ユーザーのリクエストに迅速に対応できます。ローカル実行が失敗した場合、実行リクエストはクラウドパスに送られます。この冗長性により、リクエストが失敗する可能性を最低限に抑えることができるので、全体的なユーザー エクスペリエンスが向上します。

他にも、Local Home プラットフォームには次のような機能があります。
  • 2 段階認証を有効化することなく、Wi-Fi 対応の端末タイプ端末特性をすべてサポート
  • ユーザーがアクションを行わなくても、すべての端末で Local Home を利用可能
  • 検出プロトコルとホストする JavaScript アプリの URL を Actions コンソールから簡単に設定

図 3: Actions コンソールの Local Home 設定ツール


JavaScript アプリは端末上でテストできるので、デベロッパーは Chrome Developer Console などのおなじみのツールを使ってデバッグできます。また、Local Home SDK は既存のスマートホーム フレームワークと連携して動作するので、新しいアプリはスマートホーム用テストスイートを使って自己検証することもできます。

使ってみる

Local Home プラットフォームの詳細については、API リファレンスをご覧ください。また、デベロッパー ガイドサンプルを参考にして、ローカル実行を試してみてください。スマート端末を Google アシスタントに接続する方法など、汎用的な情報については、スマートホームのドキュメントにアクセスするか、今年の Google I/O でお話ししたスマートホーム向けのローカル テクノロジーについて確認してください。
フィードバックは、バグトラッカーから送ることができます。または、/r/GoogleAssistantDev からコミュニティにお知らせいただいても構いません。ディスカッションを整理するために、投稿には local-home-sdk タグを付けてください。

[1] 米国内でのみ販売される製品も含まれています

Reviewed by Yoshifumi Yamaguchi - Developer Relations TeamJohan Euphrosine - Developer Relations team

この記事は Sean McQuillan (Developer Advocate Android) による Medium Blog の記事 "Coroutines On Android (part III): Real work" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

この記事は、Android でのコルーチンの使用に関する連載の一部です。この記事では、ワンショット リクエストを実装することによって、コルーチンを使った実際の問題の解決に焦点を当てます。

このシリーズの他の記事:

Android のコルーチン(パート I): 背景を理解する
Android のコルーチン(パート II): 使ってみる

コルーチンで現実の世界の問題を解決する

このシリーズのパート I とパート II では、コルーチンを使ったコードの簡素化、Android でのメインセーフティの提供、処理漏れの防止の方法に焦点を当てました。そうした状況から見れば、コルーチンは、バックグラウンド処理と、Android でのコールバック ベースのコードを簡略化する方法の両方に対する優れた解決策のように見えます。

ここまでは、コルーチンとは何か、およびコルーチンの管理方法に焦点を当ててきました。この記事では、コルーチンを使って実際のタスクを行う方法をいくつか紹介します。コルーチンは関数と同じレベルの、汎用プログラミング言語の機能です。そのため、デベロッパーはコルーチンを使って、関数やオブジェクトで実行可能なあらゆる処理を実装できます。ただし、実際のコードでよく発生し、コルーチンが優れた解決策となるのは以下の 2 種類のタスクです。

  1. ワンショット リクエスト: 呼び出されるとその都度実行されるリクエストです。必ず、結果が利用可能になった後で完了します。
  2. ストリーミング リクエスト: 継続的に変更を監視して呼び出し元に変更を伝えるリクエストです。最初の結果が利用可能になった時点では完了しません。

コルーチンは上記の両方のタスクに対する優れた解決策です。本稿では、ワンショット リクエストについて詳しく確認し、Android でコルーチンを使ってワンショット リクエストを実装する方法を説明します。

ワンショット リクエスト

ワンショット リクエストは、呼び出されるたびに 1 回実行され、結果が利用可能になるとすぐに完了します。このパターンは標準の関数呼び出しと同じです。呼び出され、何らかの処理を実行し、その後リターンします。ワンショット リクエストは関数呼び出しと似ていることから、ストリーミング リクエストよりも理解しやすいといえます。

ワンショット リクエストは、呼び出されるとその都度実行されます。結果が利用可能になるとすぐに実行を停止します。

ワンショット リクエストの例として、ブラウザがこのページをどのように読み込んだかを考えてみましょう。あなたがこの記事へのリンクをクリックしたときに、ブラウザはサーバーに対して、ページを読み込むためのネットワーク リクエストを送信しました。ページがブラウザに転送されると、ブラウザはバックエンドとのやり取りを停止します。この時点で、ブラウザは必要なデータをすべて入手しています。サーバー側で記事が変更されても、ブラウザにはその変更は表示されません。変更を表示するにはページの更新が必要になります。

このように、ストリーミング リクエストのライブプッシュは無いものの、ワンショット リクエストは極めて有用です。Android アプリにおいて実行できる処理のなかで、データの取得、保管、更新など、ワンショット リクエストによって解決できるものは数多くあります。このパターンは、リストの並べ替えのような処理にも適しています。

問題: 並べ替えられたリストの表示

並べ替えられたリストをどのように表示するかを例に、ワンショット リクエストを見てみましょう。例を具体的にするために、従業員が店舗で使う在庫管理アプリを構築することにします。このアプリは、最後に補充された日時に基づいて商品を検索するために使用されます。リストは昇順と降順の両方で並べ替えられるようにする必要があります。商品数が多いため、並べ替えには約 1 秒かかると考えられます。そこで、メインスレッドがブロックされるのを回避するためにコルーチンを使います。

このアプリでは、すべての商品が Room データベースに保存されます。これはユースケースとして取り上げるのに適しています。ネットワーク リクエストを含める必要がなく、パターンに焦点を当てることができるためです。この例はネットワークを使わないため簡単になっていますが、ワンショット リクエストの実装に必要なパターンを示しています。

コルーチンを使ってこのリクエストを実装するために、ViewModel、Repository、および Dao にコルーチンを導入します。それぞれを 1 つずつ見ながら、コルーチンと統合する方法を確認してみましょう。(ソースはこちら


ProductsViewModel は、UI レイヤからのイベントを受け取った後、リポジトリに更新されたデータがないか問い合わせる役割を担います。ProductsViewModel は LiveData を使って、UI での表示用に現在の並べ替えられたリストを保持します。新しいイベントが届くと、sortProductsBy が新しいコルーチンを開始してリストを並べ替え、結果が利用可能になったら LiveData を更新します。通常、このアーキテクチャのほとんどのコルーチンを開始するのに適した場所は ViewModel です。これは、ViewModel が onCleared 内のコルーチンをキャンセルできるためです。ユーザーが現在の画面から別の場所に移動した場合、通常、未完了の処理には用途がなくなります。

LiveData の使用経験があまりない場合は、LiveData が UI 用のデータを保管する仕組みについて紹介した @CeruleanOtter による以下の記事をご覧ください。

ViewModel: 簡単な例 (medium.com)

これは Android のコルーチンの一般的なパターンです。Android フレームワークは中断関数を呼び出さないため、デベロッパーは UI イベントに応じてコルーチンを調整する必要があります。そのための最も簡単な方法は、イベントが届いたときに新しいコルーチンを開始することです。その処理を実行する最も自然な場所は ViewModel 内です。

一般的なパターンとして、ViewModel 内でコルーチンを開始します。

ViewModel は ProductsRepository を使って実際にデータを取得します。コードは以下のようになります。(ソースはこちら


ProductsRepository は、商品のデータにアクセスするための相応のインターフェースを提供します。このアプリでは、すべてのデータがローカルの Room データベースに保存されているため、ProductsRepository はそれぞれの並べ替え順に対応した 2 つの関数を持つ @Dao 用の適切なインターフェースを提供します。

リポジトリは Android アーキテクチャ コンポーネント アーキテクチャのオプション部分ですが、アプリ内にリポジトリまたは類似のレイヤがある場合、そうしたリポジトリやレイヤでは標準の中断関数のエクスポーズを優先する必要があります。リポジトリは自然なライフサイクルを持たず、単なるオブジェクトに過ぎないため、処理をクリーンアップする手段を持ちません。その結果、リポジトリ内で開始されたコルーチンはすべて、デフォルトで処理漏れとなります。

処理漏れの回避に加えて、標準の中断関数をエクスポーズすることで、別のコンテキストでリポジトリを簡単に再利用できます。コルーチンの作成方法を知っているものなら何でも、loadSortedProducts を呼び出せます。たとえば、WorkManager ライブラリによってスケジュール設定されたバックグラウンド ジョブは、直接 loadSortedProducts を呼び出すことができます。

リポジトリは、メインセーフである標準の中断関数のエクスポーズを優先する必要があります。
注: 一部のバックグラウンドの保存オペレーションについては、ユーザーが画面から離れた後も続行することをおすすめします。こうした保存をライフサイクルなしで実行することは合理的です。他のほとんどの場合は、viewModelScope が合理的な選択です。
ProductsDao に進みます。コードは以下のようになっています。


ProductsDao は Room の @Dao であり、2 つの中断関数をエクスポーズします。関数には suspend のマークが付けられているため、Room はそれらの関数がメインセーフになるようにします。つまり、デベロッパーはそれらの関数を Dispatchers.Main から直接呼び出すことができます。

これまでに Room 内でのコルーチンを見たことがない場合は、@FMuntenescu による以下の記事をご覧ください。

データベースに中断を追加する (medium.com)

ただし、これを呼び出すコルーチンはメインスレッド上にある、ということに注意が必要です。そのため、その結果を使って負荷の高い処理(新しいリストへの変換など)を実行する場合は、メインスレッドをブロックしていないことを確認する必要があります。
注: Room では独自のディスパッチャを使って、バックグラウンド スレッドでクエリを実行します。デベロッパーのコードでは withContext(Dispatchers.IO) を使って中断の原因となる Room のクエリを呼び出さないようにする必要があります。コードが複雑になり、クエリの実行速度が遅くなります。
Room の中断関数はメインセーフであり、カスタム ディスパッチャ上で実行されます。

ワンショット リクエストのパターン

上記の処理は、Android アーキテクチャ コンポーネントにおいて、コルーチンを使ってワンショット リクエストを作成する完全なパターンです。ViewModel、Repository、および Room にコルーチンを追加しました。各レイヤはそれぞれ別の役割を担います。

  1. ViewModel はメインスレッド上でコルーチンを開始します。コルーチンは結果を取得すると完了します。
  2. Repository は標準の中断関数をエクスポーズし、それらの関数がメインセーフになるようにします。
  3. データベースとネットワークは標準の中断関数をエクスポーズし、それらの関数がメインセーフになるようにします。

ViewModel は、コルーチンの開始と、ユーザーが画面から離れた場合にそうしたコルーチンが確実にキャンセルされるようにする役割を担います。ViewModel は負荷の高い処理を実行しません。負荷の高い処理の実行は他のレイヤに依存します。結果を取得したら、LiveData を使ってその結果を UI に送ります。

ViewModel は負荷の高い処理を実行しないため、メインスレッド上でコルーチンを開始します。メインスレッド上で開始することで、結果がすぐに(たとえば、メモリ内キャッシュから)利用できる場合はユーザー イベントにより迅速に応答できます。

Repository は、データにアクセスするための標準の中断関数をエクスポーズします。Repository は通常、長期にわたって実行される独自のコルーチンを開始しません。これは、Repository がそうしたコルーチンをキャンセルする手段を持たないためです。リストの変換のような負荷の高い処理を実行しなければならない場合、Repository は withContext を使ってメインセーフなインターフェースをエクスポーズする必要があります。

データレイヤ(ネットワークまたはデータベース)は常に、標準の中断関数をエクスポーズします。Kotlin コルーチンを使う際はこうした中断関数がメインセーフであることが重要であり、Room と Retrofit はいずれもこのパターンに従っています。

ワンショット リクエストでは、データレイヤは中断関数のエクスポーズのみを行います。そうした関数が新しい値を必要とする場合、呼び出し元はそうした関数を再度呼び出す必要があります。これは、ウェブブラウザの更新ボタンのようなものです。

ワンショット リクエストに関するこうしたパターンを理解しておくと便利です。これは Android のコルーチンにおける通常のパターンであり、頻繁に使用することになります。

最初のバグレポート

デベロッパーはこのソリューションをテストした後、本番環境向けにリリースしました。その後数週間ほど問題なく動作していましたが、あるとき奇妙なバグレポートが寄せられました。
件名: 🐞 -  並べ替え順が正しくありません
レポート: 並べ替えボタンを何度も素早く押したときに、並べ替えが正しく行われないことがあります。この問題は毎回発生するわけではありません。🙃
デベロッパーはこのレポートを見て困惑しました。どのような問題が起きているのでしょうか。アルゴリズムは極めてシンプルに思えます。

  1. ユーザーのリクエストした並べ替えを開始する。
  2. Room ディスパッチャで並べ替えを実行する。
  3. 並べ替えの結果を表示する。

デベロッパーは「修正しない  - ボタンを何度も素早く押さないこと」としてバグをクローズしたくなりましたが、何か不具合があるのかも知れないと心配になりました。ログ ステートメントを追加し、一度に数多くの並べ替えを呼び出すテストを作成した結果、デベロッパーはついに原因を突き止めました。

表示される結果は「いま行った並べ替えの結果」ではなく、実際には「前回完了した並べ替え」の結果であることがわかりました。ユーザーが何回もボタンを押すと、同時に複数の並べ替えが開始され、順序に関係なく完了する可能性があります。

UI イベントに応じて新しいコルーチンを開始する際は、その 1 回の操作が完了する前にユーザーが同じ操作を新たに開始した場合に何が起きるかを考慮します。

これは並行性バグであり、コルーチンとは一切関係がありません。コールバック、Rx、あるいは ExecutorService を同じように使ったとしても、同様のバグが発生すると考えられます。

この問題は、ViewModel と Repository の両方において、さまざまな方法を使って修正できます。ワンショット リクエストをユーザーの予期する順序で、確実に完了させるためのパターンをいくつか紹介します。

最適な解決策: ボタンを無効にする

根本的な問題は、並べ替えが 2 つ実行されていることです。並べ替えが 1 つしか実行されないようにすることで、この問題を修正できます。最も簡単な方法は、並べ替えボタンを無効にして、新しいイベントが起きないようにすることです。

単純な解決策に思えるかも知れませんが、これは極めて良い方法です。この処理はシンプルなコードで実装でき、テストも簡単で、UI において一貫性がある限り問題は完全に解決されます。

ボタンを無効にするには、以下のように、sortPricesBy 内で並べ替えリクエストが発生中であることを UI に伝えます。(ソースはこちら

sortPricesBy で _sortButtonsEnabled を使って、並べ替えが実行している間はボタンを無効にします

これはなかなか良い方法です。sortPricesBy 内でリポジトリへの呼び出しの間じゅう、ボタンを無効にするだけです。

ほとんどの場合、この方法で問題を適切に解決できます。しかし、ボタンを無効にせずにこのバグを修正したい場合は、どうすればよいでしょうか。その場合はやや複雑になります。本稿の残りの部分で、その他の解決方法を見てみましょう。
重要: このコードは、タップに応じてボタンがすぐに無効化されるという、メインスレッド上で開始することの大きな利点を示しています。ディスパッチャを切り替える場合、低速のスマートフォンでユーザーが素早く何度もタップすると、複数回のタップが送信される可能性があります。

同時実行のパターン

ここからは高度なトピックを紹介します。コルーチンを使い始めたばかりの場合は、以下の内容をすぐに理解する必要はありません。発生する問題のほとんどは、単にボタンを無効にすることで適切に解決できます。

ここからは、コルーチンを使って、ボタンを有効にしたまま、複数のワンショット リクエストがユーザーの予期した順序で確実に実行されるようにする方法をいくつか紹介します。コルーチンをいつ実行するか(または実行しないか)を制御することで偶発的な同時実行を防ぐことによって、その動作を実現できます。

ワンショット リクエストで一度に 1 つのリクエストだけが実行されるようにする方法として、次の 3 つの基本パターンを使用できます。

  1. 新たな処理を開始する前に直前の処理をキャンセルする。
  2. 次の処理をキューに入れて、その処理を開始する前に直前のリクエストが完了するのを待つ。
  3. すでに実行中のリクエストがある場合は直前の処理を結合し、新たなリクエストを開始せずにその処理の結果を返す。

こうした解決策を見て行くなかで、その実装がやや複雑であることがわかると思います。実装の詳細ではなくこうしたパターンの使用方法に焦点を当てるために、再利用可能な抽象化として全 3 パターンの実装を含めた gist を作成しました。

解決策その 1: 直前の処理をキャンセルする

並べ替えの場合、ユーザーから新たなイベントが届くことは、通常、直前の並べ替えをキャンセルできることを意味します。結果が不要であるとユーザーがすでに伝えてきているのなら、処理を続行する意味はありません。

直前のリクエストをキャンセルするためには、そのリクエストを何らかの方法で管理することが必要となります。gist 内の関数 cancelPreviousThenRun がその処理を実行します。

この関数を使ってバグがどのように修正されるかを見てみましょう。(ソースはこちら

cancelPreviousThenRun を使って、並べ替えが一度に 1 つだけ実行されるようにする。
gist での cancelPreviousThenRun の実装例を見てみると、進行中の処理を管理する方法がわかります。(ソースはこちら


簡単に言えば、この関数は常に、メンバー変数 activeTask 内で現在アクティブな並べ替えを管理します。並べ替えが開始されるたびに、現在 activeTask 内にあるものに対して、直ちに cancelAndJoin を実行します。この関数によって、新たな並べ替えを開始する前に、進行中の並べ替えがすべてキャンセルされます。

アドホックの同時実行をアプリケーション ロジックに組み込むのではなく、ControlledRunner<T> のような抽象化を使ってこうしたロジックをカプセル化することをおすすめします。

抽象化を作成して、アドホックの同時実行パターンをアプリケーション コードに組み込むのを避けることを検討してください。
重要: 関連のない呼び出し元同士がお互いをキャンセルすることはできないため、このパターンはグローバル シングルトンでの使用には適していません。

解決策その 2: 次の処理をキューに入れる

並行性バグに対して、常に有効な解決策が 1 つあります。

リクエストをキューに入れ、一度に 1 つのリクエストしか実行されないようにする方法です。お店での順番待ちや列のように、リクエストは一度に 1 つずつ、開始された順に実行されます。

今回発生した並べ替えの問題に対しては、キューに入れるよりもキャンセルするほうが良いと考えられますが、この方法は常に有効であることから、ここで紹介します。(ソースはこちら


この方法では、新しい並べ替えが届くたびに、SingleRunner のインスタンスを使って、一度に実行される並べ替えが 1 つのみとなるようにします。

この方法では Mutex を使います。Mutex は 1 回限りのチケット(ロック)であり、コルーチンがブロックに入るためには Mutex を取得する必要があります。実行中のコルーチンがある状態で新たにコルーチンを実行しようとすると、その新たなコルーチンは Mutex によって、保留中のすべてのコルーチンが完了するまで、自身を中断させます。

Mutex によって、一度に 1 つのコルーチンだけが実行されるようにすることができます。コルーチンは開始された順に完了します。

解決策その 3: 直前の処理を結合する

3 番目に検討する解決策は、直前の処理を結合する方法です。この方法は、新しいリクエストが、すでに途中まで完了しているものと完全に同じ内容の処理を再スタートするものである場合に適しています。

このパターンは、並べ替え機能に特に適しているわけではありませんが、データを読み込むネットワーク フェッチには自然にフィットします。

今回の在庫管理アプリでは、ユーザーはサーバーから新たな商品の在庫を取得する方法を必要とします。そこで、シンプルな UI として、ユーザー向けに更新ボタンを用意します。ユーザーはこのボタンを押して新しいネットワーク リクエストを開始できます。

並べ替えボタンと同様に、リクエストの実行中は単にこのボタンを無効することが、この問題に対する完全な解決策です。しかし、もしその方法をとらない(あるいは、とれない)場合は、その代わりに既存のリクエストを結合することができます。

この方法が動作する仕組みの例として、gist の joinPreviousOrRun を使ったコードを見てみましょう。(ソースはこちら


これは、cancelPreviousAndRun の動作を逆さにしたものです。直前のリクエストをキャンセルすることで破棄する代わりに、新しいリクエストを破棄して実行を防ぎます。すでに実行中のリクエストがある場合は、新たにリクエストを実行する代わりに、現在の「実行中の」リクエストの結果を待って、その結果を返します。ブロックが実行されるのは、すでに実行中のリクエストがない場合のみです。

この動作は joinPreviousOrRun  の開始部分で確認できます。activeTask にデータがある場合は、そのまま直前の結果を返します。(ソースはこちら


このパターンは、id による商品の取得などのリクエストに拡張できます。id から Deferred へのマップを追加したうえで、同じ結合ロジックを使って、同じ商品に対する直前のリクエストを管理できます。

直前の処理の結合は、ネットワーク リクエストの繰り返しを避けるための優れた解決策です。

次のステップ

本稿では、Kotlin コルーチンを使ったワンショット リクエストの実装方法について見てきました。まず、ViewModel 内でコルーチンを開始し、Repository と Room Dao から標準の中断関数をエクスポーズする方法を示したパターン全体を実装しました。

ほとんどのタスクの場合、Android で Kotlin コルーチンを使うために必要なのはこれだけです。このパターンは、本稿で紹介したリストの並べ替えのような、一般的な数多くのタスクに適用できます。このパターンは、ネットワーク上のデータの取得、保存、更新にも使用できます。

次に、発生するおそれのあるわかりにくいバグと、考えられる解決策を紹介しました。この問題を解決する最も簡単な(そして多くの場合最適な)方法は、UI において、並べ替えが進行中の間は並べ替えボタンを無効にすることです。

そして最後に、いくつかの高度な同時実行パターンと、Kotlin コルーチンでのそうしたパターンの実装方法を紹介しました。このコードはやや複雑ですが、いくつかの高度なコルーチンのトピックへの優れた入門編となっています。

次回は、ストリーミング リクエストと、liveData ビルダーの使用方法を紹介します。

Posted by Yuichi Araki - Developer Relations Team

この記事は Chrome 拡張機能チーム、Devlin Cronin による Google Online Security Blog の記事 "Improving Security and Privacy for Extensions Users" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。


Chrome は広告ブロッカーの撲滅を目指しているわけではない。安全にしようとしているだけだ。
Chrome 拡張機能のエコシステムは、10 年以上前にリリースされてから驚くほど進化し、採用も進んで拡大しています。拡張機能は、ユーザーが Chrome やウェブの体験をカスタマイズできるすばらしい方法です。このシステムはリーチとパワーの両面で成長、拡大していますが、Chromium プロジェクトがユーザーの安全や保護に特に力を入れている点は変わっていません。

10 月、私たちが発表したのは、Chrome 拡張機能のセキュリティやプライバシー、パフォーマンスを改善するための数々の変更点でした。この変更には、拡張機能のパーミッションを制御するユーザー オプションの追加、レビュー プロセスやリーダビリティ要件の変更、デベロッパーへの 2 段階認証の義務付けなどが含まれています。また、ウェブサイトでのインライン インストールの制限誤解を生じさせるインストール方法の防止拡張機能によるデータ収集の制限によって、不正利用をとどめようとしています。さらに、チーム自身の改革も行い、この 1 年で拡張機能の不正利用に対処するエンジニアリング チームの規模を 3 倍以上に、レビューアーの数を 4 倍以上に増やしました。

このような変更により、2018 年初頭以降、不正インストールの比率が 89% 減少しています。現在では、毎月約 1,800 の悪意のあるアップロードをブロックし、これらが 2 度とストアに現れることがないようにしています。Chrome チームはこの改善を誇りに思っていますが、レビュー プロセスだけですべての不正利用を検知できるわけではありません。ユーザーの保護をさらに強化するには、プラットフォームにも変更を加えなければなりません。それが、私たちが Manifest V3 と呼んでいる一連の変更です。

この作業は、ユーザーの安全を保ち、拡張機能を通して共有されるデータの視認性と制御性を向上させたいという思いで行われています。1 つの方法として取り組んでいるのは、メール、写真、ソーシャル メディア アカウントへのアクセスといったプライベートなデータへのアクセスを許可する際に、ユーザーがじっくりと検討できるようにすることです。変更を行うに当たっては、今後も拡張機能がユーザーのできることを増やし、ブラウズ体験を拡張できるようにしたいと考えています。

このバランスを保つため、数々の強力な API の動作について再考しています。拡張機能からあらゆるプライベート データへアクセスするたびにユーザーがアクセス権を付与するのではなく、必要なデータのみへのアクセス権をリクエストする方法を準備しています。その 1 つの例が、Web Request API の一部に代わる Declarative Net Request API の導入です。
この変更を概念的に説明するなら、コンテンツをブロックするのに、拡張機能がユーザーのプライベートなデータすべてにアクセスする必要はないということです。現在の Web Request API では、Chrome がネットワーク リクエストについてのすべての情報を拡張機能に渡せるパーミッションを与えます。この情報には、メールや写真などのプライベートな情報が含まれる可能性があります。これとは違い、Declarative Net Request API は、ユーザーがプライベートな情報へのアクセスを許可しなくても、拡張機能がコンテンツをブロックできるようにします。さらに、Declarative Net Request API を使うと、ブラウザでかなりのオーバーヘッドを削減できるので、ウェブ リクエストにおいてシステムレベルで大幅なパフォーマンス向上が見込まれます。


Web Request API は、広告ブロッカーを含む多くの人気拡張機能で使われているので、この変更は議論を呼んでいます。私たちは、広告ブロッカーの開発や、ユーザーによる広告のブロックを止めさせようとしているわけではありません。むしろ、コンテンツ ブロッカーを含め、ユーザーのプライバシーが守られる拡張機能を書けるようにしたいと考えています。
Declarative Net Request API の詳細や Web Request API との違いについては、こちらをご覧ください。

この変更によって、デベロッパーが拡張機能の動作方法を更新しなければならなくなる点は承知しています。しかし、この変更は、ユーザーのプライベートなデータが第三者に共有されることを防ぎつつ独自のブラウズ体験を提供する上で、正しい選択だと考えています。Manifest V3 の設計にあたっては、さまざまな側面で議論を重ねています。また、デベロッパー コミュニティと連携しながら、現在の拡張機能のユースケースをサポートしつつユーザーの安全性や制御性を高めることができるソリューションを探しています。

Reviewed by Eiji Kitamura - Developer Relations Team

この記事は Chrome 拡張機能デベロッパー アドボケート、Simeon Vincent による Chromium Blog の記事 "Web Request and Declarative Net Request: Explaining the impact on Extensions in Manifest V3" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

これまでのストーリー

ユーザーのセキュリティとプライバシーを向上させる取り組みの一環として、Chrome 拡張機能プラットフォームにたくさんの変更を加えることが予定されています。昨年の 10 月にいくつかの変更点についてお知らせしたのに続き、本日はそれに関する追加情報も提供しています。プラットフォームに対するこれらの変更点は、Chrome 拡張機能プラットフォームの次のバージョンである Manifest V3 の一部として実装されています。

その変更点の 1 つが、ブロッキング版の Web Request API から、Declarative Net Request と呼ばれる新しい API への移行です。この変更については、意図と実装の両面でさまざまな混乱や誤解が生じています。その中には、今回の変更が広告ブロッカーを妨げたり、弱体化させたりするために設計されたものだという憶測があります。これは、本来の目的とはまったく違います。実際には、今回の変更はデベロッパーが安全でパフォーマンスのよい広告ブロッカーを作成できるようにするためのものです。

拡張機能プラットフォームでセキュリティやプライバシーを保証するために、拡張機能プラットフォームのコア API の一部を再考しています。ブロッキング版の Web Request API を Declarative Net Request API で置き換えようとしているのはそのためです。

Web Request の仕組み

Web Request を使うと、Chrome はネットワーク リクエストに含まれるすべてのデータを、監視している拡張機能に送ります。これには、個人の写真やメールなど、リクエストに含まれるすべてのプライベートなデータが含まれます。拡張機能はリクエストを評価でき、そのリクエストをどのように処理するか(許可、ブロック、いくつかの変更を加えて送信)を Chrome に伝えます。そのため、Web Request API を使う拡張機能は、ウェブでユーザーが行うあらゆることにアクセスし、それを読み取ったり変更したりできるのが一般的です。


善良なデベロッパーは、この API を使ってコンテンツ ブロッカーなどの強力な機能を実装しています。しかし、これは悪用される可能性もあり、実際に悪用もされています。すべてのリクエスト データが拡張機能に渡るので、悪意のあるデベロッパーは、いとも簡単にユーザーの認証情報やアカウント、個人情報へのアクセスを悪用できます。2018 年 1 月以降、悪意のある拡張機能の 42% が Web Request API を使っています。

以上のような安全性の懸念に加え、パフォーマンスにも重大なコストが発生します。ほとんどの場合、このコストは拡張機能のスクリプト処理イベントを評価する部分ではなく、スクリプトを管理する他の部分によるものです。全体的なパフォーマンスへの影響は非常に大きくなる場合があります。これは、JavaScript の実行時間が無視できるほどパフォーマンスよく書かれた拡張機能でも変わりません。

現在の設計では、ブロッキング版の Web Request API には、長時間にわたって実行される常駐プロセスが必要で、遅延処理に対応したプロセス(貴重なシステム リソースを節約できるよう、必要に応じて準備、分割されるもの)とは根本的に互換性がありません。また、リクエスト データのシリアル化、そのデータを拡張機能に送信するために必要なプロセス間通信、拡張機能からの応答の処理にかかるコストも重大です。

Declarative Net Request の導入

Declarative Net Request API は、Web Request API とは異なる仕組みで動作します。Chrome は、リクエスト時にすべてのリクエストに関する情報を、監視している拡張機能に送ることはしません。その代わり拡張機能は、あるタイプのリクエストが発生したとき何をするかを Chrome に伝えるルールを登録します。


このアプローチは、ユーザーのセキュリティやプライバシーの面だけでなく、パフォーマンスの面でも優れています。宣言的なアプローチでは、Chrome はプライベートなデータを拡張機能に渡す必要はありません。拡張機能が既にアクションを実行する条件を指定しているので、ブラウザはネットワーク リクエストに関連するすべてのデータを送ることなく、拡張機能がリクエストしたアクションを実行できます。そのため、拡張機能はユーザーのすべての個人情報にアクセスせずに、コンテンツをブロックできるようになります。

これは、パフォーマンスに大きく関係します。最も重要な点は、実行時に処理を行う必要はなく、リクエストが行われる前にルールが登録されているので 、長時間にわたって実行される常駐プロセスが必要なくなることです。すべてのリクエストをシリアル化するコストや、監視している拡張機能との間でプロセス間メッセージが往復するコストも不要になります。以上のようなパフォーマンスの改善によって、リソースに制約があるプラットフォームでも拡張機能が広く利用できるようになります。

なぜ両方とも使えるようにはしないのですか?

前述のようなパフォーマンスの懸念もさることながら、拡張機能がその機能を実行するためにアクセスする必要がないなら、メールや写真、ソーシャル メディアなどのプライベートなデータを拡張機能に見せる必要はないはずだというのが Chrome チームの考えです。これまでも、機能かセキュリティかという選択を迫られた拡張機能のデベロッパーの大半が、機能を選んでいます。イベントページ、オプションのパーミッション、activeTab がある拡張機能プラットフォームでは、これが繰り返し目撃されています。

エンタープライズ

企業や学校では、組織のポリシーに準拠するために、別のネットワークやソフトウェア制御が必要になることもよくあります。さらに、こういった組織には、環境を理解して設定する役割をもつ管理者がいるのが一般的です。

Chrome は、管理者ポリシーによるエンタープライズ コントロールを提供しています。企業はソフトウェア スイートと Chrome を密接に統合している可能性があるため、マネージドな拡張機能では引き続きブロッキング版の Web Request API を利用できます。エンタープライズ環境では、システム管理者は OS が提供する仕組みを使って Chrome のポリシーをデプロイすることで、引き続き無料で Chrome を管理できます。

さらなる進化

Declarative Net Request と Manifest V3 の全体は、依然として多くの部分がまだ設計、開発の段階です。コミュニティからのフィードバックに基づいて今後も改善を繰り返し、デベロッパーの皆さんとともにさまざまなユースケースをサポートする取り組みを続けています。

Declarative Net Request API が最初に発表されて以降、このような検討の結果として API に重要な機能を追加しました。現在の Declarative Net Request API では、動的なルールの登録や削除が可能になっています。つまり、マニフェストに静的に登録するのではなく、実行時に指定することができます。また、Referer、Cookie、Set-Cookie などの一般的なトラッキング ヘッダーを削除する機能も追加しています。

私たちは、この API を拡張するその他の方法も積極的に検討しています。たとえば、一致したルールについてフィードバックを得る方法を追加することや、URL 操作と正規表現を活用した高度なリダイレクトをサポートすることなどです。さらに、現在、ルールの制限を拡張機能 1 つあたり最大 3 万個から、全体で最大 15 万個に変更することも計画しています。

今後も私たちは、さらに進化するデベロッパー コミュニティとの連携を続けます。Manifest V3 を採用するためには、デベロッパーの皆さんに拡張機能をアップデートしていただく必要があることは承知しています。引き続き、この移行をサポートする取り組みを続けてまいります。

Reviewed by Eiji Kitamura - Developer Relations Team

この記事は Cloudflare のプロダクト ディレクターである Zack Bloom 氏と、CTO である John Graham-Cumming 氏 による The AMP Blog の記事 "Introducing Cloudflare AMP Real URL" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

AMP プロジェクトの目的は、ウェブ、特にモバイルウェブのブラウジングを快適にすることです。AMP フレームワークは、ウェブページの読み込みを高速化するために設計され、ユーザー エクスペリエンスに重点が置かれています。

当初の主なターゲットは、読者が移動中にニュースやストーリー、解説記事を読む際に、高速で優れたウェブ エクスペリエンスを提供したいパブリッシャー(報道関係など)でした。しかしその後は、e コマースストア、求人、メディアなど、モバイル パフォーマンスを重視するあらゆるサイトに重宝されるようになりました。

AMP HTML フレームワークと同様、AMP もエンドユーザーの近くで AMP コンテンツのコピーを保持するキャッシュを利用していました。これは、コンテンツをできる限り早く読み込めるようにするためです。このキャッシュによってウェブページの読み込みは超高速になりますが、問題も発生します。Google のキャッシュから提供される AMP ページの URL は https://google.com/amp/ から始まるという問題です。これは、エンドユーザーの混乱のもとです。

ユーザーは、ウェブブラウザのナビゲーション バーでアクセスしているサイトを確認できるものだと考えています。AMP キャッシュでは、この考え方が成り立たなくなります。Google のキャッシュからページを提供すると、アドレスバーに表示される「google.com」という URL を見て、ユーザーは混乱してしまうかもしれません。

昨年 11 月、私たち Cloudflare は、この問題に対する技術的なソリューションを発表しました。これは、オリジナルのページの URL を維持したまま、AMP ページをキャッシュから提供できるようにするものです。URL が変わらないことによるメリットも、すべて受け継がれます。詳細については、Gabbi Fisher と Avery Harnish が詳しい技術解説を行っているブログ投稿をご覧ください。このソリューションは、Web Packaging(暗号技術をうまく利用しています)を使って、キャッシュ(Google や Cloudflare などが運用しています)が AMP ページのコピーを保持してエンドユーザーに高速に提供できるようにしています。キャッシュには、元のページがどこから来たのかを暗号学的に証明する証拠も含まれています。
Web Packaging を解釈できるブラウザと連携すれば、ページを AMP キャッシュに格納してそこから高速に提供しつつ、ブラウザのナビゲーション バーにオリジナルのサイトの URL を表示できます。まさに完全勝利です!

私たちが「AMP Real URL」と呼んでいるこの機能は、すべての Cloudflare のお客様が無料で使うことができます。

仕組み

Google の AMP クローラは、1 日に何度も皆さんのウェブサイトのコンテンツをダウンロードし、AMP キャッシュに格納します。サイトで AMP Real URL が有効になっていると、Cloudflare はクローラに提供するコンテンツにデジタル署名を行います。これにより、皆さんが生成したコンテンツであることが暗号学的に証明されます。モダンブラウザ(今のところ Android の Chrome のみ)で Google の検索結果から AMP コンテンツを開くと、この署名があるだけでアドレスバーに正しい URL が表示されます。

さらに重要なのは、これまでと同様に、サイトが Google の AMP キャッシュから提供されていることです。SEO やウェブのパフォーマンスには一切影響を与えません。








Reviewed by Eiji Kitamura - Developer Relations Team

この記事は Chrome ポリシーおよび不正利用防止チーム、Swagateeka Panigrahy、Benjamin Ackerman による Chromium Blog の記事 "Taking Action on Deceptive Installation Tactics" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

Chrome に関するあらゆる作業で最も重視されているのは、プライバシーとセキュリティ、そして透明性です。10 月、私たちは、初期設定のままでも確実に信頼できる Chrome 拡張機能を実現するための変更について発表しましたが、この取り組みはそれで終わるものではありません。

透明性を実現するための取り組みの一環として、Chrome ウェブストアでの拡張機能の「誤解を生じさせるインストール戦略」に対抗するための新しいポリシーを発表します。Chrome 拡張機能のダウンロードに至る手順は、すべての拡張機能の信頼性に影響します。たった一度の悪い体験だけで、デベロッパーの皆さんが作成した多くのすばらしい拡張機能への興味が損なわれかねません。拡張機能そのものだけでなく、デベロッパーのみなさん、そして熱心なユーザーのみなさんによる健全で活発なエコシステムを創り出すには、拡張機能が行うことを最初から正しく想定してもらうことが必要です。

昨年には、ユーザーの透明性向上を目的として、インライン インストールを非推奨とし、すべての拡張機能のインストールにおいて Chrome ウェブストアを経由することを必須化しました。この変更によって、意図しない拡張機能に関するユーザーからのクレームが 18% 減少しました。しかし、誤解を生じさせる拡張機能のインストール フローに関するフィードバックは、継続的に寄せられています。ユーザーの透明性はエコシステムにとって重要な要素なので、こうした取り組みをさらに進め、次のポリシーに基づいて誤解を生じさせるインストール戦略を採る拡張機能を禁止していきます。

拡張機能は、責任を持ってマーケティングされる必要があります。誤解を生じさせるインストール戦略を採用する拡張機能は、Chrome ウェブストアから削除されます。

誤解を生じさせるインストール戦略には、次のようなものがあります。
  • Chrome ウェブストアの掲載項目の直前にマーケティングに関連する不明瞭または目立たない表示が出る。
  • 配布フローの一部に、誤解を生じさせるインタラクティブ要素がある。これには、拡張機能のインストール以外の結果を暗示させるアクション実行ボタンやフォームなどが含まれる。
  • 拡張機能のメタデータをユーザーから隠す効果を使って、Chrome ウェブストアの掲載項目ウィンドウを調整している。

すべてのインストール トラフィックを確認してください。新しいポリシーについてのよくある質問は、Chrome デベロッパー センターで確認できます。

本日(英語版記事公開当時)、Google の Project Strobe の一環として、ユーザーの保護をさらに強化する追加ポリシーも発表しています。拡張機能では、機能の実装に必要なパーミッションを限定的にリクエストすることが義務づけられる予定です。また、より多くの拡張機能にプライバシー ポリシーを掲示して、ユーザーのデータを安全に扱うことを求める予定です。これらの変更点の詳細については、公式ブログへの投稿Chrome デベロッパー センターのよくある質問をご覧ください。



Reviewed by Eiji Kitamura - Developer Relations Team

この記事は Android Media デベロッパー アドボケート、Don Turner による Android Developers Blog の記事 "Capturing Audio in Android Q" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。


Android Q には、アプリで他のアプリのオーディオをキャプチャできる新しい API があります。AudioPlaybackCapture API と呼ばれるこの API を使えば、コンテンツ共有やアクセシビリティを簡単にするいくつかの重要なユースケースを実現できます。
いくつかの例を示します。
  • ライブ字幕生成 - 現在再生しているオーディオ コンテンツの字幕や翻訳をリアルタイムに生成します。実は今年の I/O で紹介したライブ字幕機能もこの API を利用しています。ライブ字幕生成を使うと、公共の場所でヘッドフォンなしで聞く場合など、オーディオ コンテンツを楽しめない状況や楽しみづらい状況でも、ユーザーにアプリを利用してもらうことができます。
  • ゲームの録画とストリーミング - ゲーム内サウンドを録音してライブ視聴者にストリーミングすることで、ゲームのコンテンツを広めることができます。
デベロッパーには、アプリのオーディオがキャプチャされるのを禁止したいケースもあるでしょう。この記事では、ユーザーから見たオーディオ キャプチャの動作と、デベロッパーが必要に応じてアプリのオーディオ キャプチャを禁止する方法について説明します。

ユーザーから見た動作

他のアプリのオーディオをキャプチャするには、ユーザーがキャプチャするアプリにオーディオの録音パーミッションを付与する必要があります。
AUDIO_RECORD パーミッション ダイアログ
AUDIO_RECORD パーミッション ダイアログ
さらに、キャプチャ セッションが始まる前に、キャプチャするアプリで MediaProjectionManager.createScreenCaptureIntent() を呼び出す必要があります。これにより、次のダイアログがユーザーに表示されます。 スクリーン キャプチャ インテント ダイアログ
スクリーン キャプチャ インテント ダイアログ
キャプチャ セッションを開始するには、ユーザーが [Start now] をタップする必要があります。これにより、動画とオーディオの両方がキャプチャされます。
ステータスバーに赤く表示されるキャスト アイコン
ステータスバーに赤く表示されるキャスト アイコン
キャプチャ セッション中は、ステータスバーに赤いキャスト アイコンが表示されます。

アプリのオーディオをキャプチャできるか

デフォルトでアプリのオーディオをキャプチャできるかどうかは、ターゲット API によって異なります。次に、デフォルトの動作をまとめた表を示します。
ターゲット API デフォルトでサードパーティ製アプリがオーディオをキャプチャできるか デフォルトでシステムのアプリやコンポーネントがオーディオをキャプチャできるか
28 以下 不可、アプリで明示的なオプトインが必要 使用タイプが MEDIA、GAME、UNKNOWN のオーディオであれば可
29 使用タイプが MEDIA、GAME、UNKNOWN のオーディオであれば可 使用タイプが MEDIA、GAME、UNKNOWN のオーディオであれば可

サードパーティ製アプリによるキャプチャを禁止する

アプリで、他のアプリによるオーディオのキャプチャを禁止したい場合もあるでしょう。たとえば、次のようなオーディオの内容が該当します。
  • プライベートな情報 - 個人的な録音など
  • 著作権で保護されている素材 - 著作権で保護されている音楽、映画やテレビ番組のオーディオなど
アプリのオーディオ キャプチャ ポリシーは、すべてのオーディオに対して設定することも、個々のオーディオ プレーヤーに対して設定することもできます。

すべてのオーディオでサードパーティ製アプリによるキャプチャを禁止する

すべてのオーディオでサードパーティ製アプリによるキャプチャを禁止するには、以下のいずれかを行います。
AndroidManifest.xml に右の記述を追加する <application
...
android:allowAudioPlaybackCapture="false"/>
オーディオを再生する前に右のコードを実行し、プログラムからキャプチャを無効化する AudioManager.setAllowedCapturePolicy(ALLOW_CAPTURE_BY_SYSTEM)

プレーヤーごとにサードパーティ製アプリによるキャプチャを禁止する

個々のプレーヤーに対してキャプチャを禁止するには、オーディオ プレーヤーを構築する際に次のコードを呼び出してキャプチャ ポリシーを設定します。
AudioAttributes.Builder.setAllowedCapturePolicy(ALLOW_CAPTURE_BY_SYSTEM)
アプリでライセンスの異なるコンテンツを再生する場合は、このアプローチが便利です。たとえば、著作権で保護されているコンテンツと、ロイヤリティ フリーコンテンツの両方を再生する場合です。

システムのアプリやコンポーネントによるキャプチャを禁止する

使用方法が MEDIA、GAME、UNKNOWN である場合、システムのアプリやコンポーネントは、デフォルトでアプリのオーディオをキャプチャすることが許可されています。これにより、ライブ字幕生成などの重要なアクセシビリティ ユースケースが可能になります。
めったにないことですが、システムのアプリによるオーディオ キャプチャも禁止したい場合は、サードパーティ製アプリと同様の方法で対応できます。なお、これを行うと、サードパーティ製アプリによるキャプチャも禁止されます。

すべてのオーディオのキャプチャを禁止する

これは、プログラムによってのみ行えます。最初にオーディオが再生される前に次のコードを実行します。
AudioManager.setAllowedCapturePolicy(ALLOW_CAPTURE_BY_NONE)

プレーヤーごとにキャプチャを禁止する

個々のプレーヤーに対してキャプチャを禁止するには、オーディオ プレーヤーを構築する際に次のコードを呼び出してキャプチャ ポリシーを設定します。
AudioAttributes.Builder.setAllowedCapturePolicy(ALLOW_CAPTURE_BY_NONE)

次のステップ

API 28 以下をターゲットにしているアプリでオーディオ キャプチャを有効化したい場合は、アプリの manifest.xmlandroid:allowAudioPlaybackCapture="true" を追加します。
一部または全部のオーディオ キャプチャを禁止したい場合は、前述の手順に従ってアプリをアップデートしてください。
詳細については、Audio Playback Capture API のドキュメントをご覧ください。

Reviewed by Yuichi Araki - Developer Relations Team

この記事は Thomas Nattestad による Chromium Blog の記事 "WebAssembly brings Google Earth to more browsers" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。


約 14 年前、子どものころの家にズームインできる Google Earth は、ユーザーに興奮の渦を巻き起こしました。ただし、それを体験するためにはアプリケーションをダウンロードし、インストールすることが必要でした。Google Earth がネイティブ アプリケーションとしてリリースされたのは、全世界をリアルタイムにレンダリングするためにブラウザでは利用できない高度なテクノロジーが必要だったからです。 


ウェブは進化し、私たちは Google Earth をウェブ プラットフォームで利用できるようにしたいと考えました。そうすれば多くの人が、全世界を体験簡単に体験できるようになるからです。ウェブアプリは優れたユーザー エクスペリエンスを実現できます。これリンクを張ることができためです。つまりリンクを共有することで、クリック 1 つでアプリにアクセスできるのです。またソフトウェアをダウンロードする際に、ウイルスが紛れ込むリスクもないため安全です。さらにウェブの他の部品に埋め込み、他の機能と組み合わせて使うこともできます。


WebAssembly(Wasm)は、ウェブでネイティブ コードを使えるようにする W3C のウェブ標準です。Earth チームは、Google Earth を複数のブラウザで動作させるために検討を続けてきました。そして、WebAssembly にその解を見つけました。Google Earth が初めてウェブに登場したのは 2 年ほど前です。そのときは、Chrome 限定のソリューションであるネイティブ クライアント(NaCl)が使われました。ブラウザでネイティブ コードを実行し、ユーザーがモダンなウェブ アプリケーションに期待するパフォーマンスを実現する方法は、これしかありませんでした。しかし、すべてのブラウザが同じように新技術をサポートしているとは限らないので、ブラウザ間の互換性を実現するのは容易なことではありません。 


今回、Google Earth に WebAssembly を使った経験から、WebAssembly にはさまざまなブラウザからアプリにアクセスできるようにするだけでなく、オンライン体験をスムーズにできる可能性があると感じています。Google Earth のベータ版プレビューを試せるので、Earth チームが実現したことをご確認ください。実装の詳細については、こちらをご覧ください。


WebAssembly と複数のスレッドを利用するアプリケーションを連携させる方法
WebAssembly を使ってみようと考えている方は、いくつかの仕様を理解しておくことが重要です。特に、スレッドに関することが重要になります。


ブラウザには、マルチスレッドをサポートしているものも、そうでないものもあります。Google Earth では、データが常にブラウザにストリーミングされ、圧縮されたデータが復元され、画面にレンダリングする準備が行われています。この作業をバックグラウンド スレッドで行うことができれば、ブラウザでの Google Earth のパフォーマンスは明らかに向上します。


Chromium ベースのブラウザ(Chrome、将来のバージョンの Edge、Opera など)は、すべて WebAssembly をサポートしています(マルチスレッドに対応しているものも、していないものもあります)。Chromium をベースとした新バージョンの Edge が配布されれば、Edge でも Chrome と同じように WebAssembly アプリが動作するようになるでしょう。Firefox は WebAssembly をサポートしていますが、SharedArrayBuffer の問題により、マルチスレッドのサポートは無効にせざるを得ませんでした。また、Opera は Chromium ベースですが、現在のバージョンの Opera はシングル スレッドでしか WebAssembly をサポートしていません。Safari の WebAssembly 実装は強力ですが、WebGL2 を完全にはサポートしていません。各ブラウザの WebAssembly のサポート状況の詳細については、詳しい技術解説の投稿をご覧ください。


Emscripten: Google Earth のブラウザ移植を実現したツール
ネイティブ オペレーティング システム向けに作られたアプリケーションをウェブに移植するのは、簡単な作業ではありません。Emscripten ツールチェーンは、デベロッパーが C++ を WebAssembly にコンパイルし、ネイティブ アプリケーションが使うたくさんの OS インターフェースをエミュレートする際に役立ちます。たとえば、アプリケーションでは、OS にファイルを開くように伝える POSIX API の fopen を使っているかもしれません。Emscripten がこの呼び出しを見つけると、ローカル ストレージなどのブラウザで使える適切な動作を提示してくれます。OpenGL 呼び出しを WebGL 呼び出しに変換するときも、同じことをしてくれます。他の多くの機能と同様、この機能もネイティブ アプリケーションをウェブに移植する作業を大幅に簡素化するものです。


Emscripten は、他のアプリケーションをウェブに移植する際にも使われています。たとえば、35 年前に作られた AutoCAD のコードベースや、それよりも新しい Sketchup のようなアプリケーションなどです。


WebAssembly の今後
今後 WebAssembly には、いくつかの機能が追加される予定です。以下の機能は、Google Earth のウェブ エクスペリエンスの改善にも役立ちます。


SIMD サポート: SIMD(single instruction, multiple data)では、1 つの CPU 命令が複数のデータに影響を与えます。SIMD を適切に設定すると、データ処理のスループットが上昇します。今年中には、SIMD の一部が初めて WebAssembly でサポートされる予定です。これによって、Google Earth のパフォーマンスが大きく向上することを期待しています。 


ダイナミック リンク: この機能によって、Google Earth の読み込み時間が最適化される可能性があるので、Google Earth を別のウェブページやオンライン体験に埋め込む道が開かれます。現在のところ、連携が必要なモジュールは、すべて同時にコンパイルする必要があります。ダイナミック リンクが利用できれば、アプリケーションをたくさんのモジュールに分割し、小さなクライアントを配布して他のパーツを徐々に読み込むことができます(遅延読み込みと呼ばれています)。


デバッグの強化: 現在の Wasm ではソースマップがサポートされているので、デベロッパー ツールでソースコードを確認できます。これは大きな第一歩ですが、デベロッパーが変数の内容を調べたり、適切なスタック トレースを表示したりできるようにしたいと考えています。

Google Earth は、大きな一歩を踏み出してクロスブラウザ標準を採用しました。これにより、アプリケーションをさらに多くのブラウザに移植できるようになりましたが、今後もさらに改善を重ねる予定です。ぜひ自分のネイティブ コードで WebAssembly を試してみてください。高速で一貫性のある体験をすべてのユーザーに提供しましょう。



投稿者: Web Assembly、V8 およびウェブ機能担当プロダクト マネージャー、Thomas Nattestad


Reviewed by Chiko Shimizu - Developer Relations team

この記事は Will Ro (Head of Android Enterprise Partnerships, Management and Security)による Google Blog の記事 "Google and Samsung simplify choosing Android in the Enterprise" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

Android Enterprise では、Samsung をはじめとするパートナーとの連携に力を注ぎ、世界中の企業が膨大な数の Android デバイスを安全に管理できるようサポートしてきました。セキュリティ分野でも先駆的な Samsung は、企業利用に対応した Android の柔軟なフレームワーク上で高度な機能セットを構築し、企業向けセキュリティ プラットフォーム Knox として提供しています。

Google は、ここ数年の間に企業向け分野で Samsung と一緒に、企業のモバイル管理をよりシンプルにするとともに機能の重複を減らしてきました。そして、Android 8.0 Oreo での Knox Platform for Enterprise(KPE)の導入に伴い、Knox 機能を Android Enterprise のコア フレームワークをベースに構築することとなりました。これにより、Android Enterprise 対応のモバイル管理(EMM)パートナーは、EMM の管理機能の基盤として Android Enterprise を提供しつつ、適切と判断した場合は Samsung Knox を補足的に追加することが可能になりました。

今週のモバイル ワールド コングレス(英: Mobile World Congress)が、Samsung とのパートナーシップの第 2 章の始まりです。新たな共同プロジェクトとして以下の 2 つを推進し、企業向け機能の管理を容易にするとともにデバイス登録オプションを拡張することにしています。
Android OEMConfig で Knox 機能の配信を加速する Samsung
本日 Samsung が、OEMConfig をサポートすることを発表しました。新たに Android 標準となった OEMConfig を使用すると、OEM が独自に開発したデバイス機能を、EMM プロバイダを通じてすぐ提供することができます。OEMConfig の仕組みはシンプルです。

これまで、OEM が独自にカスタマイズしたデバイス機能は EMM 製品内で個別にサポートする必要がありましたが、OEMConfig なら OEM 提供のアプリを使用してすべての独自機能をデバイス上で設定できます。OEMConfig は、Android Enterprise の管理対象アプリの設定 (managed configurations) 機能を応用したもので、Appconfig コミュニティで標準公開されています。

Samsung KPE のような包括的な機能セットは、幅広いセキュリティ機能を提供でき、ハードウェアもきめ細かく制御できる反面、EMM プロバイダにとっては実装に手間がかかるという問題がありました。しかし OEMConfig なら、EMM コンソールで機能ごとにサポートを追加しなくても、Android Enterprise で KPE のすべての機能を提供できます。

加えて、Samsung がリリースした新機能を即座にお客様に提供できるというメリットもあります。Samsung では、OEMConfig をサポートするための Knox Service Plugin(KSP)アプリを今春リリースすることにしています。Android Enterprise 対応ソリューションを提供するすべての EMM ベンダーは、Samsung KPE 機能が KSP アプリを通じて更新されると同時にサポートできるようになります。
Samsung との協力により企業デバイスの一括登録を合理化
Android Enterprise は、デバイスをサーバー上のコンソール経由で一括登録できる「ゼロタッチ登録」機能を備えています。一方、Samsung の Knox Deployment Program(KDP)にも、Samsung デバイス向けに同様の機能を提供する「Knox Mobile Enrollment」が用意されています。どちらもデバイス設定とユーザー登録を自動化し、ユーザーがデバイスを箱から出してすぐに使えるようにするための機能です。

これらの登録機能は、膨大な数の Android デバイスを導入するお客様にとっては大きなメリットがありますが、登録機能を提供するサービス プロバイダにとっては、両方のサービスを統合して提供することが負担となっていました。

こうした負担を軽減するため、Google と Samsung で共通のクライアント ライブラリを開発しました。これにより、Android ゼロタッチ対応のデバイスと Samsung デバイスを共通の API で登録することが可能になります。このライブラリの配布を 2019 年春に開始し、Google と Samsung の両方に対応しているすべてのパートナーがこのシンプルな統合モデルに移行できるようにする予定です。
この先もさらにシンプルに
Google と Samsung が協力し、Android Enterprise による Android デバイス管理をさらにシンプルにすることで、EMM の Android 管理機能の基盤としてお客様に安心してお選びいただけるようにしたいと考えています。パートナーにとっては、自動化された登録サービスを提供できると同時に、Samsung Knox Platform for Enterprise のような機能拡張にも迅速に対応できるようになります。今後も Samsung との連携を継続し、さらに魅力的な企業向けモバイル サービスを提供できるよう努めてまいります。

Reviewed by Ben Seab (Regional Manager, Android Enterprise)

この記事は Ben Morss による The AMP Blog の記事 "Learn web development with AMP!" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。


AMP について学べる新しいコースが公開されました。その名も、Web Development with AMP(AMP によるウェブ開発)です!

ウェブ デベロッパーを目指す方にとって、AMP はまたとない出発点になるはずです。なんと言っても、AMP を使えば JavaScript を使わずにインタラクティブなウェブサイトを作れるのです。HTML と CSS を少し知っているけれど JavaScript はまだ学習したことがないという方は、AMP を使ってインタラクティブなサイトを作れるようになります。

また経験を積んだウェブ デベロッパーで、手間をかけずにパフォーマンスが高く適切に動作するサイトを作りたいと考えている方にもおすすめです。

さらに、ウェブ開発を教えている方は、このコースを無料で使用することができます。初心者にとって、この AMP コースは HTML/CSS と JavaScript のギャップを埋めるカリキュラムになります。その他の方も、このコースから短時間で AMP の原理を学ぶことができます。
Web Development with AMP は、初級、中級、上級のコースに分かれています。各コースは、さまざまな形で利用できます。

今後は、以下のような形で展開する予定です。
  • 今年の夏には、他の 2 つのコースの動画を公開します。
  • さらに高度なデベロッパーや時間のないデベロッパーのために、各コースの短縮版も提供する予定です。

ぜひご利用ください!

投稿者 : Google デベロッパー アドボケート、Ben Morss


Reviewed by Chiko Shimizu - Developer Relations team


いくつかの灰色のピクセルから誕生したモバイルゲームは、21 年の時を経て、映像も音声も美しい、マルチプレーヤーで楽しめる高性能ゲームに成長しました。大人になると、一般に物事はより複雑化します。成功に至る道筋はいくつもあるとは言え、競争が激しくなり、周囲の関係者からのプレッシャーも徐々に、しかし確実に増してきます。

モバイルゲームの状況もそれと同じです。ユーザーは長年にわたりさまざまなジャンルで質の高い体験を享受してきたため、その期待はますます高まっています。モバイルゲーム業界は年率 13% で成長しており(出典: 世界のゲーム市場に関する Newzoo の最新レポート、2018 年 10 月)、多くのデベロッパーが注目を浴びようとしています。この市場では、ユーザーに「発見」されるゲームを開発することが依然としてデベロッパーの重要な任務です。開発サイクルが長期化しコストが膨れ上がる中、より慎重で周到な戦略が求められるような場合は特にそう言えます。


モバイルゲーム マーケティングの進化

そこで出番となるのがマーケティングです。実際のゲーム開発とは切り離して行われることが多かったマーケティング活動やそのためのツールは、かつてないほど重要性を増しています。今日では、ユーザーに発見されるのが早いほど利益になり、それがゲームの収益見通しを大きく左右します。そのため、最近のゲーム開発では、マーケティング担当者があらゆる場面で重要な役割を果たしています。

ゲームのリリース前には、さまざまなテーマに対するユーザーの関心をデベロッパーが評価します。その際利用するのは、対応する広告のテストやクリック率の分析です。リリース時には、短期間での新規ユーザー獲得に適した媒体を吟味して、そのメディアを利用します。リリース後にマーケティングが果たすべき重要な役割は、離脱したユーザーを復活させることと、ターゲットを絞ったキャンペーンを実施することです。そこで、ゲームプレイの最新情報や時期に応じた LiveOps を活用し、ユーザー トラフィックの流れを途切れさせないようにします。

さらに、ゲームが成功を収めるためには、高いユーザー維持率と収益力も必要です。マーケティング戦略が一流だからといって平凡なゲームを改良できるわけではありませんが、平凡なマーケティング戦略は一流のゲームに悪影響を与えます。

ゲームの企画、リリース、運用においてマーケティングが不可欠な要素となる中で、デベロッパーは、ゲーム発見の機会を広げるためのチャネルを継続的に見直して最適化しています。そのためのアプローチとしてよく話題になるのが、YouTube などのプラットフォームでインフルエンサーと提携することです。

デベロッパーと話をすると、インフルエンサー マーケティングの価値についてさまざまな意見が聞かれます。懐疑的な人は、インフルエンサー キャンペーンの管理には労力がかかることや、体験プレイ広告の方が測定しやすいことを指摘します。一方、実際のゲームプレイの様子を見られる動画は、ユーザーの目を引く独特の効果があり、ゲーム コミュニティの構築に一役買うものだという肯定的な意見もあります。

「インフルエンサーを活用すると、広告ネットワークや DSP を介して設定できる一般的なターゲットに入らない人々にリーチできます。また、インフルエンサーのおかげで長期的な見通しが立ちます。コンテンツは通常、インフルエンサーのチャンネルで無期限に配信されるためです。」— Kolibri Games マーケティング ディレクター、Volkmar Reinerth 氏

こうした議論は続いているものの、インフルエンサーは今や無視できない存在だという点では合意が得られそうです。2018 年のモバイルゲーム デベロッパーの投資額は 2 億 5,000 万ドルを超え、今後数年にわたり予算が増加していくという明らかな兆候も見られました(2018 年、Statista/Morar HPI for Rakuten Marketing)。

では、この業界がインフルエンサー マーケティングの真の価値を理解できるよう、賛成派と反対派の双方に行動を起こさせるための有意義なデータを提供したらどうなるでしょうか。データを基に熟慮したアプローチをインフルエンサー マーケティングに適用することで、マーケティング全体への投資を最大限に活かせるとしたらどうでしょう。マーケティングは、ゲームの開発および運用のあらゆる段階で重要な役割を担うようになりました。今日の市場環境でゲームが全体的な成功を収めるためには、インフルエンサーを起用する意義を理解することがカギとなりそうです。

ゲーム デベロッパーに適したインフルエンサー マーケティングとは

Google Play では、デベロッパーの皆様が Android でビジネスの持続的な成功を収められるよう支援したいと考えています。そこでこの 1 年間は、インフルエンサー マーケティングの有効性の研究を行ってきました。その際常に念頭に置いていたのは、これがデベロッパーの利益を左右する課題であり、チャンスでもあるということです。

作業を進めるにあたり、インフルエンサー マーケティングに関して関心のある分野を特定する目的で、開発形態やビジネスの規模を問わず多数のデベロッパーに話を聞きました。すると、デベロッパー コミュニティではいくつもの疑問が湧いていることがわかりました。

たとえば、適切なインフルエンサーを選ぶにはどうすればよいか、提携するうえで最善の方法はどれか、デベロッパーはどこから手を付けるべきか、といった疑問です。その中でも特に大きな課題が 1 つありました。それは、インフルエンサーの動画をどのように管理し、効果を測定すればよいのか、というものでした。こうした動画の費用対効果を明確に理解していないと、たとえパフォーマンス改善の秘策を知っていても十分に活かせません。

最近のインフルエンサー マーケティングにはかかわっていないという方のために、多数のデベロッパーがインフルエンサーの動画の効果をどのように評価しているか、改めてご紹介しましょう。通常、YouTube クリエイターは、プロモーションするゲームへのリンクを動画の説明欄に掲載します。

このリンクは、それをクリックしたユーザー集団によるインストールや収益をトラッキングしています。ただし、すべてのユーザーがこのトラッキング リンクをクリックするわけではないと考えるのが妥当です。その動画を見ながら Google Play の検索バーに直接ゲームの名前を入力するというユーザーもいれば、動画を見ているのとは別のデバイスで後からゲームをダウンロードするユーザーもいるでしょう。

あるいは、動画をフルスクリーン表示にしているために、リンクがクリックできない状態になっていることもあり得ます。そのうえ、APK のサイズが大きくなり続けているため、スマートフォン ユーザーの多くは安定した Wi-Fi に接続できるまで待とうとするものです(この状況を回避する方法をぜひ採用してみてください)。要するに、トラッキング リンクは評価の手がかりにはなるものの、インフルエンサーの動画を見てゲームをダウンロードしプレイしたユーザー、さらには課金にまで至ったユーザーを完全に把握できる方法とは言えません。

こうしたトラッキング リンクの限界に対応するために始まったのが、トラッキングできないユーザーについての仮説を立てることでした。インフルエンサーを利用するプラットフォームと代理店は、キャンペーン データや業界関係者からの情報を基にベンチマークと推定値を用意し、より複雑なモデルを考案しました。そこで Google では、推定値から実際のデータに発展させることで、インフルエンサーの効果測定のレベルアップを図ることにしました。

トラッキング リンクの限界を超えるのは小さな一歩のように見えますが、実際デベロッパーにとっては大きな前進です。この方法をうまく機能させるため、ログインした Android ユーザーから成る匿名化された集団と、これらのユーザーが 2 つの Google サービス(YouTube と Google Play)でどのように行動したかを Google は調査しました。調査データが適切であること、多様なユースケースに幅広く応用できることが不可欠だったため、規模の異なる複数のデベロッパーに連絡を取り、インフルエンサーがゲームをプレイしている動画の提供を依頼しました。ゲームのライフサイクルの各段階に注目し、フォロワー数の多いインフルエンサーと少ないインフルエンサーの両方の動画を調べるためです。

その後、独自の測定モデルを試験的に運用して、ユーザーがインフルエンサーの動画を見た後に Google Play で実際にゲームをダウンロードしたかどうかを検証します。また、ダウンロードしたユーザーの数がトラッキング リンクで測定したときと比べて増えている可能性はあるか、つまり、今まで誰も証明できなかった数値の上昇が見られるかどうかを調べることにしました。

そこで、総視聴回数が 6,000 万回を超える 250 以上のゲーム動画について、動画視聴後のユーザーの行動を調査した後、その調査記録と、各デベロッパーのトラッキング リンクのデータを比較しました。なんと、YouTube でインフルエンサーの動画のトラッキング リンクをクリックしたユーザー 1 人に対し、リンクはクリックしなかったものの視聴後 4 日以内にゲームをダウンロードしたユーザーはその 4 倍もいたのです。

この大きなユーザー グループを、「トラッキングされていない多数派」と呼ぶとしましょう。インフルエンサーと提携する価値を自社の CFO に示す必要があるすべてのマーケティング担当者にとって、4 倍という数字は朗報です。4倍というのは平均かつ控えめな数字で、ゲームや動画の内容によっては、10 倍にさえなり得ます。また、この調査全体のアトリビューション期間を 4 日間と定義しましたが、平均すると、全ユーザーの 50% が視聴後 4 時間以内にゲームをダウンロードしていることがわかりました。つまり、インフルエンサーの動画は明らかに、従来のトラッキング リンクよりもはるかに多くのユーザーにリーチして、即座に行動を起こさせているのです。

「当社では長年にわたり、インフルエンサー キャンペーンによるパフォーマンス向上効果を観察、測定しています。この効果を追跡しやすくなったことは、非常に有意義です。」— Space Ape Games CMO、Mickey Elimelech 氏

バイラル効果の影響力と限界

効果はそれだけではありません。この調査の実施中に、参加者であるデベロッパーとその結果について議論する中で、インフルエンサーを活用する価値についてさらなる見識が得られました。そのひとつが波及効果です。ゲーム デベロッパーの多くは、さまざまなタイトルを管理することで収益を分散させ、タイトル間の相互プロモーションを促すというポートフォリオ戦略を実施しています。

通常、これらのゲームでは同じオーディエンスをターゲットとしているため、離脱しそうなユーザーを別のゲームに誘導することができます。シェアの奪い合いはデベロッパー自身のゲーム同士で起きるだけです。さて、この調査で 250 以上のゲーム動画を分析した結果、1 つのゲームをプレイする動画を公開すると、ほぼ同じカテゴリに属する同種のゲームのインストール数が増えることが判明しました。インフルエンサーの動画を見てゲーム A をダウンロードしたユーザーが 10 人いたとすると、同時期における類似のゲーム B のインストール数が 1 件増えると予想できるのです。

しかも、これは先ほどと同じく平均値であり、IP が非常によく似ているケースではゲーム A とゲーム B の比率が 10:3 になることもありました。複数のゲームで同じオーディエンスをターゲットにするポートフォリオを運用しているものの、インフルエンサー マーケティングをまだ試したことがないデベロッパーにとって、これは注目に値するデータと言えるでしょう。

ユーザー行動に関するこれらの分析結果とは別に、この調査ではインフルエンサーの活用の仕方についても理解を深めることができました。同じクリエイターが短期間に複数回登場した場合、必ずしもダウンロード数が増えるわけではないことが明らかになったのです。あるインフルエンサーがモバイルゲームを紹介する動画のプロモーションを行った後、そのインフルエンサーが登場する 2 本目の動画を 12 か月以内に公開した場合、後者でのゲームのダウンロード数は前者のときと比べて最大で 3 分の 1 まで減少していました。

これは、まったく予想外の結果というわけでもありません。それでも、インフルエンサー戦略を立てるときは、いわゆる「ダウンロード疲れ」を念頭に置いておく必要があります。この状況は、クリエイターのコミュニティではすでにゲームがダウンロードされていたか、あるいはダウンロードが選択されなかったということです。第一印象を与えられるチャンスは一度しかなく、モバイルゲーム業界では特にそれが当てはまります。では、インフルエンサーの活用は 1 回限りにすべきなのでしょうか。インフルエンサーをインストール数増加のためのチャネルと考えるのであれば、そうすることをおすすめします。

ただし前述のように、ゲームのリリースは、モバイルゲーム ビジネスの半分にすぎません。本当の課題はその運用を成功させることであり、既知のコミュニティへの再アプローチは、そのための有効な手段となり得ます。人生でもよくあるように、そこには正解も不正解もありません。ただタイミングと理由だけが重要なのです。

「こうした分析結果をすべてまとめることで、有望なインフルエンサー戦略の形が見えてきて、ひいては成功につながります。」— Kolibri Games マーケティング ディレクター、Volkmar Reinerth 氏

インフルエンサーが効果をもたらす理由

ここで、「理由」という大きな問題に再び直面します。つまり、インフルエンサーを活用する理由です。デベロッパー コミュニティ全体がこのオピニオン リーダー達とのコラボレーションを強く望んでいるという事実もさることながら、先に取り上げたように正当な理由はいくつもあります。

いずれも胸を躍らせるのに十分な理由ではありますが、ひとつ忘れてはならないのは、インフルエンサーの動画はアプリ インストール キャンペーンではないことです。アプリ インストール キャンペーンの場合は、キャンペーンの目標、入札戦略、クリエイティブを選択するだけで十分な結果が得られます。しかし、インフルエンサーとの提携ではそうはいきません。提携する適切なクリエイターの選択、関係構築、ビジネス条件の交渉、最終的な動画の準備には、より多くの時間を割く必要があります。

こうした明らかな違いにもかかわらず、パフォーマンス マーケティング担当者の多くはこの 2 種類のキャンペーンを同列に評価しています。また、広告費用対効果の比較においては、インフルエンサー マーケティングに収益性があるとは考えていません。そこで皆さんに質問です。

あなたは、測定が困難であるものの欠かすことのできない側面も考慮して、本当に価値全体を評価しようとしているでしょうか。あらゆるマーケティング活動は、それ自体で、あるいは他の要素と組み合わせて(テレビと検索の組み合わせは今でも典型例です)、利益を生むことが求められます。ユーザー コミュニティを通じてつながっているユーザーの長期的価値は、他の形態のパフォーマンス マーケティングを実施した場合より大きいと言えます。

トラッキングされていない多数派によるダウンロード数がトラッキング リンクの 4 倍になるうえに、インフルエンサーは貴社のゲームまたは貴社そのものに個性を与えてくれる存在です。つまり、今の世の中、大規模な新しい未知の IP をインフルエンサーの協力なしに立ち上げることは、結果として無謀な試みに終わる可能性があります。

「新しいシューティング ゲーム、FRAG をリリースするにあたり、当社では YouTube でインフルエンサーと提携しています。潜在的なプレーヤーが、このプラットフォームで動画の視聴に多くの時間を費やしているからです。私たちは、このゲームをあらゆる人に見つけてほしいのです。」— Oh BiBi CRO、Solène Delooz 氏

それでもインフルエンサーとの提携をためらうという方は、インフルエンサーを使ったキャンペーンを実施する際に陥りやすい誤りを回避するとよいでしょう。YouTube でクリエイターとのコラボレーションをテストする簡単な方法は、狭い範囲で影響力を持つインフルエンサー、いわゆる「マイクロ インフルエンサー」と提携することです。

この種のクリエイターはチャンネル登録者数が比較的少人数(1 万~20 万人程度)で、たいてい提携の話には非常に前向きです。ゲーム デベロッパー側のメリットとしては、コストの節約、リスクの抑制、コミュニティをゼロから構築できるチャンスなどが挙げられます。デベロッパーとクリエイターが共にユーザーベースを拡大できれば理想的です。

「初めてのゲームのプロトタイプ開発を始めた最初の週から「インフルエンサー的」な人たちの話を聞きました。彼らは、ゲームを一緒にプレイしたりハイレベルな競争をしたりする友人から成るグループを形成していました。その過程で何人かのクリエイターにも会いました。YouTube のチャンネル登録者数が 10 万人になると大騒ぎした時代です。彼らと連絡を取り続けた結果、当社の「インフルエンサー戦略」は過去 7 年にわたり自然な形で発展しました。現在一緒に仕事をしているメガ インフルエンサーの中には、最初の頃のマイクロ インフルエンサーもいます。単なるチャンネルとの取引にとどまらず、何年も続く関係を構築し、純粋に興味を持って、インフルエンサーの成功に投資する取り組みなのです。」— Space Ape Games CMO、Mickey Elimelech 氏

ゲーム デベロッパーは、マイクロ インフルエンサーとの交渉は有名クリエイターとのコラボレーションと比べると有利に進められることに気付くでしょう。Google の調査データによると、すべてのインフルエンサーの動画をチャンネル登録者数ベースで分類すると、マイクロ インフルエンサーの CPI は、チャンネル登録者数が多いクリエイターと比較して最大で 3 分の 1 程度に抑えられます。

これは、トップ クリエイターとの提携関係を解消すべきだという意味ではありません。そこには他の利点も存在するからです。チャンネル登録者数が多いインフルエンサーはコミュニティ エンゲージメントの規模も大きく、他のクリエイターに良い影響を与えたり、コンバージョンに至ったユーザーの LTV を高めたりすることもあります。一方、インフルエンサーを起用することに慣れていない、あるいはインフルエンサー マーケティングのリスクを回避したいデベロッパーにとって、マイクロ インフルエンサーは最適な提携先です。

リスクの回避と言えば、ゲームの開発プロセスにインフルエンサーを採用するタイミングが早いほど、彼らが本当にプレイしてみたいと思えるゲームになる可能性が高くなります。フィードバックは貴重なものであり、インフルエンサーからのものであればなおさらです。これまでに何度も目にしたのは、リリースからすでに 2 年が経過し、動画での公開には適さないゲームをプレイするようインフルエンサーを説得しようとするデベロッパーの姿です。

時代の先端を行く実況可能なゲームを作るためには、開発の初期段階でインフルエンサーとの関わりを持つことをおすすめします。そうすれば、早いうちからインフルエンサーのフィードバックを聞けるだけでなく、インフルエンサー自身もベータ版テスターであることを誇りに思って、最新の状況を自分のコミュニティに伝えることができます。

その好例と言えるのが、Space Ape Games による「Rumble League」でのインフルエンサーの起用です。ロンドンを拠点とするこのデベロッパーは、プロ ゲームチームの Team Secret をオフィスに招待し、ゲーム「Rumble League」について紹介した後、プロチームとデベロッパー自身が参加する小さなトーナメントを開催しました。

このゲームとゲームの成否に関する評価はまだ公開されていませんが、Space Ape Games はすでに、リリースの数か月前から高度なマーケティング戦略を展開しています。これは、リリース当日のみに注力してきた従来のモバイルゲーム デベロッパーにとって、学ぶべきところの多い事例です。

「開発プロセスのごく早い段階でインフルエンサーに参加してもらうことで、ゲームが視聴者に受け入れられるとインフルエンサーが思う理由をよく理解できるようになり、それに合わせてゲームを作ることができる、と私たちは確信しています。インフルエンサーのためにゲームを作るということではありません。むしろ、何百万というファンを惹きつけるための手がかりとしてインフルエンサー自身が何に注目するかを理解することが目的です。ゲームの開発プロセスや展望に関する知識が深まるほど、インフルエンサーは自らのチャンネルをレベルアップできるチャンスを確実につかめるようになります。」— Space Ape Games CMO、Mickey Elimelech 氏

最後に: すべてのマーケティング担当者が知っておくべきこと

今回の調査から得られた有益な情報やおすすめの方法が、インフルエンサーを活用する本当の価値を理解するうえで皆さんのお役に立てば幸いです。デベロッパーの規模の大小を問わず、インフルエンサーと関わりを持つべき理由はいくつもありますが、この記事を読んだ後も特に忘れないでいただきたいことを最後に 4 つ挙げておきます。


トラッキングされていない多数派: 大部分のユーザーがゲームをダウンロードするのはインフルエンサーの動画を見た後です(インフルエンサーの動画を見た後で、説明欄のリンクはクリックしていません)。トラッキングされていない多数派によるダウンロード数が、トラッキング リンクの 4 倍になることを考慮しましょう。


波及効果: ゲームのプロモーションにインフルエンサーを起用した場合、類似のゲームのダウンロード数も増えることに注目しましょう。類似ゲームのダウンロード数が増える割合は、元のゲームの 10 分の 1 です。なお、競合ゲームのインストールを促す可能性もある点に注意してください。


ダウンロード疲れ: インストールのチャンスは最初の 1 回限りです。1 人のインフルエンサーが同じゲームをプレイする 2 本目の動画を 12 か月以内に公開すると、最初の動画と比べてダウンロード数が最大で 3 分の 1 まで減少する場合があります。


マイクロ インフルエンサー: インフルエンサーを試しに使ってみたい場合は、チャンネル登録者数が 20 万人以下と比較的少人数のインフルエンサーに依頼しましょう。マイクロ インフルエンサーの CPI は、著名なクリエイターと比較して最大で 3 分の 1 程度に抑えられます。

以上のポイントを考慮に入れることにより、ゲームのリリース前、リリース時、リリース後のどのタイミングでも、ユーザーを獲得し惹きつけるためのマーケティング投資の効果を最大化できます。結局のところ、大人になったときに重要なのは、最終的に結果を出すことです。この先の 21 年も、モバイルゲーム業界で大きく成長しましょう。

Reviewed by Kentaro Meiseki (Gaming Partnerships, APAC)

この記事は Chromium Blog の記事 "Chrome 76 Beta: dark mode, payments, new PWA features and more" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

 特に記載のない限り、下記の変更は Android、Chrome OS、Linux、macOS、Windows 向けの最新の Chrome Beta チャンネル リリースに適用されます。ここに記載されている機能の詳細については、リンクまたは ChromeStatus.com の一覧でご確認ください。2019 年 6 月 13 日の時点で Chrome 76 はベータ版です。

ダークモード

現在、多くのオペレーティング システムのシステム設定で、反転したカラーパターンがサポートされています。これは、システムによって「ダークテーマ」や「ダークモード」と呼ばれています。


prefers-color-scheme メディアクエリを使うと、ユーザーが設定したディスプレイ モードをウェブサイトやウェブアプリで採用できます。CSS コードで次のようなクエリを使ってみてください。


@media (prefers-color-scheme: dark) {
  body {
    color: white;
    background-color: black;
  }
}


さらに詳しい説明を読んでみたい方は、Hello Darkness, My Old Friend という記事をご覧ください。

Payments API

直近のいくつかのバージョンの Chrome では、Payments API にたくさんの改善を行っています。この API は、自分でユーザー インタラクションを構築しなくても、専用の支払いシステムとやり取りを行えるようにするものです。Chrome 75 では、hasEnrolledInstrument()canMakePayment() に置き換えられている、課金アドレスから languageCode が削除されているなどの変更が行われています。また、Chrome 75 の PaymentRequest.show()detailsPromise オプションを使うと、サーバーを呼び出してから支払いの詳細を表示することができます。

Chrome 76 では、Payments API に関する 3 つの変更が行われています。今回実装されたのは、ユーザーが支払い手段を変更したとき、販売者のウェブサイトやウェブアプリが応答できるようにする機能です。PaymentRequestEvent に新しく changePaymentMethod() メソッドが追加され、PaymentRequest オブジェクトが paymentmethodchange というイベント ハンドラをサポートしています。どちらも、ユーザーが支払い手段を変更した際に販売者に通知を行うことができます。前者は、新しい PaymentRequest インスタンスとして解決される Promise を返します。

さらに、Payments API をローカル開発環境の自己署名証明書と合わせて使うのが簡単になっています。これを行うには、—ignore-certificate-errors フラグを追加してコマンドラインから Chrome を起動します。

これらの機能についての詳しい情報は、Web Payments のアップデートをご覧ください。

プログレッシブ ウェブアプリの改善

プログレッシブ ウェブアプリの PC へのインストールが簡単に

通常、PC では、プログレッシブ ウェブアプリがインストール可能であることはユーザーに示されません。たとえ示されるとしても、インストール フローはその他メニューの中に隠されてしまいます。

Chrome 76 では、アドレスバーにインストール ボタンが追加され、ユーザーがプログレッシブ ウェブアプリを簡単に PC にインストールできるようになっています。


サイトがプログレッシブ ウェブアプリのインストール可能基準を満たす場合、Chrome はアドレスバーにインストール アイコンを表示します。デベロッパーによる追加作業は必要ありません。ボタンをクリックすると、PWA をインストールする確認画面が表示されます。

ホーム画面に追加するためのミニ情報バーの制御

Chrome 76 では、ホーム画面に追加するためのミニ情報バーを制御できます。




Chrome は、ユーザーが初めてプログレッシブ ウェブアプリのインストール可能基準を満たすサイトにアクセスすると、ミニ情報バーを表示します。しかし、ミニ情報バーを表示せず、独自の方法でインストールをおすすめしたいというデベロッパーもいるでしょう。

これを行うには、beforeinstallprompt イベントを監視し、その中で preventDefault() を呼び出します。その後、UI をアップデートしてインストール ボタンなどの要素を追加し、ユーザーに通知します。PWA のインストールを推奨する方法には、アプリによっていくつかのパターンがあります。

ホーム画面に追加するためのミニ情報バーは、依然として暫定的な手段です。私たちは、ユーザーがプログレッシブ ウェブアプリをインストールできるようにするための新しい UI パターンも実験しています。これは、ユーザーのブラウズ体験を損なわないような形で行っています。

WebAPK のアップデート頻度の増加

Android に PWA がインストールされると、Chrome は自動的に WebAPK をリクエストしてインストールします。そして、Chrome はマニフェストが変更されたかどうか、新しい WebAPK が必要かどうかを定期的にチェックします。Chrome 76 以降では、Chrome がマニフェストをチェックする頻度が上がり、3 日に 1 度ではなく、毎日チェックが行われます。重要なプロパティが変更されていた場合、Chrome は新しい WebAPK をリクエストしてインストールします。

今回のリリースに追加されたその他の機能

Animation.updatePlaybackRate

Animation.updatePlaybackRate() が追加されます。これにより、アニメーションが目に見える形で飛ぶことがないようにしつつ、シームレスに再生速度を変えることができます。新しい再生速度が反映される際、現在時間は保存されます。

非同期クリップボード: イメージの読み取りと書き込み

Async Clipboard API でプログラムからのイメージのコピーと貼り付けが実装されます。この変更により、navigator.clipboard.read()navigator.clipboard.write() も仕様に準拠するようアップデートされます。プログラムからのイメージのコピーと貼り付けは、Chromium で最も多くスターが付いているバグです。

ユーザー アクティベーションから Escape キーを除外

Escape キーは、ユーザー アクティベーションとして扱われなくなります。ブラウザは、ユーザーが直接インタラクションでページをアクティベーションした場合を除き、不正使用可能な API(ポップアップ、全画面、バイブレーションなど)の呼び出しをブロックします。すべてのインタラクションでユーザー アクティベーションが発生するわけではありません。たとえば、リンクのクリックやテキストボックスへの入力はアクティベーションと見なされますが、画面で指をスワイプしたり、マウスカーソルを合わせたりする動作はアクティベーションとは見なされません。ユーザーが Escape キーを押した場合、ページとインタラクションすることは意図していないので、ユーザー アクティベーションが発生するべきではありません。

メタデータの取得

リクエストの出所(クロスサイトかどうか、<img> に由来するものかどうか、など)に関する追加メタデータをサーバーに送信する新しい HTTP リクエスト ヘッダーが導入されます。これは、サーバーがセキュリティに関する判断を行えるようにするためのものです。これにより、サーバーの応答タイミングに基づく攻撃(XSS リークなど)を緩和できる可能性があります。

たとえば、銀行の「すべての預金を送金」エンドポイントが <img> タグから参照されることは考えられません。同様に evil.com が正当なリクエストを行うことも考えられません。こういったリクエストは、アプリケーションのバックエンドに送るのではなく、あらかじめサーバーが拒否できるのが理想です。

form.requestSubmit()

form.requestSubmit() 関数が追加されます。この関数は、フォームの送信をリクエストします。これには、インタラクティブな制約の検証、submit イベントのディスパッチ、送信ボタンの参照などが含まれます。

ImageCapture が focusDistance 制約をサポート

Image Capture API は focusMode をマニュアルに設定する手段を提供していますが、焦点距離を設定できなければ役に立ちません。この変更により、焦点範囲の値の取得と焦点距離の値の設定を行うインターフェースが提供されます

Animation.pending の実装

Web Animations API に pending 属性が追加されます。ペンディング中のアニメーションとは、再生状態に影響する非同期オペレーションを待っているアニメーションです。この属性は単にシグナルを参照できるようにしているだけなので、これがサポートされたことでアニメーションの描画やタイミングに影響が及ぶことはありません。

IndexedDB トランザクションの明示的コミット API 呼び出し

IDBTransaction オブジェクトに commit() 関数が追加されます。この関数は、これ以上追加のリクエストを受け付けないものとして明示的にトランザクションをマークします。現在の IndexedDB では、すべての関連リクエストの completion イベント ハンドラが実行され、イベント ハンドラが新しいリクエストをキューに格納していない場合にのみ、トランザクションがコミットされます。デベロッパーは、明示的に commit() 関数を呼び出して数サイクルのイベントループを節約し、トランザクションの遅延を回避することができます。

明示的コミットの主なメリットは、オブジェクト ストアに対して行われる読み取りや書き込みのリクエストのスループットが増加することです。オペレーションの処理速度で見れば、明らかなパフォーマンスのメリットがあります。さらに、スピードの増加によってトランザクションの生存期間内に破壊的なイベントが発生する確率が減るので、IndexedDB の安定性が向上するというメリットもあります。

JavaScript

DateTimeFormat の dateStyle と timeStyle
Intl.DateTimeFormat の関数のオプションに dateStyletimeStyle が追加されます。具体的には、formatToParts() 関数と resolveOptions() 関数が対象になります。これらのオプションにより、指定された長さのスタイルで、言語 / 地域に固有な正しい日付と時刻を簡単にリクエストできるようになります。

言語 / 地域に対応した BigInt.prototype.toLocaleString と Intl.NumberFormat format/formatToParts の BigInt 対応
BigInt.prototype.toLocaleString() が変更され、言語 / 地域に対応した数値形式になります。また、Intl.NumberFormat.prototype.format()formatToParts() が変更され、BigInt を入力できるようになります。

Worker のメディア機能

すべてのタイプの Worker で Media Capabilities API が有効になり、ウェブサイトやウェブアプリが最適なメディアを選択して Worker からストリーミングできるようになります。この情報は、後ほど Worker から MediaStream を作る際に利用できます。

Promise.allSettled

Promise.allSettled() が追加されます。これは、Promise の状態のスナップショットの配列を含む Promise を返します。この Promise は、すべてのオリジナルの Promise が完了(成功または拒否)した後に解決されます。

Blob インターフェースのシンプルな読み取りメソッド

Blob インターフェースに 3 つの新しいメソッドtext()arrayBuffer()stream() が追加され、いずれも読み取りオペレーションを実行します。

WebRTC

RTCSctpTransport
max-message-sizemax チャンネル数などの WebRTC データ チャンネルを転送する SCTP トランスポート情報を参照できるようになります

RTCRtpSender.setStreams
RTCRtpSender に関連付けられたトラックとストリームとの関連付けを変更できるようになります。ストリームの関連付けを行うと、同じストリーム内のトラックが同期されます。これは、RTCRtpSender.replaceTrack() を使っているアプリで、ユーザーが通話中に前面カメラから背面カメラに切り替える場合などに便利です。受信側では、新しいトラックを既存のストリームと関連付け、そのストリームの自動トラックと同期させる必要があります。

RTCRtpTransceiver.setCodecPreferences()
setCodecPreferences() メソッドが追加されます。これは、ユーザー エージェントが使用するデフォルトのコーデック プリファレンスを上書きします。これにより、アプリケーションが特定のコーデックに関するネゴシエーションを無効化できます。また、コーデックを送信するリストの最初に設定することで、リモートピアにそのコーデックを優先させることができます。

white-space: break-spaces

通常、保持されている空白の列は改行せずに、行がはみ出します(CSS Text Module 仕様のトリミングと位置決めのルールに記載されています)。white-space:break-spaces 値を使うと、これを改行させるように指定できます。

削除分

Feature Policy の削除: lazyload

lazyload Feature Policy は、<iframe> タグや <img> タグの lazyload 属性をデベロッパーが個別に制御し、埋め込みコンテンツやイメージの読み込み遅延をオリジンごとに制御できるようにするためのものでした。

読み込み用の新しい Feature Policy である loading-frame-default-eager が導入されたため、この Policy は削除されます。新しい Policy は、loading 属性の使用方法と密接に連携するようになっています。Policy の削除は、Feature-Policy ヘッダーと <iframe> allow 属性の両方に適用されます。

MediaStreamAudioDestinationNode から出力を削除

仕様に従えば、Web Audio API の MediaStreamAudioDestinationNode は出力を行うべきではありません。Chrome の実装にある 1 つの出力は、削除されました

DeviceMotionEvent の安全でない使用方法の削除

2015 年以降、Chromium はこの API が安全でないブラウジング コンテキストで使用された場合に、サポート終了の警告を表示しています。今後、Chrome は、この API の使用を安全なブラウジング コンテキストに制限します。この変更により、Chromium の実装は仕様のプライバシーおよびセキュリティの推奨事項に準拠します。また、安全でないオリジンで強力な機能のサポートを終了するという方向性とも一致します。

DeviceOrientationEvent の安全でない使用方法の削除

2015 年以降、Chromium はこの API が安全でないブラウジング コンテキストで使用された場合に、サポート終了の警告を表示しています。今後、Chrome は、この API の使用を安全なブラウジング コンテキストに制限します。この変更により、Chromium の実装は仕様のプライバシーおよびセキュリティの推奨事項に準拠します。また、安全でないオリジンで強力な機能のサポートを終了するという方向性とも一致します。


Reviewed by Eiji Kitamura - Developer Relations Team