Quantcast
Channel: Google Developers Japan
Viewing all 2206 articles
Browse latest View live

Actions on Google を使った開発を始めてみましょう

$
0
0
[この記事は Jason Douglas、Actions on Google 担当 PM ディレクターによる Google Developers Blog の記事 "Start building Actions on Google" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

Google Assistant は、ナレッジグラフから自然言語処理に至るまで、長年積み上げてきたテクノロジーや知能を統合したものです。Assistant を効果的に活用するには、ユーザーの生活の中でさまざまなアプリやサービスをつなげることが必要になります。そのためには、デベロッパーが Google Assistant を通して多種多様なサービスをユーザーに提供するためのエコシステムを構築することがとても重要だと考えています。

10 月には、Google Assistant のデベロッパー プラットフォームである Actions on Google のプレビュー版を公開しました。Actions on Googleを使うと、Assistant に独自のサービスを追加できるため、Assistant のユーザー体験をさらに向上させることができます。本日(*原文公開当時)より、Google ホームの会話アクションが開発できるようになりました。さらに、プラットフォームへのフィードバックを行う事が可能な、アーリーアクセスパートナーへの申し込みフォームも公開しました。

Google Home の会話アクション

会話アクションを活用すると、ユーザーに情報、サービス、サポートを提供できます。特徴的な部分としては、会話アクションを通じて本当に Assistant と会話ができることです。ユーザーには特殊な技術や、アプリをインストールする必要もありません。ただ話しかければよいだけです。現在、デベロッパーを対象に、何が実現可能かを説明する 2 つのサンプルが提供されています。「Ok Google, talk to Number Genie」と話しかけると、数当てゲームができます。または、「Ok Google, talk to Eliza」と話しかけると、1960 年代の傑作 AI と会話できます。


デベロッパー向けの Actions on Google ウェブサイトにアクセスすると、すぐに開発を始めることができます。スムーズで直感的な開発を実現するため、Google は会話インタラクション開発ツールの API.AI や Gupshup、アナリティクス ツールの DashBot や VoiceLabs、コンサルティング会社の Assist、Notify.IO、Witlingo、Spoken Layer など、さまざまな開発パートナーと連携してきました。また、一連のサンプルや音声ユーザー インターフェース(VUI)リソースも作成しています。今後数週間でリリースされる予定のアーリーアクセス パートナーによる統合アプリを試すこともできます。

Wayne Piekarskiによる会話アクションの紹介


近日公開: Pixel や Allo 向けのアクション、購入や予約への対応

この取り組みはまだ始まったばかりで、みなさんが開発される Google Assistant 向けアプリを見るのを楽しみにしています。今後も、プラットフォーム機能の追加は継続され、Pixel スマートフォンや Google Allo など、各種アシスタントで利用できる統合アプリを作れるようになります。購入や予約にも対応するだけでなく、業界を問わず、複雑なアシスタントとも連携していく予定です。今後公開されるこのような機能を利用してアクションを作ってみたいデベロッパーのみなさんは、ぜひアーリーアクセス パートナー プログラムに登録してください。ともにこのプラットフォームの将来を作り上げてゆきましょう。
さまざまな開発を試して、Actions on Google を使ってみた感想をお聞かせください。最新情報を入手するには、ニュースレターに登録し、Google+ コミュニティに参加してください。StackOverflowでの質問には、「actions-on-google」タグをご利用ください。


Posted by Takuo Suzuki - Developer Relations Team

Chrome for Android で試せる WebVR API のご紹介

$
0
0
[この記事は Brandon Jones、バーチャル リアリティ工作人による Chromium Blog の記事 "Introducing the WebVR API in Chrome for Android" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

急速に普及しているバーチャル リアリティ(VR)は、今やウェブにも広がりつつあります。ウェブの力は、ブラウザやハードウェアに制限されることなく VR を動作させ、ワンクリックで VR へのアクセスを実現できる点にあります。VR デベロッパーは、1 つのウェブアプリだけでさまざまなタイプのヘッドセットのユーザーに対応できるようになります。以下では、WebVR を始める方法を紹介します。

現在、Android 向けの Chrome 56 ベータ版が公開されています。オリジン トライアルに登録したウェブ デベロッパーは、WebVR APIGamePad API 拡張機能を使うことができます。WebVR API を使うと、Daydream View などのバーチャル リアリティ デバイスの入出力機能にアクセスできます。また、ユーザーの位置や向きにもアクセスできるので、ウェブアプリからヘッドセットのディスプレイに立体的な 3D シーンをレンダリングできます。Gamepad API 拡張機能を使うと、Daydream コントローラなどのモーション コントローラからの入力にアクセスでき、VR での自然なインタラクションが実現できます。

オリジン トライアルを使っているデベロッパーは、自分のウェブサイトにアクセスしたすべての Chrome ユーザーの機能を一時的に有効化することができます。WebVR API はまだ進化の途上にあり、デベロッパーの皆さんのフィードバックに基づいてさらに変更する予定です。デフォルトですべてのページで有効化されるのは、その後です。今後の Chrome のリリースで、WebVR は PC プラットフォームや Google Cardboard にも拡張される予定です。Chrome 57 ではさらに、パフォーマンスも改善されます。

初めての WebVR ウェブアプリを作る方法を学んでみたい方は、WebVR デベロッパー サイトにアクセスして、チュートリアルやサンプルをご覧ください。ぜひ議論に参加し、APIChrome 実装へのフィードバックをお送りください。また、WebVR Slack チャンネルにも参加してください。


Posted by Eiji Kitamura - Developer Relations Team

Google Slides API でテキストの書式を設定する

$
0
0
[この記事は Wesley Chun@wescpy)、G Suite デベロッパー アドボケートによる G Suite Developers Blog の記事 "Formatting text with the Google Slides API" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

プレゼンテーションで、オーディエンスにアイデアを伝えるために写真や画像を使うのは常識です。そのため、優れたプレゼンテーションを作成するベスト プラクティスの 1 つは、全体的にテキストをなるべく少なくすることです。つまり、プレゼンテーションにテキストを 入れるなら、(わずかに)使うテキストは印象的 かつ視覚的にも美しいものでなければなりません。ソフトウェア アプリケーション、たとえば Google Slides APIで生成されるスライドであれば、手で作るスライドよりもなおさらそれが重要になります。

先日、G Suite チームは Slides API の初版をリリースし、まったく新しいカテゴリのアプリケーションへの扉を開きました。それ以降、この API の持つ可能性をみなさんに実現していたくため、スライドのテキストや画像を置き換える方法やスプレッドシートのデータからスライドを生成する方法など、いくつかの動画を公開しています。今回は、主要 API の 3 つの使用例の最後となる、テキストの書式設定についてお伝えしましょう。


Google スライド内のテキストは、API リクエストを送信して操作できます。Google Sheets APIと同じく、リクエストは JSON ペイロード形式で API の batchUpdate()メソッドに送信します。次に示すのは、スライド内のある図形(shapeID)の中にテキストを挿入する JavaScript です。
{
"insertText": {
"objectId": shapeID,
"text": "Hello World!\n"
}


動画をご覧頂ければ、上の例のリクエストのように、テキストを 書き込む操作はテキストの読み取りや書式設定よりも複雑ではないことがおわかりと思います。テキストの読み取りや書式設定は、どちらもスライド内のテキストがどのような構造になっているかを理解している必要があるからです。書き込みに必要なのはコピー(オプションでインデックスも指定できますが、指定しなかった場合のデフォルトは 0)だけです。

スライドの図形に正常に「Hello World!」が挿入されると、次のリクエストで「Hello」だけを太字にできます。
{
"updateTextStyle": {
"objectId": shapeID,
"style": {
"bold": true
},
"textRange": {
"type": "FIXED_RANGE",
"startIndex": 0,
"endIndex": 5
},
"fields": "bold"
}


上記のような 1 つ以上のリクエストを requestsという配列に格納できたら、API を 1 回呼び出すだけでその操作を実行できます(サービス エンドポイントを SLIDES、スライドデッキ ID を deckIDとしています)。

SLIDES.presentations().batchUpdate(presentationId=deckID,
body=requests).execute()

Google スライドのテキストの構造やスタイル設定について理解を深めたい方は、ドキュメントのテキスト コンセプト ガイドをご覧ください。DevByte で取り上げたコードサンプルの 全容については、さらに詳しく取り上げている投稿をご覧ください。一般的な API の操作の他のサンプルは、こちらのページをご覧ください。これらの動画やデベロッパー リソースが次のすばらしいアプリの作成に役立つことを願っています。ぜひ、ユーザーのために印象的なプレゼンテーションの作成を自動化するアプリを作ってみてください。


Posted by Eiji Kitamura - Developer Relations Team

ExifInterface Support Library が登場

$
0
0
この記事は Ian Lake による Android Developers Blog の記事 "Introducing the ExifInterface Support Library" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

Support Library 25.1.0のリリースに合わせて、新たに ExifInterface Support Library が追加されました。Android 7.1 では、フレームワークの ExifInterfaceが大幅に改善されています。そのため、ごく自然な流れとして、Support Library にも ExifInterfaceが導入され、API 9 以降のすべての端末でその機能が利用できるようになりました。

機能が改善されたとはいえ、画像ファイルに埋め込まれた Exifタグを読み書きするという基本機能は変わっていません。現在の Exif タグには、カメラ情報、カメラ設定、写真の向き、GPS 座標など、140 種類の属性(そのうち約 100 種類は、Android 7.1 と今回の Support Library で新しく対応したもの)が含まれています。

カメラ アプリ: Exif 属性の書き込み

カメラ アプリでもっとも重要になるのはおそらく書き込みですが、属性を書き込めるのは、依然として JPEG 画像ファイルに限られています。通常、実際にカメラ撮影を行う際にこの機能を使う必要はなく、JPEG_ORIENTATIONJPEG_GPS_LOCATION、または Camera1 API の Camera.Parametersに相当するものを使って Camera2 API の CaptureRequest.Builder.set()を呼び出します。ただし、ExifInterfaceを使うと、あとからそのファイルを変更できます(たとえば、ユーザーのリクエストによる位置情報の削除など)。

Exif 属性の読み取り

しかし、これらの属性の読み取りは実用的で欠かせないものです。今回大きく改善されたのはこの部分です。

まず、JPEG および RAW イメージ(具体的には、DNG、CR2、NEF、NRW、ARW、RW2、ORF、PEF、SRW、RAF の各ファイル)の Exif データを読み取ることができます。これには、大きな内部的変更が伴いました。すべてのネイティブの依存性を排除し、実際にすべてが動作することを確認するために大規模なテストを行う必要があったためです。

他のアプリから content:// URI(ターゲット API 24 以上のアプリから送信されるものなど)経由でイメージを受信するアプリでは、直接 InputStreamから ExifInterfaceを使えるようになっています。これによって、受信した content:// URI から Exif 情報を簡単に直接抽出でき、一時ファイルを作成する必要がなくなります。
Uri uri; // the URI you've received from the other app
InputStream in;
try {
in = getContentResolver().openInputStream(uri);
ExifInterface exifInterface = new ExifInterface(in);
// Now you can extract any Exif tag you want
// Assuming the image is a JPEG or supported raw format
} catch (IOException e) {
// Handle any errors
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ignored) {}
}
}

: ExifInterfaceは、HttpURLConnectionから返されるようなリモートの InputStreamでは動作しません。content://または file:// URI に対してのみ使用することを強くお勧めします。

ほとんどの属性では、必要に応じて getAttributeInt()getAttributeDouble()getAttribute()(文字列の場合)などのメソッドを使うだけで情報を取得できます。

イメージを表示する際に、もっとも重要になる属性の 1 つがイメージの向きです。この属性は、TAG_ORIENTATIONという名前で格納されており、いずれかの ORIENTATION_定数を返します。この値に対して後処理を行うと、回転角に変換することができます。
int rotation = 0;
int orientation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotation = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotation = 270;
break;
}

特定の Exif タグから値を抽出するために、いくつかのヘルパー メソッドが用意されています。位置データについては、getLatLong()メソッドで緯度と経度の浮動小数点値を、getAltitude()メソッドでメートル単位の高度を取得できます。イメージによっては、小さなサムネイルが埋め込まれている場合もあります。サムネイルの有無は hasThumbnail()で確認でき、getThumbnail()を使うとサムネイルを byte[]形式で抽出できます。これは、BitmapFactory.decodeByteArray()に渡すのに最適です。

Exif の利用: すべては省略可能

Exif データを理解するうえで重要な点は、必須のタグはないということです。すべてのタグは省略可能で、意図的に Exif データを削除するサービスもあります。そのため、コード全体を通して、Exif データが存在しない場合に常に対応できるようにする必要があります。特定の属性データがない場合もあれば、Exif データをまったくサポートしていない画像形式(広く普及している PNG や WebP イメージもその一例)もあります。

プロジェクトに ExifInterface Support Library を追加するには、以下の依存性を設定します。
compile "com.android.support:exifinterface:25.1.0"

Exif 属性があれば、アプリでイメージが間違った向きで表示されなくなるのなら、ぜひ ExifInterface Support Library を使ってみてください(#BuildBetterApps もフォローしてください)。



Posted by Yuichi Araki - Developer Relations Team

Google の Internet of Things プラットフォーム アップデートのお知らせ: Android Things と Weave

$
0
0
[この記事は Wayne Piekarski、IoT 担当デベロッパー アドボケートによる Google Developers Blog の記事 "Announcing updates to Google’s Internet of Things platform: Android Things and Weave" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

次のブログから引用: Android デベロッパー ブログ

Internet of Things(IoT)は、まったく新しい分野のデバイスにコンピューティングをもたらします。本日(*原文公開当時)は、Google の IoT デベロッパー プラットフォームの 2 つの重要なアップデートについてお知らせします。このアップデートによって、ネットワークに接続されたスマートな製品を今まで以上に短時間で簡単に作れるようになります。

現在、Android Things の Developer Preview 版が公開されています。Android Things は、IoT 製品を作成する総合的な手法で、世界有数のサポート数を誇るオペレーティング システムである Android を活用しています。これによって、Android デベロッパーは、Android API や Google のサービスを利用してスマート デバイスを短時間で構築できるようになります。アップデートは Google から直接提供されるので、高いセキュリティを確保できます。Project Brillo に寄せられたフィードバックを取り入れているため、Android Studio、Android Software Development Kit(SDK)、Google Play サービス、Google Cloud Platform などのおなじみのツールも含まれています。数か月後には、Developer Preview のアップデートを提供し、定期的な OS パッチ、セキュリティの修正、そして皆さんのアップデートを安全にプッシュできるインフラを実現する予定です。それと同時に、ビルトインの Weave 接続なども提供されます。

現在、Android Things を搭載した実際の製品の構築を始めるにあたって、すぐに使えるハードウェア ソリューションも存在しています。たとえば、Intel Edison、NXP Pico、Raspberry Pi 3 などです。こういったカスタム デザインのソリューションを使うと、Google の同じ Board Support Package(BSP)を使用しつつ、大規模な本番環境で容易に稼働させることもできます。

また、Weave プラットフォームもアップデートされています。これによって、あらゆるタイプのデバイスがクラウドに接続し、Google Assistant のようなサービスと簡単に通信できるようになりました。Philips Hue や Samsung SmartThings などのデバイス メーカーはすでに Weave を使っており、Belkin WeMo、LiFX、Honeywell、Wink、TP-Link、First Alert などのメーカーも実装を進めています。Weave は、デベロッパーがクラウド サービスに投資することなく製品の開発に集中できるように、あらゆるクラウド インフラを提供しています。さらに、サポート対象のマイクロコントローラや管理コンソール用の Device SDK も含まれています。現在の Weave Device SDK は、電球、スマートプラグおよびスイッチ、サーモスタット向けのスキーマをサポートしています。今後数か月で、サポートするデバイスタイプの増加、カスタムのスキーマや特性、Android および iOS 向けのモバイルアプリ用の API の追加などを行う予定です。さらに、Weave と Nest Weave を統合し、あらゆるクラスのデバイスが安全で信頼性の高い方法で相互に接続できるように取り組んでいます。そのため、Google Weave と Nest Weave のどちらから始めても、エコシステムの将来に向けた道を歩みだすことができます。

これは、皆さんとともに IoT エコシステムを作り上げる道のりの第一歩にすぎません。参加するには、Google の IoT デベロッパー サイトを参照するか、Android ThingsWeaveGoogle Cloud Platformの各サイトに直接アクセスし、ドキュメントやコードサンプルをご覧ください。また、Google+ の Google IoT デベロッパー コミュニティに参加して最新のアップデートを入手し、他のデベロッパーとアイデアを共有したり語り合ったりすることもできます。




Posted by Yoshifumi Yamaguchi - Developer Relations Team

Android Wear 2.0 Developer Preview 4: 認証、アプリ内課金など

$
0
0
[この記事は Hoi Lam、デベロッパー アドボケートによる Android Developers Blog の記事 "Android Wear 2.0 Developer Preview 4: Authentication, In-App Billing, and more" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]



Android Wear 2.0の中核をなす機能は、ウォッチアプリをスタンドアロン アプリのように動作させ、ユーザーがメッセージに応答したり、フィットネスをトラッキングしたり、お気に入りのアプリを使えるようにする機能です。これは近くにスマートフォンがないときでも変わりません。Android Wear 2.0 の Developer Preview 4 には、今まで以上に強力なスタンドアロン アプリの構築に役立つ数々の新しい API が含まれています。

シームレス認証

Android スマートフォン、iPhone の両方のユーザーがシームレスな認証を行えるように、OAuth やワンクリック Google ログインのサポートが追加された API が新たに作成されました。Android Wear 向けの OAuth API を使うと、ユーザーが時計のボタンをタップしてスマートフォンの認証画面を開き、ウォッチアプリから直接サーバーサイドの API で認証できるようになります。Google ログインを使うと、この操作がさらに簡単になり、どのアカウントで認証するかを選択するだけで、ユーザーの認証が完了します。

アプリ内課金

有料アプリに加え、アプリ内課金のサポートが追加されています。これによって、Android Wear アプリやウォッチフェイスを収益化する方法がまた 1 つ増えることになります。ユーザーは、時計と 4 桁の Google アカウント PIN ですばやく簡単に購入時の認証を行えます。新しいゲームのレベルから新しいスタイルのウォッチ フェイスまで、ユーザーはデベロッパーの皆さんが作るものを購入できます。

デバイスをまたいだプロモーション

スタンドアロンで動作しないウォッチアプリもあります。また、時計とスマートフォンの両方のアプリがインストールされている場合に、よりよいユーザー エクスペリエンスを提供できることもあります。Google は皆さんのフィードバックを入念にチェックし、ペア設定された端末で Play Store を開いてユーザーが簡単にアプリをインストールできるように、2 つの新しい APIPlayStoreAvailabilityRemoteIntent)を追加しています。また、新しく追加された RemoteIntent API を使い、時計から操作してスマートフォンでカスタム URL を開くことができます。この操作には、追加のスマートフォン アプリやデータレイヤーは不要です。
// Check Play Store is available
int playStoreAvailabilityOnPhone =
PlayStoreAvailability.getPlayStoreAvailabilityOnPhone(getApplicationContext());

if (playStoreAvailabilityOnPhone == PlayStoreAvailability.PLAY_STORE_ON_PHONE_AVAILABLE) {
// To launch a web URL, setData to Uri.parse("https://g.co/wearpreview")
Intent intent =
new Intent(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.parse("market://details?id=com.google.android.wearable.app"));
// mResultReceiver is optional; it can be null.
RemoteIntent.startRemoteActivity(this, intent, mResultReceiver);
}

スワイプで閉じる動作の復活

Android Wear 1.0 のスワイプで閉じる操作は、直感的で時間の節約になるという多くのフィードバックをいただきました。そこで、今回の Developer Preview リリースでは、以前の動作を復活させています。このリリースでスワイプで閉じる操作をサポートするために、次のプラットフォームと API の変更を行っています。
  • アクティビティでは、スワイプで閉じる操作が自動的にサポートされます。左から右にアクティビティをスワイプすると、そのアクティビティが閉じ、アプリはバックスタックをさかのぼります。
  • 新しいフラグメントとビューがサポートされます。新しく追加された SwipeDismissFrameLayoutでフラグメントに含まれるビューや汎用的なビューをラップすると、ユーザーがスワイプしたときにアクティビティを終了するのではなく、バックスタックをさかのぼるなどのカスタム アクションを実装できます。
  • ハードウェア ボタンは「電源」にマッピングされます。以前は「戻る」にマッピングされていましたが、この変更によって、アプリがハードウェア ボタンをインターセプトできなくなりました。

詳しい情報は、Android Wear Preview サイトの動作の変更点セクションでご覧ください。

Android Wear 1.0 アプリとの互換性

Android Wear 2.0 対応の時計に、以前の埋め込みアプリのメカニズムを使ってパッケージ化された Android Wear アプリを配信できるようになっています。埋め込み Android Wear アプリを含むスマートフォン アプリをインストールしようとすると、埋め込みアプリをインストールするように通知されます。その際に埋め込みアプリをインストールしなかったユーザーは、Play Store の Android Wear ページにある「Apps you've used」(使用したことのあるアプリ)という特別なセクションから埋め込みアプリを探すことができます。

既存のメカニズムもサポートされますが、アプリをマルチ APK 配信メカニズムに移行すれば、多大なメリットを受けることができます。マルチ APK を使うと、アプリを Play Store の Android Wear ページで検索できます。また、ホームページで宣伝できたり、ウェブから時計にリモートでインストールできるなどのメリットもあります。そのため、マルチ APK に移行することを強くお勧めいたします。

Developer Preview 4 のその他の詳細

  • アクションとナビゲーションドロワー: ピーク動作が可能になっているため、ユーザーはリストの一番上や下までスクロールしなくても操作を行うことができます。アクション ドロワー用の新しい API である setShouldPeekOnScrollDownなどを利用すると、ドロワーのピーク動作をさらに細かく制御できます。
  • WearableRecyclerView: WearableRecyclerView で曲線レイアウトが選択できるようになったため、RecyclerView を簡単に置き換えることができるようになりました。
  • コンプリケーション用の焼き付き防止アイコン: コンプリケーション データ プロバイダが、焼き付きやすい画面向けのアイコンを提供できるようになりました。通常、このような焼き付き防止アイコンは、インタラクティブ モードのアイコンのアウトラインです。画面の焼き付きを防ぐため、常に画面表示モードでウォッチ フェイスにアイコンをまったく表示しないように設定されている場合もあります。

フィードバックを歓迎します!

Android Wear 2.0 にすばらしいフィードバックの数々をお寄せいただき、ありがとうございます。g.co/wearpreviewで最新のビルドやドキュメントをご覧いただき、バグの報告Android Wear Developersコミュニティへの投稿を通してフィードバックをお送りください。また、Android Wear Developer Preview 5 にもご期待ください!


Posted by Yoshifumi Yamaguchi - Developer Relations Team

ゲーム認証に Google Sign-In API を採用

$
0
0
[この記事は Clayton Wilkinson、デベロッパー プラットフォーム エンジニアによる Android Developers Blog の記事 Games authentication adopting Google Sign-In APIを元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

2017 年初め、Play ゲームサービスでいくつかの変更が実施されます。

Google API クライアントの作成方法の変更


11 月に、Google Sign-In API のアップデートについてお知らせしました。現在、Play ゲームサービスでは、認証に Google Sign-In API を使用するよう変更するアップデート作業が行われています。この変更によって、次のようなメリットが生まれます。
  • ゲームとログインの両方を同じクライアント接続で実行できる
  • 1 つの API でバックエンド サーバーに送る認証コードを取得できる

この変更により、Google ログインと Games API のログインが統合され、Google API クライアントの作成方法も次のようにアップデートされます。

// Defaults to Games Lite scope, no server component
GoogleSignInOptions gso = new
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN).build();

// OR for apps with a server component
GoogleSignInOptions gso = new
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestServerAuthCode(SERVER_CLIENT_ID)
.build();

// OR for developers who need real user Identity
GoogleSignInOptions gso = new
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestEmail()
.build();

// Build the api client.
mApiClient = new GoogleApiClient.Builder(this)
.addApi(Games.API)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addConnectionCallbacks(this)
.build();
}

@Override
public void onConnected(Bundle connectionHint) {
if (mApiClient.hasConnectedApi(Games.API)) {
Auth.GoogleSignInApi.silentSignIn(mApiClient).setResultCallback(
new ResultCallback() {
@Override
public void onResult(GoogleSignInResult googleSignInResult) {
// In this case, we are sure the result is a success.
GoogleSignInAccount acct =
googleSignInResult.getGoogleSignInAccount());

// For Games with a server, send the auth code to your server.
String serverAuthCode = signInAccount.getServerAuthCode();

// Use the API client as normal.
Player player = Games.API.getCurrentPlayer(mApiClient);
}
}
);
} else {
onSignedOut();
}
}

iOS からのアカウント作成のサポート終了

  • 現在、新しいプレイヤーが iOS から Play ゲーム アカウントを作成する操作はサポートされていません。また、iOS からは Google+ 統合も削除されました。そのため、「ソーシャル」API は成功を示す結果コードを返しますが、返されるリストは空になります。これには、リーダーボードやマルチプレーヤー型ゲームの招待状で使う「標準」UI も含まれます。

Google+ 統合の終了

  • 昨年お知らせしたように、今回の移行でゲームと Google+ が切り離されることになります。そのため、サークルを通じてプレーヤーを接続するパブリック API は動作しなくなります。ただし、マルチプレーヤー型ゲームの招待状やソーシャル リーダーボードの標準 UI は引き続き動作します。2017 年 2 月には Google+ のデータにアクセスできなくなり、標準 UI にソーシャル グラフの結果が表示されなくなります。これによって、Android のマルチプレーヤー型ゲーム、ソーシャル リーダーボード、ギフト API が影響を受けます。以上の API は、成功を示す値を返しますが、プレイヤーのリストは空になります。

Google+ 統合の削除によってサポート終了となる API のリスト(C++ の対応機能も同様)
  1. Games.Players.getPlayerSearchIntent()
  2. Games.Players.loadConnectedPlayers()
  3. Games.Players.loadInvitablePlayers()
  4. LeaderboardVariant.COLLECTION_SOCIAL
  5. Invitations.loadInvitations()
  6. RealtimeMultiplayer.getSelectOpponentsIntent()
  7. TurnBasedMultiplayer.getSelectOpponentsIntent()
  8. Requests パッケージのすべてのメソッド

これが大幅な変更であることは認識していますが、Play ゲームサービスを進化させることで他の Google のモバイル プラットフォームと緊密に連携できるようになり、Android ゲーム デベロッパーの皆さんにとって、開発の利便性も向上します。



Posted by Takeshi Hagikura - Developer Relations Team

Android アプリで複数の Firebase プロジェクトを使う

$
0
0
この記事は Ian Barber による The Firebase Blog の記事 "The Firebase Blog: Working with multiple Firebase projects in an Android app " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

Parul Soi

Ian Barber
Developer Programs Engineer

Firebase は、アプリで使用できるさまざまな機能を提供します。それらの機能は、Firebase コンソールで作成したプロジェクトを通じて使用できます。通常は、アプリを1 つの Firebase プロジェクトにつなげれば十分なはずですが、場合によっては、1 つのアプリから複数のプロジェクトのデータにアクセスしたいこともあるでしょう。たとえば、2 つのデータベースのデータにアクセスしなければならなかったり、それぞれのデータベースにアクセスするためにユーザーを認証できるようにしたい場合が考えられます。この投稿では、その方法を説明します。

最初に、少しばかり用語を整理しておきます。

以前の Firebase.com プロジェクト 以前のコンソールで作成され、新しいコンソールにアップグレードしていない Firebase Database に関連づけられているプロジェクト
Google API プロジェクト Google API にアクセスするためのプロジェクト(通常は、https://console.developers.google.comまたは https://console.cloud.google.comから)
Firebase プロジェクト 新しい Firebase コンソールで作成されたプロジェクト。すべての Firebase プロジェクトには、ベースとなる Google API プロジェクトが存在します。
アプリ 特定のプラットフォーム用のクライアント。各プロジェクトには、複数のアプリを関連づけることができます。


アップグレードした以前の Firebase.com プロジェクトと既存の Google API プロジェクトを共存させる

別の Google API プロジェクトのサービスを使いつつ、以前の Firebase.com データベースを新しい Firebase プロジェクトにアップグレードしたい場合に発生する 1 つのシナリオがあります。アップグレードした以前のプロジェクトは、新しい Firebase プロジェクトになります。しかし、そのプロジェクトは既存ユーザーに Google Sign-In の認証を提供する Google API プロジェクトと併せて使う必要があります。

ここで問題になるのは、Android アプリで Google Sign-In を動作させるには、そのアプリの SHA-1(APK の署名に使用するキーのフィンガープリント)とパッケージ名(com.foo.bar など)を登録する必要があることです。Google Sign-In は、このペアによって特定のアプリがどの Google API プロジェクトを使っているか判断します。ある SHA1 とパッケージ名のペアは Google(と Firebase プロジェクト)内でグローバルに一意であるため、アップグレードした以前の Firebase プロジェクトに同じ SHA-1 とパッケージ名のペアを追加しようとすると、OAuth2 クライアントがすでに(Google API プロジェクト内に)存在するという次のエラーが発生します。


警告: このエラーが表示されても、本番環境のアプリの既存クライアント ID は削除しないでください。削除してしまうと、既存ユーザーがアプリを利用できなくなります。正しい対応は、Firebase コンソールでアップグレードしたプロジェクトの中に同じパッケージ名の新しいアプリを作成することであり、その際に SHA1 を 空のまま で登録します。
あとは、通常どおりに Firebase Auth を使った Google Sign-In を実装します。ある時点で、次のようにして GoogleSignOptions オブジェクトを設定することになります。

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();


ここで、 default_web_client_id文字列は、ID トークンの audienceフィールドを設定するために使われています。この値は google-services.json ファイルから取得されており、Google プロジェクトではなく Firebase プロジェクトに紐付きます。この値を Google API プロジェクトのクライアント ID と置き換える必要があります。任意のウェブ クライアント ID を使うことも、次のようにして新しい ID を作ることもできます。


次に、Firebase プロジェクトに戻り、先ほど GoogleSignInOptionsに設定したクライアント ID をホワイトリストに登録します。この操作は、Firebase コンソールの Auth > Sign In Providers > Googleセクションから行います。


忘れずに google-services.jsonファイルをダウンロードし直し、Android アプリに追加してください。この時点で、Firebase プロジェクトは Google API プロジェクトで生成された Google ID トークンでも利用できるようになります。そのため、Android アプリは Google API プロジェクトを使って問題なく Google Sign-In でログインできます。そして、通常のアプローチに従い、Google API プロジェクトに紐付けた Google ID トークンを使って Firebase プロジェクトに対する認証を行います。これによって、Google API プロジェクトに関連づけられている Google API に対する認証情報付きの API 呼び出しや、Firebase プロジェクトを使った Firebase API に対する認証情報付きの API 呼び出しができるようになります。

2 つの Firebase プロジェクトのデータベースにアクセスする

先ほどの例は、1 つの Firebase プロジェクトから別の Google API プロジェクトにアクセスする必要がある場合でした。この方法は、API が分かれているためうまく動作します。しかし、同じ Firebase API を経由し、複数のデータベース インスタンスなど、別のプロジェクトにアクセスしなければならないこともあるでしょう。

Firebase を使う Android アプリには、中核となる FirebaseAppオブジェクトが存在し、すべての Firebase API で使う設定を管理しています。このオブジェクトは、アプリが起動する際に、コンテンツ プロバイダによって自動的に初期化されます。通常、その後はこのオブジェクトを使用することはありません。しかし、1 つのアプリから複数のプロジェクトにアクセスする場合は、各プロジェクトを参照する別々の FirebaseApp が必要になります。Firebase SDK が自動で作成するデフォルトのインスタンス以外は、自分で初期化を行う必要があります。
たとえば、次のようにしてデフォルトの Firebase Database インスタンスに接続する場合、デフォルトの FirebaseApp が暗黙的に使用されます。

FirebaseDatabase database = FirebaseDatabase.getInstance();


別のプロジェクトにある別の Firebase Realtime Database に接続する場合は、最初に対象となる Firebase プロジェクトの FirebaseApp インスタンスを初期化し、識別子を指定します。次の例では、識別子として "secondary"を使用しています。

FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId("1:530266078999:android:481c4ecf3253701e") // Required for Analytics.
.setApiKey("AIzaSyBRxOyIj5dJkKgAVPXRLYFkdZwh2Xxq51k") // Required for Auth.
.setDatabaseUrl("https://project-1765055333176374514.firebaseio.com/") // Required for RTDB.
.build();
FirebaseApp.initializeApp(this /* Context */, options, "secondary");


これで、同じクライアント API を使ってデータベースにアクセスできるようになります。ただし、この場合、対象の FirebaseAppFirebaseDatabase.getInstance()に渡し、どのプロジェクトにアクセスするかを明示します。

// Retrieve my other app.
FirebaseApp app = FirebaseApp.getInstance("secondary");
// Get the database for the other app.
FirebaseDatabase secondaryDatabase = FirebaseDatabase.getInstance(app);


2 つの Firebase Database に対して認証を行う

以上で説明した 2 つのテクニックを組み合わせると、結合する外部 ID さえあれば、複数の Firebase プロジェクト間で認証データを共有できます。

たとえば、Google Sign-In を使ってログインできるアプリがあり、デフォルトとセカンダリのプロジェクトの両方で認証が必要となるデータベース ルールが設定されている場合、同じ Google 資格情報を使って両方のシステムにログインできます。

まず、アプリでデフォルトのプロジェクトの Google Sign-In を通常どおりにセットアップします。次に、デフォルトのプロジェクトからベースとなるクライアント ID を取得します。クライアント ID は、アプリのクライアント(ウェブ、Android、iOS)の単なる識別子で、通常はクライアントの中に含まれています。プロジェクトには複数のクライアント ID を持たせることもできますが、ホワイトリストに登録する必要があるのは、GoogleSignInOptions のビルダーの requestIdToken を呼び出す際に指定するものです。

.requestIdToken(getString(R.string.default_web_client_id))


通常、これは google-services.json で type が「3」になっている最初の client_id です。筆者の環境では、次のようになっています。


{
"client_id": "56865680640-e8mr503bun5eaevqctn4u807q4hpi44s.apps.googleusercontent.com",
"client_type": 3
},


これが取得できたら、 Auth > Sign In Providersセクションにある Googleパネル(セカンダリのプロジェクト)からクライアント ID をホワイトリストに登録します。



あとは、Google Sign-In のログイン結果から同じ GoogleSignInAccountオブジェクトを取得し、デフォルトとセカンダリの両方のアプリを認証します。

AuthCredential credential = GoogleAuthProvider.getCredential(account.getIdToken(), null);
FirebaseAuth.getInstance().signInWithCredential(credential);

FirebaseApp app = FirebaseApp.getInstance("secondary");
FirebaseAuth.getInstance(app).signInWithCredential(credential);
ユーザーは 1 回ログインするだけで、両方のプロジェクトに対して認証を行うことができます。

プロジェクト間でユーザー ID を共有する

ここで 1 つ問題になるのは、各プロジェクトの Firebase ユーザー ID が異なることです。たとえば、同じ Google 資格情報を使っても、次のような 2 つのユーザー ID となります。

Default Auth UID: 0960868722032022577213DA4EA8B7A1683D92B405DD
Secondary Auth UID: 7h6XOeSxmkNsSseFJ1jU31WZHDP2


アプリにアカウントのリンク機能がない場合、データベース構造やセキュリティ ルールなどで Google(または Facebook、Twitter など)のユーザー ID を使うことができます。しかし、各プロジェクトで同じユーザー ID が必要になる場合や、メール / パスワード認証や匿名認証を使っている場合、やや複雑になります。

幸い、この問題はカスタム認証機能と少しのサーバーサイドのコードを使って解決できます。カスタム認証トークンによってユーザー ID を指定できるため、この仕組みが可能になります。

今回は、セカンダリ プロジェクトをホワイトリストに登録する必要はありませんが、デフォルトとセカンダリの両方のプロジェクトのサービス アカウントをダウンロードします。Android クライアントでは、最初にログインして FirebaseAuth クライアントから Firebase ID トークンを取得します。

注:ここでは、任意のログイン プロバイダを利用できます。カスタム トークンはプロジェクト間でユーザー ID をリンクするためだけに使用します。

firebaseAuth.getCurrentUser().getToken(false /* forceRefresh */)
.addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
String token = task.getResult().getToken(); // Send this to the server.
}
});
このトークンはサーバーに送信し、サーバーで Firebase カスタム トークンを作成します。Android で行ったのと同じように、サーバーでも各アプリを初期化する必要があります。ただし、サーバーサイドでの処理であるため、サービス アカウントを使用します(今回は、Java サーバー SDK を利用しますが、NodeJS も同じように利用できます)。

FirebaseOptions options = new FirebaseOptions.Builder()
.setServiceAccount(new FileInputStream("default-service-account.json"))
.build();
FirebaseApp.initializeApp(options);


FirebaseOptions secondaryOptions = new FirebaseOptions.Builder()
.setServiceAccount(new FileInputStream("secondary-service-account.json"))
.build();
FirebaseApp.initializeApp(secondaryOptions, "secondary");


デフォルトの FirebaseApp はクライアントから送られてくるトークンを検証するために、セカンダリの FirebaseApp は適切なユーザー ID のセットを持つカスタム認証トークンを作成するために使用します。
// Verify the ID token using the default app.
FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
System.out.println("User " + uid + " verified");
FirebaseApp app = FirebaseApp.getInstance("secondary");
String customToken = FirebaseAuth.getInstance(app).createCustomToken(uid);
// TODO: Send the token back to the client!
}
});
Android アプリでは、サーバーから受け取ったカスタム トークンを使ってセカンダリ プロジェクトに対する認証を行います。

FirebaseApp app = FirebaseApp.getInstance("secondary");
FirebaseAuth.getInstance(app).signInWithCustomToken(token);


これで、両方のプロジェクトの Firebase のユーザー ID が一致します。
Default Auth UID: 0960868722032022577213DA4EA8B7A1683D92B405DD
Secondary Auth UID: 0960868722032022577213DA4EA8B7A1683D92B405DD


iOS とウェブでも同様に

今回の説明によって、1 つのアプリから複数の Firebase プロジェクトを使うという選択肢が増えたと感じていただけるとうれしいです。iOS やウェブで同じ仕組みが使えるかどうか疑問に思うかもしれません。もちろん、使うことができます。Android の FirebaseApp に該当するオブジェクトを使ってセカンダリ プロジェクトへの参照を作成すればよいだけです。
JavaScript では、firebase.appを使います。

var config = {
apiKey: "",
authDomain: ".firebaseapp.com",
databaseURL: "https://.firebaseio.com",
storageBucket: ".appspot.com",
messagingSenderId: "",
};

var secondary = firebase.initializeApp(otherAppConfig, "secondary");
var secondaryDatabase = secondary.database();


iOS では、FIRAppを使います。
// Alt: load from plist using |FIROptions(contentsOfFile:)|
let options = FIROptions(googleAppID: googleAppID, bundleID: bundleID, GCMSenderID: GCMSenderID, APIKey: nil, clientID: nil, trackingID: nil, androidClientID: nil, databaseURL: databaseURL, storageBucket: nil, deepLinkURLScheme: nil)

FIRApp.configure(withName: "secondary", options: fileopts)
guard let secondary = FIRApp.init(named: "secondary")
else { assert(false, "Could not retrieve secondary app") }

let secondaryDatabase = FIRDatabase.database(app: secondary);


詳しい情報やリンクは、Firebase ドキュメントの新しい Firebase プロジェクトの設定について記述されたページをご覧ください。

Posted by Khanh LeViet - Developer Relations Team

IoT 対応のジオロケーションと Firebase

$
0
0
[この記事は、Ken Nevarez, Industry Solutions Lead at Google による Geo Developers Blog の記事 "Geolocation and Firebase for the Internet of Things" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

GPS は位置情報サービスの要ですが、GPS ハードウェアのコストや消費電力を抑えたいケースや、市街地や建物内など GPS の精度に欠ける場所にあるデバイスを探すといったケースも存在します。

近年、アセットの追跡や盗難防止、使用状況の最適化、アセットの保守点検などを目的として、GPS の代わりに Google Maps Geolocation APIを用いた IoT(モノのインターネット)アプリケーションが増えています。そこで、Industry Solutions プロジェクトの一環として、周辺の Wi-Fi ネットワークと Google Maps Geolocation API を使って自身の位置を特定できる IoT デバイスのプロトタイプ作成に取り組みました。この記事では、実装した機能の一部を紹介すると共に、皆さんがご自分でもプロトタイプを作成できるよう、その方法を簡単に説明します。

作成した IoT デバイスは、周辺の Wi-Fi を探してその結果(Wi-Fi ホットスポットとその信号強度)を Firebase Realtime Databaseへ書き込みます。次に、バックエンド サービスがこのデータを読み出し、Google Maps Geolocation API を使ってそのデータから実際の位置を導き出します。導き出された位置は地図上にプロットすることができます。

デバイスのセットアップとローカルでの書き込み

これを実現するために、Intel EdisonをLinux ベースのコンピューティング プラットフォームとして使い、これに Sparkfun の Edison Blocksを加えました。なお、デバイスの作成には Intel EdisonBase BlockBattery BlockHardwareパックがそれぞれ 1 つずつ必要です。



Edison の開発は Intel XDK IDEを使えば簡単です。JavaScript でシンプルな Node.js アプリケーションを作っていきます。今回、3 つのライブラリ(データベース接続には Firebase、Wi-Fiネットワークの取得には wireless-tools/iwlist、デバイスのMAC 取得には macaddress)を使用しました。実装手順はそれぞれのリンク先のページを参照してください。

ステップ 1: デバイスの MAC アドレスを取得して Firebase に接続する
function initialize() {
macaddress.one('wlan0', function (err, mac) {
mac_address = mac;
if (mac === null) {
console.log('exiting due to null mac Address');
process.exit(1);
}
firebase.initializeApp({
serviceAccount: '/node_app_slot/<service-account-key>.json',
databaseURL: 'https://<project-id>.firebaseio.com/'
});
var db = firebase.database();
ref_samples = db.ref('/samples');
locationSample();
});
}


上記のコードに含まれている 2 つのプレースホルダーは次のとおりです。

  1. service-account-key は Firebase コンソールで作成するプライベート キーです。コンソールの左上部にある歯車アイコンから「settings」を選択して、Generate New Private Key をクリックします。このキーを Edison の /node_app_slot/ ディレクトリに入れます。詳しくは、Firebase のドキュメントをご覧ください。
  2. データベース URLの中の project-id は、Google プロジェクトを Firebase と連携させた後、Firebase コンソールのデータベース ページに表示されます。


ステップ 2: 10秒毎に Wi-Fiネットワークをスキャンしてローカルに書き込む
function locationSample() {
var t = new Date();
iwlist.scan('wlan0', function(err, networks) {
if(err === null) {
ref_samples.push({
mac: mac_address,
t_usec: t.getTime(),
t_locale_string: t.toLocaleString(),
networks: networks,
});
} else {
console.log(err);
}
});
setTimeout(locationSample, 10000);
}


クラウドへの書き込み

上記の locationSample() は、検出可能なWi-Fi ネットワークを Firebase のデータベースに書き込む関数で、データベースはネットワーク接続時にクラウドと同期します。

補足説明: Firebase へのアクセス権と認証の設定では、デバイスを「サーバー」として設定しました。この設定方法については Firebase ウェブサイトをご覧ください。今回、認証情報の保存に関しデバイスのセキュリティは十分であると仮定しましたが、皆さんが実装する際にこの点が該当しない場合は、クライアント JavaScript SDK の設定手順に従ってください。

データベースではワークロード管理に 3 つのキュー(Wi-Fi サンプル キュー、ジオロケーション結果キュー、視覚化データ キュー)を使用します。ワークフローは次のとおりです。デバイスからのサンプルがサンプル キューに入り、これを使ってジオロケーションが生成され、生成されたジオロケーションはジオロケーション キューに入れられます。ジオロケーションは取得されて表示用にフォーマット化され、デバイスによって整理された後、出力が視覚化バケットに保管され、フロントエンドのウェブサイトがこれを使用するという流れです。

以下に、Firebase Database コンソール上に表示されるサンプル、ジオロケーション、デバイスによって書き込まれた視覚化データの例を示します。

データを Google App Engine で処理する

サンプルデータの処理の実行には、長期実行中の Google App Engine Backend Module と Java Client for Google Maps Servicesのカスタム版を使用しました。

補足説明: Firebase と App Engine を併用する場合は、必ず手動スケーリングを使用してください。Firebase はバックグラウンド スレッドを使って変更をリッスンしていて、App Engine は手動でスケーリングされたバックエンド インスタンスに対する長期のバックグラウンド スレッドしか許可しません。

Java Client for Google Maps Servicesは Google Maps API を利用する際に必要な大量の通信コードを扱い、エラー処理について公開されているベスト プラクティスおよびレート制限に従ったリトライ方針に従います。次に示す GeolocateWifiSample() 関数は、イベント リスナーとしてFirebase に登録されています。この関数はデバイスから報告される各ネットワークをループし、それをジオロケーション リクエストに組み込みます。

private void GeolocateWifiSample(DataSnapshot sample,  Firebase db_geolocations, Firebase db_errors) {
// initalize the context and request
GeoApiContext context = new GeoApiContext(new GaeRequestHandler()).setApiKey("");
GeolocationApiRequest request = GeolocationApi.newRequest(context)
.ConsiderIp(false);
// for every network that was reported in this sample...
for (DataSnapshot wap : sample.child("networks").getChildren()) {
// extract the network data from the database so it’s easier to work with
String wapMac = wap.child("address").getValue(String.class);
int wapSignalToNoise = wap.child("quality").getValue(int.class);
int wapStrength = wap.child("signal").getValue(int.class);
// include this network in our request
request.AddWifiAccessPoint(new WifiAccessPoint.WifiAccessPointBuilder()
.MacAddress(wapMac)
.SignalStrength(wapStrength)
.SignalToNoiseRatio(wapSignalToNoise)
.createWifiAccessPoint());
}
...
try {
// call the api
GeolocationResult result = request.CreatePayload().await();
...
// write results to the database and remove the original sample
} catch (final NotFoundException e) {
...
} catch (final Throwable e) {
...
}
}


GeolocateWifiSample() 関数をイベント ハンドラーとして登録します。ジオロケーションの結果を処理して視覚化データを生成するそれ以外のリスナーも、同じようなパターンで作成します。
ChildEventListener samplesListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
// geolocate and write to new location
GeolocateWifiSample(dataSnapshot, db_geolocations, db_errors);
}
...
};
db_samples.addChildEventListener(samplesListener);


データの視覚化

デバイスの位置の視覚化には、Google App Engine を使います。保存されたデータを Firebase から渡して、Google Maps JavaScript API を使って結果表示用のシンプルなウェブページを作成しました。index.html ページの中身は空の <div> とID “map” です。この <div> を初期化して Google Map オブジェクトを入れました。また、イベントハンドラーの “child_added” と “child_removed” を追加して、時間の経過に伴ってデータが変化したときにマップを更新するようにしています。

function initMap() {
// attach listeners
firebase.database().ref('/visualization').on('child_added', function(data) {
...
data.ref.on('child_added', function(vizData) {
circles[vizData.key]= new CircleRoyale(map,
vizData.val().lat,
vizData.val().lng,
vizData.val().accuracy,
color);
set_latest_position(data.key, vizData.val().lat, vizData.val().lng);
});
data.ref.on('child_removed', function(data) {
circles[data.key].removeFromMap();
});
});
// create the map
map = new google.maps.Map(document.getElementById('map'), {
center: get_next_device(),
zoom: 20,
scaleControl: true,
});
...
}


API は位置だけでなく精度表示も返すため、精度のコンポーネントを示すカスタム マーカー(半径内の範囲が脈動する)を作成しました。

2 個のデバイス(赤と青)と判明した位置の直近 5 か所

次に進むには

この記事では、インターネットに接続されたデバイス(ロボットからウェアラブル端末まで)を追跡するために、Google Maps Geolocation API を使った IoT デバイスの構築方法を紹介しました。App Engine の処理モジュールを拡張し、他の Google Maps APIを使ってルート案内標高プレイスタイムゾーン情報などの地図データを提供することもできます。皆さん、ぜひ作成してみてください。

さらに、Firebase の代わりに Google Cloud Platform を使って同様のソリューションを実現することも可能です。手順はこちらの記事をご覧ください。




Posted by 丸山 智康 (Tomoyasu Maruyama) - Google Maps Solution Architect, Google Maps

Firebase を使って NativeScript + Angular 2 モバイルアプリを構築する

$
0
0
この記事はゲスト ブロガー Jen Looper による The Firebase Blog の記事 "The Firebase Blog: Building a NativeScript + Angular 2 Mobile App using Firebase" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。




Jen Looper
Developer Advocate at ProgressSW

NativeScript、Firebase、Angular 2 という強力な組み合わせを活用すれば、アプリの構築を一気に加速させることができます。クリスマス休暇の期間中は、アプリの開発をスピードアップさせて、プレゼントを贈りたいという家族のニーズに応えなければならないため、特にその点が重要になります。ちょうどよいことに、Angular 2 ベースの NativeScript アプリで Firebase を使う方法のデモを皆さんにプレゼントすることができます(以下をご覧ください 🎁)。これは、Eddy Verbruggen 氏による有名な NativeScript-Firebase プラグインのいくつかのコンポーネントを使ったものです。


このチュートリアルでは、よく使われている次の 4 つの Firebase 機能を NativeScript アプリで使用する方法を説明します。4 つの機能には、ログインとユーザー登録の機能を提供する Authentication、リアルタイムにアップデートされるデータ ストレージの Realtime Database、リモートでアプリを変更できる Remote Config、写真を保存する Storageがあります。説明するにあたって、以前に Ionic で書いた Giftler アプリを書き直すことにしました。

実際のプロジェクトで作業に着手する前に、ドキュメントに目を通し、以下の前提事項について確認することをお勧めします。

  • ローカルマシンに NativeScriptがインストールされており、CLI が問題なく動作していることを確認します。
  • お好みの IDE で、NativeScript と Angular の開発環境を設定します。TypeScript が必要になるので、トランスパイルプロセスが動作することを確認しておきます。Visual StudioVisual Studio CodeJetbrains 対応の IDEなどで利用できる優れた NativeScript プラグインがありますが、中でも Visual Studio Code には、開発を加速させる便利なスニペットがあります。
  • Firebase アカウントにログインし、コンソールを開きます。
  • Firebase コンソールで新しいプロジェクトを作成します。ここでは、「Giftler」という名前にしました。さらに、Firebase コンソールで iOS と Android のアプリを作成します。その際に、GoogleServices-Info.plist ファイルと google-services.json ファイルをダウンロードします。後ほど必要になるので、ファイルを配置した場所は覚えておいてください。


依存モジュールのインストール

Giftler は、認証が必要な NativeScript アプリのサンプルとして作成しました。このアプリでは、ユーザーがクリスマス休暇に受け取りたいギフトを、写真や説明とともに一覧表示できます。現時点で、このアプリには iOS 版と Android 版があり、以下の機能があります。

  • ログイン、ログアウト、ユーザー登録、および「パスワードを忘れた」場合の処理の実行
  • ユーザーによるリストへのギフト項目の登録
  • ユーザーによるリストからのギフト項目の削除
  • ユーザーによるリストの各ギフト項目の編集(説明や写真の追加)
  • バックエンドですぐに変更できる Firebase の Remote Config サービスによるメッセージング

それでは、Giftler のソースコードをフォークしましょう。これは、問題なく動作している完全版のアプリです。アプリをクローンできたら、アプリを作成した際にダウンロードした、現在の Firebase 関連のアプリのファイルを置き換えます。

  • Firebase からダウンロードした google.services.json ファイルを /app/App_Resources/Android folderに配置します。
  • 同様に、Firebase からダウンロードした GoogleService-Info.plist ファイルを /app/App_Resources/iOS folderに配置します。


これらのファイルは、アプリで Firebase を初期化し、関連する外部サービスに接続するために必要です。

次に、アプリのルートにある package.jsonを確認します。このファイルには、アプリで使用するプラグインが含まれています。ここでは、NativeScript に関連するプラグインに注目してください。

"nativescript-angular":"1.2.0",
"nativescript-camera": "^0.0.8",
"nativescript-iqkeyboardmanager": "^1.0.1",
"nativescript-plugin-firebase": "^3.8.4",
"nativescript-theme-core": "^1.0.2",


NativeScript-Angular プラグインは、Angular と NativeScript を統合するプラグインです。Camera プラグインを使うと、少しカメラを管理しやすくなります。IQKeyboardManager は iOS 専用のプラグインで、厄介な iOS のキーボードを管理してくれます。Theme プラグインは、スキンを完全に自作しなくてもデフォルトのスタイルをアプリに追加できるすばらしいプラグインです。最後に、このアプリでもっとも重要なのが Firebase プラグインです。

以上の依存モジュールを配置して、プラグインをインストールする準備ができたら、iOS と Android のそれぞれのコードが格納された platformsフォルダを作成し、Firebase プラグインやその他の npm ベースのプラグインを初期化して、アプリを構築できるようにします。NativeScript CLI を使ってクローンしたアプリのルートに移動し、tns run iosまたは tns run androidを実行します。これによってプラグインをビルドするルーチンが開始されます。中でも、Firebase プラグインのさまざまなパーツのインストールが始まることが確認できるはずです。インストール スクリプトが実行されると、さまざまな Firebase サービスを統合するためのコンポーネントをインストールするかどうかの確認が表示されます。ここでは、Messaging とソーシャル認証を除くすべてを選択します。ここでの大きな特徴は、firebase.nativescript.json ファイルがアプリのルートにインストールされることです。そのため、今後プラグインの新しいパーツをインストールしたい場合、このファイルを編集するだけでプラグインを再インストールできます。


ここで、tns livesync ios --watchまたは tns livesync android --watchを実行し、エミュレータでアプリが起動して変更が監視されることを確認すると、アプリが実行されて新しくログインする準備ができていることがわかります。ただし、ログインを行う前に、Firebase コンソールの [Authentication] タブからメール / パスワードによるログインを有効にして、Firebase がこのタイプのログインを処理できるようにする必要があります。


この裏で何が起こっているかを確認するために、少しばかり内部の仕組みを見てみましょう。Firebase にログインするには、インストールした Firebase サービスを初期化しておく必要があります。app/main.tsには、いくつか興味深い点があります。

// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { platformNativeScriptDynamic } from "nativescript-angular/platform";

import { AppModule } from "./app.module";
import { BackendService } from "./services/backend.service";


import firebase = require("nativescript-plugin-firebase");


firebase.init({
//persist should be set to false as otherwise numbers aren't returned during
livesync
persist: false,
storageBucket: 'gs://giftler-f48c4.appspot.com',
onAuthStateChanged: (data: any) => {
console.log(JSON.stringify(data))
if (data.loggedIn) {
BackendService.token = data.user.uid;
}
else {
BackendService.token = "";
}
}
}).then(
function (instance) {
console.log("firebase.init done");
},
function (error) {
console.log("firebase.init error: " + error);
}
);
platformNativeScriptDynamic().bootstrapModule(AppModule);


最初に、プラグインから firebase をインポートし、.init() を呼び出します。次に storageBucket プロパティを編集し、Firebase コンソールの [Storage] タブに表示されている値を貼り付けます。

これで、お使いの Firebase アカウントに合わせてアプリがカスタマイズされ、アプリで新しいユーザーの登録とログインが可能になるはずです。必要に応じて、app/login/login.component.tsファイルの user.email と password 変数を編集して、デフォルトのログイン認証情報を user@nativescript.orgからご自身のログインとパスワードに変更することもできます。

iOS と Android のログイン画面
注: iOS では、Xcode シミュレータを使うとすぐにアプリをエミュレートできます。ただし Android では、アプリをエミュレータにインストールするために、Google Services の有効化など、追加でいくつかの手順が必要になる場合があります。

コードの構造と認証

Angular 2 のデザイン パターンでは、コードをモジュール化する必要があります。そのため、以下のコード構造に従うものとします。

—login
  1. login.component.ts
  2. login.html
  3. login.module.ts
  4. login.routes.ts
—list …

—list-detail …

—models

  1. gift.model.ts
  2. user.model.ts
  3. index.ts
—services
  1. backend.service.ts
  2. firebase.service.ts
  3. utils.service.ts
  4. index.ts
app.component.ts

app.css

app.module.ts

app.routes.ts

auth-guard.service.ts

main.ts

Firebase の認証が Angular 2 の auth-guard.service と連携する方法に注目してください。前述のように、アプリの app/main.tsで Firebase が初期化されます。その際に、onAuthStateChanged関数が呼び出されます。

onAuthStateChanged: (data: any) => { 
console.log(JSON.stringify(data))
if (data.loggedIn) {
BackendService.token = data.user.uid;
}
else {
BackendService.token = "";
}
}

アプリが起動する際に、Firebase から返されるデータを文字列化したものをコンソールで確認してください。そのユーザーに loggedInフラグが立っている場合、Firebase から送り返された userId を tokenとして設定します。NativeScript アプリケーション設定モジュールを使って、この userId を保存するかつ、これから作成するデータと関連付けます。このモジュールは、localStorage のような機能を持つモジュールです。このトークンとトークンを使う認証テストは app/services/backend.service.tsファイルで管理されており、app/auth-guard.service.tsファイルで利用できます。auth-guard ファイルは、アプリのログインおよびログアウト状態を適切に管理する方法を提供しています。

AuthGuard クラスは、Angular Router モジュールの CanActivate インターフェースを実装しています。

export class AuthGuard implements CanActivate {
constructor(private router:Router) { }

canActivate() {
if (BackendService.isLoggedIn()) {
return true;
}
else {
this.router.navigate(["/login"]);
return false;
}
}


基本的には、前述のログイン ルーチンでトークンが設定され、かつ BackendService.isLoggedIn 関数が true を返す場合、アプリでデフォルトのルートであるウィッシュリストへのナビゲーションが許可されます。しかし、それ以外の場合、ユーザーはログイン画面に戻されます。

const listRoutes:Routes = [
{ path: "", component:ListComponent, canActivate: [AuthGuard] },
];

これで、Firebase を使う NativeScript アプリを初期化できました。次は、アプリにデータを読み込み、Firebase のすばらしいリアルタイム性を活用して、アップデートされるデータベースの内容を監視する方法について学んでゆきましょう。

リストの作成とダブルチェック

ウィッシュリストのベースとなっている app/list/list.htmlから説明します。ここには、テキスト項目と空のリストが表示されているはずです。では、サンタさんに欲しいものを伝えてみましょう。項目がデータベースに送信され、リアルタイムにリストに追加されます。これをどうやって実現しているかを見てみましょう。

app/list/list.component.tsでは、最初にギフトのリストを保持するための監視可能オブジェクトを設定しています。 public gifts$: Observable; 次に、コンポーネントの初期化の際に、データベースからリストを読み込みます。

ngOnInit(){
this.gifts$ = this.firebaseService.getMyWishList();
}


おもしろいのは firebaseService ファイルです。この関数では、リスナーを追加して Firebase Database の Gifts コレクションの変更を監視する監視可能オブジェクト rxjs を返しています。この方法に注目してください。

getMyWishList():Observable {
return new Observable((observer: any) => {
let path = 'Gifts';
let onValueEvent = (snapshot: any) => {
this.ngZone.run(() => {
let results = this.handleSnapshot(snapshot.value);
console.log(JSON.stringify(results))
observer.next(results);
});
};
firebase.addValueEventListener(onValueEvent, `/${path}`);
}).share();
}


このクエリの結果は、次に示す handleSnapshot関数で処理されます。この関数は、ユーザーがフィルタリングしたデータを _allItems 配列に設定しています。

handleSnapshot(data: any) {
//empty array, then refill and filter
this._allItems = [];
if (data) {
for (let id in data) {
let result = (Object).assign({id: id}, data[id]);
if(BackendService.token === result.UID){
this._allItems.push(result);
}
}
this.publishUpdates();
}
return this._allItems;
}


最後に、publishUpdates が呼び出されます。この関数は、新しい項目が先頭に表示されるように、日付でデータを並び替えています。

publishUpdates() {
// here, we sort must emit a *new* value (immutability!)
this._allItems.sort(function(a, b){
if(a.date < b.date) return -1;
if(a.date > b.date) return 1;
return 0;
})
this.items.next([...this._allItems]);
}


監視可能オブジェクト $gifts にデータが設定されると、要素の編集や削除を行うたびにリスナーが呼ばれ、フロントエンドが適切にアップデートされます。getMyWishList メソッド内の onValueEvent 関数で ngZoneが使われていることに注意してください。これによって、非同期に行われるデータのアップデートに応じて UI が適切にアップデートされます。NativeScript アプリの ngZone の概要については、こちらをご覧ください。

メッセージのリモート設定


もう 1 つの優れた Firebase サービスに「Remote Config」があります。これは、Firebase のバックエンドからアプリをアップデートできる機能です。Remote Config を使うと、アプリの機能のオン、オフを切り替えたり、UI を変更したりできます。ここでは、サンタさんからメッセージを送る機能を追加してみましょう。

app/list/list.htmlには、次のメッセージ ボックスがあります。 <Label class="gold card" textWrap="true" [text]="message$ | async"></Label> 監視可能オブジェクト message$は、データリストとほぼ同じ方法で組み込まれていますが、ここではアプリが新しく初期化されるたびに変更が適用されます。

ngOnInit(){
this.message$ = this.firebaseService.getMyMessage();
}


秘密は、次に示すサービスレイヤ(app/services/firebase.service.ts)にあります。
getMyMessage():Observable{
return new Observable((observer:any) => {
firebase.getRemoteConfig({
developerMode: false,
cacheExpirationSeconds: 300,
properties: [{
key: "message",
default:"Happy Holidays!"
}]
}).then(
function (result) {
console.log("Fetched at " + result.lastFetch + (result.throttled ? " (throttled)" : ""));
for (let entry in result.properties)
{
observer.next(result.properties[entry]);
}
}
);
}).share();
}



好きなだけ新しいメッセージを発行可能

注: アプリから必要のない高頻度で Remote Config の値を取得すると、Remote Config の利用が制限されてしまう場合がありますので、慎重に開発してください。

写真を撮る



このプロジェクトのおもしろいところは、選んだプレゼントの写真を撮って Firebase Storage に格納できる点でしょう。前述のように、この部分には Camera プラグインを使いました。これでハードウェアの管理が少し楽になります。最初に、app/list-detail/list-detail.component.tsの ngOnInit() メソッドでパーミッション セットを取得し、アプリがカメラデバイスにアクセスできるようにします。

ngOnInit() {
camera.requestPermissions();
...
}

ユーザーが詳細画面の [Photo] ボタンをクリックすると、イベント チェーンが始まります。最初に呼ばれるのは次のコードです。

takePhoto() {
let options = {
width:300,
height:300,
keepAspectRatio: true,
saveToGallery: true
};
camera.takePicture(options)
.then(imageAsset => {
imageSource.fromAsset(imageAsset).then(res => {
this.image = res;
//save the source image to a file, then send that file path to firebase
this.saveToFile(this.image);
})
}).catch(function (err) {
console.log("Error -> " + err.message);
});
}


カメラで写真が撮影され、その写真が imageAsset として保存されて画面に表示されます。このイメージはファイルとしてローカルに保存されます。その際に、日付のタイムスタンプに従った名前が付けられます。また、今後の利用に備えて、パスも保存されます。

saveToFile(res){
let imgsrc = res;
this.imagePath =
this.utilsService.documentsPath(`photo-${Date.now()}.png`);
imgsrc.saveToFile(this.imagePath, enums.ImageFormat.png);
}


[Save] ボタンが押されると、イメージはローカルパス経由で Firebase に送信され、ストレージ モジュール内に保存されます。アプリに返される Firebase のフルパスは、/Giftsデータベース コレクションに保存されます。

editGift(id: string){
if(this.image){
//upload the file, then save all
this.firebaseService.uploadFile(this.imagePath).then((uploadedFile: any) =>
{
this.uploadedImageName = uploadedFile.name;
//get downloadURL and store it as a full path;
this.firebaseService.getDownloadUrl(this.uploadedImageName).then((downloadUrl: string) => {
this.firebaseService.editGift(id,this.description,downloadUrl).then((result:any) => {
alert(result)
}, (error: any) => {
alert(error);
});
})
}, (error: any) => {
alert('File upload error: ' + error);
});
}
else {
//just edit the description
this.firebaseService.editDescription(id,this.description).then((result:any) => {
alert(result)
}, (error: any) => {
alert(error);
});
}
}


このイベント チェーンは一見複雑そうですが、最終的に実行されるのは、Firebase サービス ファイルの中の数行です。

uploadFile(localPath: string, file?: any): Promise {
let filename = this.utils.getFilename(localPath);
let remotePath = `${filename}`;
return firebase.uploadFile({
remoteFullPath: remotePath,
localFullPath: localPath,
onProgress: function(status) {
console.log("Uploaded fraction: " + status.fractionCompleted);
console.log("Percentage complete: " + status.percentageCompleted);
}
});
}
getDownloadUrl(remoteFilePath: string): Promise {
return firebase.getDownloadUrl({
remoteFullPath: remoteFilePath})
.then(
function (url:string) {
return url;
},
function (errorMessage:any) {
console.log(errorMessage);
});
}
editGift(id:string, description: string, imagepath: string){
this.publishUpdates();
return firebase.update("/Gifts/"+id+"",{
description: description,
imagepath: imagepath})
.then(
function (result:any) {
return 'You have successfully edited this gift!';
},
function (errorMessage:any) {
console.log(errorMessage);
});
}


最終的な結果では、ウィッシュリストに表示するギフトの写真と説明の両方がうまく取得できています。これでもうサンタさんは、カイリーのどのアイライナーを買えばいいのかわからないという言い訳はできません。強力な NativeScript と Angular を組み合わせれば、数分で iOS と Android のネイティブ アプリを作ることができます。これに Firebase を追加すれば、アプリのユーザー、イメージ、データを保存する強力な機能を利用でき、さらに端末間でリアルタイムにデータをアップデートすることも可能になります。すばらしいと思いませんか。このアプリは、次のようになります。



ここまで、充実したウィッシュリスト管理アプリの作成に向けて順調に進んできました。しかし、サンタさんに願いごとを伝える最高の方法はまだ模索中と言えるでしょう。次のステップとしては、Mailgun のメールとの統合やプッシュ通知の利用が考えられます。それまでの間、すばらしいクリスマス休暇をお過ごしください。皆さんが Firebase を利用してすてきな NativeScript アプリを作れるようにお祈りします。

NativeScript についてさらに詳しく学びたい方は、http://www.nativescript.orgをご覧ください。質問がある方は、こちらから NativeScript の Slack チャンネルに参加してください。

Posted by Khanh LeViet - Developer Relations Team

2016 年第 4 四半期末の AMP ロードマップ アップデート

$
0
0
[この記事は AMP Project プロジェクト マネージャー、Eric Lindley による Accelerated Mobile Pages Project の記事 "AMP Roadmap Update for End-Q4 2016 – Accelerated Mobile Pages Project" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

2016 年第 4 四半期末の AMP ロードマップ アップデート

2017 年の到来とともに、第 4 四半期に提供を開始した機能や、ここ数か月でスタートして今年も継続するプロジェクトを振り返る時期となりました。以下に概要を記載しますが、さらに詳しい内容をお伝えするため、AMP ロードマップもアップデートしています。

第 4 四半期に提供を開始した機能

この四半期には、<amp-form>によるフォームのサポート、<amp-app-banner>によるアプリのインストール プロモーション、amp-videoamp-youtubeによるミュート状態での自動再生など、AMP フォーマットの機能向上が図られました。加えて、AMP-in-PWA のサポートも強化しました。これには、PWA(Progressive Web App)による AMP ドキュメントの段階的な機能拡張や、PWA 内で AMP を使うためのリファレンス実装が含まれています。

広告でも、複数サイズの広告リクエスト「フライング カーペット」型広告、amp-sticky-ad のユーザー エクスペリエンスの向上が行われました。それとともに、DoubleClick、TripleLift、Adsense などの広告サーバーがサポートされ、A4A(AMP for Ads)による AMP 形式の広告クリエイティブの配信数も増加を続けています。

また、コミュニティからのフィードバックに基づいて、アナリティクスのサポートも拡大しました。amp-carouselamp-formの機能では、トリガーが利用できるようになりました。

継続中の作業

新年を迎えても、第 4 四半期以前から始まった多くのプロジェクトでは、まだ多くの作業が残されています。今後数か月間は、そういった作業に集中的に取り組み続ける予定です。

現在は、要素の動作をユーザー アクションにバインドする仕組みの開発を進めています。これは、AMP ページのインタラクティブ性の向上につながります。また、デベロッパーが簡単に見栄えのよい AMP ページを作れるように、一連のクイックスタート サンプルコード(「AMP スタート」)も提供したいと考えています。

さらに、製品ギャラリータブ型のコンテンツ ナビゲーションのサポート、e コマース アナリティクスの強化など、すばらしい e コマース体験を提供するための作業も続けています。

アナリティクス面の強化を継続するため、amp-analytics での動画プレーヤーに対するユーザー インタラクションのネイティブ サポートや、可変フィルターのサポートなど、さらにきめ細かいアナリティクス機能も構築したいと考えています。

また、近い将来には、広告読み込み時の UX 改善や A4A への継続的な投資によって、サポートする広告ネットワークやコンテキストの数を増加させ、非 AMP ページでも AMP 広告を表示できるようにする予定です。


* * *

作業やフィードバックをいただいた AMP 開発コミュニティの方々に感謝いたします。いつものように、問題や機能リクエストがありましたら遠慮なくお知らせください。


Posted by Yoshifumi Yamaguchi - Developer Relations Team

Google AMP Cache、AMP Lite、そして高速化のニーズ

$
0
0
[この記事は Huibao Lin、Eyal Peled、Google ソフトウェア エンジニアによる Google Developers Blog の記事 "Google AMP Cache, AMP Lite, and the need for speed" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]
Google は、基本方針として高速なサービスの設計を追求しています。Accelerated Mobile Pages(AMP)形式を使うと、コンテンツを確実かつ高速に読み込むことができますが、これだけではありません。

Google 検索や Google ニュースと天気などでは、ほぼ瞬時にユーザーに画面が表示される AMP が使われています。その鍵となる技術のひとつがスマート キャッシュです。一般的に、キャッシュを活用すると、コンテンツとそれをリクエストするユーザーを物理的に近づけることができ、コンテンツのデータがユーザーのもとに届くまでに移動する距離が短くなります。さらに、キャッシュのような単一の共通インフラを使うことで、ページの提供時間の一貫性が高まります。一方、多くのホストから配信されるコンテンツは、キャッシュに比べるとコンテンツを提供するレイテンシが大幅に異なり、かなり長くなります。

Google 検索では、Google AMP Cacheから AMP ページを提供しています。その大きな理由は、一貫した高速のコンテンツ配信にあります。このキャッシュの統合コンテンツ提供インフラは、数億件の規模でドキュメント提供を改善し、最適化を図れるというすばらしい可能性をもたらしています。Google AMP Cache は誰でも無料で使うことができます。その主な理由の 1 つは、すべてのドキュメントがこのようなメリットを受けられるようにするためです。

本投稿では、最近導入された 2 つの改善点、(1)イメージ配信の最適化と(2)「AMP Lite」プロジェクトによる帯域幅が限られた状態でのコンテンツ提供の実現について取り上げます。

Google AMP Cache によるイメージの最適化


ウェブ全体の平均で、イメージはページの全データ量の 64%を占めています。つまり、効果的に最適化するには、イメージを対象にするとよいということになります。

イメージの最適化は、通信に必要なデータ量を削減する効果的な方法です。Google AMP Cache は、PageSpeed モジュールChrome データ圧縮で利用されているイメージ最適化スタックを使っています(この変換を行うために、Google AMP Cache は「Cache-Control: no-transform」ヘッダーを無視している点に注意してください)。サーバーに PageSpeedをインストールすると、サイトは元のイメージに対して同じ最適化を行うことができます。

以下に、私たちが行った最適化の概要を示します。

1)見えない、または見えにくいデータを削除する
サムネイルや位置情報メタデータなど、ユーザーに見えないイメージデータを削除します。画質とカラーサンプルが必要以上に高い JPEG イメージでは、そのレベルを下げます。厳密に言えば、JPEG 画質を 85、カラーサンプルを 4:2:0(4 ピクセルごとに 1 つのカラーサンプル)に減らします。JPEG 圧縮イメージでは、これより画質が高い、またはカラーサンプルが多い場合、データ量は増えますが目視ではほとんど違いがわかりません。

データ量を減らしたイメージデータは大幅に圧縮されます。以上の最適化によって、ユーザーの見た目には影響を与えずに 40% 以上のデータ量を削減できることがわかりました。

2)イメージを WebP 形式に変換する
特定の画像形式では、モバイルと親和性が高まります。WebPがサポートされているブラウザの場合、JPEG を WebP に変換します。この変換によって、画質を変えずにさらに 25% 以上のデータ量を削減できます。

3)srcset を追加する
「srcset」が含まれていない場合は追加します。これは、「src」属性が存在し、「srcset」属性が存在しない「amp-img」タグに適用されます。この操作では、「amp-img」タグを拡張するとともに、イメージを複数のサイズに変更しています。これによって、画面が小さい端末でさらにデータ量が削減されます。

4)状況によって画質の低いイメージを利用する
ユーザーが望む場合や、ネットワークが非常に遅い場合には、(後述の AMP Lite の一環として)JPEG イメージの画質を下げます。たとえば、データセーバーをオンにしている Chrome ユーザーに対して、JPEG イメージの画質を 50 に下げます。この変換によって、さらに JPEG イメージのデータ量を 40% 以上削減できます。

次の例は、最適化前(左)と最適化後(右)のイメージを示しています。元のイメージは 241,260 バイトでしたが、1、2、4 の最適化を行った後は、25,760 バイトになっています。最適化後もイメージはほとんど同じに見えますが、データ量の 89% が削減されています。



低速ネットワーク向けの AMP Lite


世界では、多くのユーザーが低速な接続や RAM の少ない端末でインターネットにアクセスしています。しかし、AMP ページの中には、このように帯域幅が厳しく制限されたユーザー向けに最適化されていないものもありました。そのため、Google は AMP Lite を立ち上げ、このようなユーザーのためにさらに AMP ページのデータ量を削減することにしました。

AMP Lite では、イメージに対して前述のすべての最適化を行います。特に、画質レベルは常に低いものを使用します(上記の 4 つ目の項目を参照)。

さらに、amp-fontタグを使って外部フォントを最適化し、外部フォントがキャッシュ済みかどうかにかかわらずページが即座に表示されるように、フォント読み込みタイムアウトを 0 秒に設定します。

AMP Lite は、ベトナムやマレーシアなど、いくつかの国の帯域幅が限られたユーザーや、全世界の RAM が少ない端末所有者のために提供されています。イメージによっては、これらの最適化によって細部が変わってしまう場合もある点に注意してください。ただし、広告など、ページの他の部分には影響しません。

* * *

上記のすべての最適化を組み合わせると、合計 45% のデータ量を削減できます。
私たちは、今まで以上に高速な AMP を提供するために、ユーザーがさらにデータを効率的に利用できるようにしたいと考えています。


Posted by Yoshifumi Yamaguchi - Developer Relations Team

Google My Business API の分析機能のご紹介

$
0
0
この記事は Aditya Tendulkar、Google マイビジネス プロダクト マネージャーによる Google Geo Developers Blog の記事 "Google Geo Developers Blog: Introducing insights in the Google My Business API" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

Google My Business API の営業拠点・店舗分析機能を紹介します。これは、サードパーティのアプリケーション デベロッパーや大規模な多拠点ブランドが、検索数や閲覧数、ユーザーのアクション数の合計を求めるなどの営業拠点・店舗に関する分析をプログラムから簡単に行う機能です。ビジネス オーナーはこうした情報を追跡し、分析することによって、ユーザーが Google のサービスを使って、どこでどのようにして、営業拠点や店舗を見つけたのかを把握できます。

デベロッパーは Google My Business API を使って、各店舗の場所に関する最大 18 か月分のデータをリクエストし、それを分析して実用的な形で集計や視覚化を行うアプリケーションを構築できます。たとえば、数百の店舗を抱えるコーヒー ショップであれば、ユーザーの閲覧数、店舗へのルート 検索のクリック回数、電話の回数などの傾向を容易に把握し、店舗間で比較することができます。この分析結果は、店舗間のリソース割り当ての改善やマーケティング効果の追跡に活用できます。

この新しい API は、Google マイビジネス ダッシュボードの機能を皆さんのデータ アナリティクス ツールから使えるようにするものです。次の図に示すようにウェブ インターフェースを利用するユーザーは、直近 90 日の Google マイビジネス情報からグラフを生成できます。

このデータは API からも利用できます。最新の ドキュメントをご覧いただければ、この API を簡単に試してみることができます。次に示す簡単な HTML リクエストでは、Google 検索と Google マップで実行された、ビジネスリスティングの検索結果の数を取得します。

次の例では、利用者がある営業拠点・店舗までの運転ルートをリクエストした際の分析結果です。




この新機能によって、Google My Business API ユーザーは、顧客が Google のサービスを使って、どのように営業拠点・店舗を検索しているのか、さらにはその場所を見つけた後にどのようなアクションをとっているのかを理解した上で、ユーザーのアクションを引き起こす最適なビジネスリスティングを得ることができます。このような分析は、Google マイビジネス ウェブやモバイルでも利用できるため、場所を問わずに重要なトレンドを把握することができます。

Google My Business API の詳細や利用申請については、デベロッパー ページをご覧ください。質問やフィードバックがある方は、Google My Business API フォーラムで API チームにご連絡ください。

広告ユニットのアーカイブ

$
0
0
この記事は Tom Ambrose、AdMob パブリッシャー品質チームによる Inside AdMob の記事 "Inside AdMob: Archiving Ad Units" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

本日(*原文公開当時)は、今まで見逃されがちだった AdMob フロントエンド インターフェースの機能についてお話ししましょう。その機能とは、アプリでの広告ユニットのアーカイブです。広告ユニットをアーカイブすると、その広告ユニットに関連づけられているすべての広告の提供や設定が無効になり、広告ユニットにリンクされているアクティブなキャンペーンがある場合、その実行も停止されます。AdMob ユーザー インターフェースの [MONETIZE] タブからその広告ユニットにアクセスすることもできなくなりますが、レポートの履歴は参照できます。この手順は取り消すことができないため、注意してください。一度アーカイブした広告ユニットは、永遠にアーカイブ状態のままになります。

最初、この操作はありえないように思えるかもしれません。収益をもたらしてくれる可能性があるのに、なぜアプリの広告ユニットをアーカイブしてアプリの広告提供を無効化する必要があるのでしょうか。たくさんのアプリを管理している場合、ものごとがいつも単純に進むとは限りません。アプリのソースコードにアクセスできなくなっていたり、アプリの数が多すぎてすべての状況を把握し続けるのが難しい可能性もあるでしょう。このような「以前のアプリ」によって、すべてのアプリをポリシーに準拠させ続けるのが困難になる場合があります。ポリシー違反が修正されないと、AdMob アカウントが一時的に停止される可能性もあります。

以前のアプリのすべての広告をアーカイブすれば、一番簡単にこの問題を回避できます。アプリでユーザーに広告が表示されず、そこから収益が生まれなければ、おそらく AdMob のポリシー違反になることはないでしょう。次の手順に従えば、すべてを AdMob フロントエンドで管理できるため、アプリのソースコードを変更する必要はありません。

AdMob ユーザー インターフェースで、トップバーの [MONETIZE]に移動します。





画面の左側にアプリのリストが表示されます。任意のアプリをクリックすると、アプリの広告ユニットが表示されます。

広告ユニットをアーカイブするには、広告ユニットの横にあるボックスを選択し、[ARCHIVE]をクリックします。





広告をアーカイブすると、ユーザーに広告が表示されなくなり、収益も生まれなくなります。この処理は永続的なものであり、アーカイブを取り消すことはできません。この点は重要なので、覚えておいてください。

次の投稿までの間、TwitterLinkedInGoogle+でお届けする AdMob の情報をご覧ください。


Posted by Rikako Katayama - AdMob Team

Accelerated Mobile Links のご紹介: モバイル ウェブアプリを高速に

$
0
0
この記事は Matthew Prince、Cloudflare CEO による Accelerated Mobile Pages Project の記事 "Introducing Accelerated Mobile Links: Making the Mobile Web App-Quick – Accelerated Mobile Pages Project" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

以下の記事は、Cloudflare の CEO、Matthew Prince が Cloudflare のブログに投稿したものです。

2017 年は、Cloudflare のネットワーク トラフィックの半分以上がモバイル端末からのものになると予測しています。モバイルウェブは、小さな画面に表示できる形式になっているとはいえ、従来のウェブのプロトコルや技術を使って PC の CPU やネットワーク接続、画面向けに構築されたものです。そのため、モバイルウェブのブラウジングは、ネイティブのモバイルアプリに比べると低速に感じられます。

2015 年 10 月、Google のチームが AMP(Accelerated Mobile Pages)を発表しました。これは、モバイルウェブをネイティブ アプリと同じくらい高速にする新しいオープン テクノロジーです。それ以来、多数のサイトオーナーが AMP を採用しています。現在は、700,000 ドメインの 6 億ページが AMP 形式で利用できます。

この AMP コンテンツに対するトラフィックの大半は、Google.com で検索したユーザーによるものです。訪問者が Google 検索以外のソースでコンテンツを見つけた場合、コンテンツを AMP で提供できるはずでも、通常はそうはなりません。そのため、モバイルウェブは求められる速度よりも遅いままになります。

モバイル ウェブアプリを高速に

Cloudflare の Accelerated Mobile Links を使うと、コンテンツを見つけた方法によらずアプリを高速化できるので、この問題の解決につながります。Accelerated Mobile Links を有効にすると、Cloudflare のお客様のサイト上で、AMP 版が利用できるコンテンツへのリンクを自動的に識別します。モバイル端末でリンクをクリックすると、ほぼ瞬時にAMP コンテンツが読み込まれます。





動作を確認するには、モバイル端末でこの投稿を表示し、以下のいずれかのリンクをクリックしてみてください。





ユーザー エンゲージメントの向上

Accelerated Mobile Links のメリットの 1 つは、AMP コンテンツが、コンテンツにリンクしているサイトのビューアーに直接読み込まれることです。そのため、閲覧者が AMP コンテンツを読み終えてビューアーを閉じると、リンク元のソースに戻ることができます。このように、Cloudflare のお客様のサイトはネイティブ モバイルアプリに近くなり、それによってユーザー エンゲージメントも向上します。

ブランドに合わせたユーザー エクスペリエンスを提供したい大規模なサイトオーナーに対しては、サイトオーナーのドメインに一致するようにビューアーのドメインをカスタマイズできる機能を提供する予定です。訪問者を Google のドメインにリダイレクトせずに AMP コンテンツを表示するシームレスな操作が初めて実現しました。Accelerated Mobile Links ビューアーのカスタマイズに興味を持っている大規模なサイトオーナーの皆様は、Cloudflare チームにご連絡ください。

AMP の革新

AMP の初代チャンピオンは Google ですが、AMP 関連技術はオープンです。私たちは、Cloudflare の Accelerated Mobile Links や独自の AMP キャッシュの開発にあたり、Google チームと密接に連携してきました。Google で AMP プロジェクトのテクニカル リードを務める Malte Ubl 氏は、私たちとの協業について次のように話しています。

「AMP キャッシュ ソリューションに関する Cloudflare との協業は、最高にシームレスなオープンソース開発でした。Cloudflare はプロジェクトの恒常的な貢献者になり、AMP のすべてのユーザーのためにコードベースを改善してくれました。ソフトウェア プロジェクトにとって、特定のキャッシュのサポートを多くのキャッシュのサポートへと進化させることは、常に大きな進展です。これを実現した Cloudflare のエレガントなソリューションは実に見事です」

現在、Cloudflare は Google 以外で唯一互換性がある AMP キャッシュを開発しており、Google と同じパフォーマンスやセキュリティを提供しています。

私たちは、サイトオーナーやエンドユーザーの懸念に対処するために、オープンソース精神に則ってプロジェクトの開発を進めています。とりわけ、AMP に関して寄せられている懸念に対処するために、以下の機能の開発を行っています。 

  • サイトオーナーのオリジナル ドメインを使って AMP コンテンツを簡単に共有する仕組み 
  • PC から AMP 版にアクセスした訪問者を自動的にオリジナル版のコンテンツにリダイレクト 
  • AMP 版コンテンツにリダイレクトしたくないエンドユーザーがオプトアウトできる仕組み 
  • サイトオーナーが AMP ビューアーにブランドを表示し、それを自社ドメインから提供する機能 

Cloudflare は AMP プロジェクトに貢献しています。Accelerated Mobile Links は、私たちがリリースする最初の AMP 機能ですが、今後数か月でさらに実績を重ねる予定です。現在のところ、すべての Cloudflare のお客様が無料で Accelerated Mobile Links を利用できます。この機能は、Cloudflare Performance ダッシュボードから有効化できます。モバイルウェブのさらなる高速化を実現する AMP 機能にご期待ください。


Posted by Yoshifumi Yamaguchi - Developer Relations Team

Chrome Tech Talk Night #9 を開催します

$
0
0
2017 年 2 月 9 日(金)、Chrome Tech Talk Night #9 を開催します。今回は Chrome セキュリティチーム の Product Manager である Emily Schechter の来日に合わせ、ウェブをよりセキュアで安心できる環境にする HTTPS への移行について考えるセッションを集めました。


  • Case for HTTPS everywhere - Emily Schechter (@emschec), Google
  • CSP a Powerful Security Steroid - Jxck (@Jxck_), Google Developer Expert
  • なぜ/どうやってクックパッドは HTTPS に移行したのか - 星 北斗 (@kani_b), クックパッド株式会社 インフラストラクチャー部
なお、今回のイベントに通訳は付きません。Emily Schechter の講演は英語であることを予めご了承の上ご参加下さい。

イベント概要

名称:Chrome Tech Talk Night #9
日時:2017 年 2 月 9 日(金) 19:00 - 21:00 (受付 18:30 〜 19:30)
   ※ 終了後、懇親会(軽食付き)を行う予定です。
場所:グーグル株式会社 六本木オフィス
   東京都港区六本木 6-10-1 六本木ヒルズ 森タワー
会費:無料
定員:100 名
主催:グーグル株式会社
ハッシュタグ: #chromejp

申し込み方法

参加を希望される方は以下のフォームよりお申込みをお願いします。
https://goo.gl/forms/tMDQvaYAq6W7hyha2

プログラム

18:30 - 19:00 受付開始
19:00 - 21:00 セッション
21:00 - 22:00 懇親会

内容は変更になる可能性がございます。予めご了承ください。
皆様のご参加をお待ちしております。

Posted by Eiji Kitamura - Developer Relations Team

透過性によるセキュリティ - Key Transparency

$
0
0
この記事は セキュリティおよびプライバシー エンジニアリング、Ryan Hurst、Gary Belvin による Google Security Blog の記事 "Google Online Security Blog: Security Through Transparency" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

暗号化はウェブの基礎をなすテクノロジーです。私たちは多くの時間をかけて、暗号化されたアプリを使いやすくするという複雑な作業を行ってきました。その課程で、メッセージの宛先を正確に指定するために、受信者の公開鍵を見つける安全で汎用的な方法が重要であることに気づきました。この仕組みはさまざまに応用できるだけでなく、これを行う汎用テクノロジーはどこにも存在していません。

確実にインターネット規模まで拡張でき、信頼されていないサーバーを経由して安全な通信を確立する方法を提供するソリューションが必要になります。Certificate Transparencyから得た着想と CONIKSを組み合わせれば、私たちが望む以上の特性を持つシステムを構築できることがわかりました。

その結果として生まれたのが、オープンソース プロトタイプとして本日(*原文公開当時)公開する Key Transparencyです。

Key Transparency が役立つ理由
危殆化された(compromised)サーバーからユーザーを守る既存の手法では、ユーザーが手動で受信者のアカウントを検証する必要がありますが、うまく機能しているとは言えません。PGP での暗号メールの web-of-trust がその例です。これが発明されて 20 年以上たっていますが、発明者本人も含め、ほとんどの人々はこれを使えないまたは使おうとしていませんメッセージング アプリ、ファイル共有、ソフトウェアのアップデートも、同じ課題に悩まされています。

Key Transparency を開発した目的の 1 つは、このプロセスを簡素化し、専門家以外のユーザーでも使えるインフラを作ることでした。オンライン上の個人と公開鍵との関係は、自動的に検証可能かつ広く監査可能であるべきです。ユーザーはアカウントに紐付けられているすべての鍵を参照できるべきですし、同時にレコード改ざんの試みも可視化する必要があります。これにより送信者は、アカウントの所有者による検証済みの鍵を常に使い回せるようになります。

Key Transparency は汎用的で透過性のあるディレクトリです。これを活用すれば、独立してアカウント データを監査できるさまざまなシステムを簡単に構築できるようになります。Key Transparency は、データの暗号化や認証を行う必要があるさまざまなシナリオで利用でき、ユーザーにわかりやすいセキュリティ機能を実現するとともに、アカウント復旧などの重要なユーザーニーズにも対応できます。

将来の方向性
Key Transparency はまだ生まれたばかりです。Key Transparency は最初のオープンソース リリースを迎えましたが、私たちは暗号コミュニティやその他の業界のリーダーとの会話を継続し、フィードバックをお願いし、誰もが高度なセキュリティを使えるようにするための標準の作成に向けて作業を進めています。

複数年にわたる Key Transparency の開発期間中は、CONIKS チーム、Open Whisper Systems、Yahoo! や Google 内部のセキュリティ エンジニアリング チームなどと協力してきました。その皆様に感謝を捧げます。

私たちの目的は、Key Transparency を汎用的で拡張や相互運用が可能なオープンソース公開鍵ディレクトリへと進化させ、相互に監査可能なディレクトリのエコシステムを構築することです。KeyTransparency.orgは、この新しいテクノロジーに関連する皆さんのアプリや提案、貢献をお待ちしています。


Posted by Eiji Kitamura - Developer Relations Team

AMP Cache の存在意義

$
0
0
[この記事は Paul Bakaus、Google AMP デベロッパー アドボケートによる Accelerated Mobile Pages Project の記事 "Why AMP Caches exist – Accelerated Mobile Pages Project" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]


以下の記事は、Google の AMP デベロッパー アドボケート、Paul Bakaus が Medium に投稿したものです。

AMP(Accelerated Mobile Pages)プロジェクトにおいて、キャッシュは必要不可欠な仕組みです。にもかかわらず、大きく誤解されているコンポーネントの 1 つでもあります。キャッシュにリンクするのではなく、AMP サーフェス(たとえば Google)に AMP ページを掲載できないのはなぜかと、毎日のようにデベロッパーから聞かれます。キャッシュ モデルがウェブのオリジン モデルを破壊しているのではないかと心配する方もいれば、アナリティクス属性や canonical リンクの共有について心配する方もいます。また、制御できないサーバー上にページがホストされることについて心配する方もいます。本記事では、これらすべてを取り上げ、キャッシュの存在意義についての理解を深めます。

AMP Cache によって多少のトレードオフは生じるものの、これによって一貫性のある高速で使いやすい仕組みをユーザーに提供できます。キャッシュは、次の目的で設計されています。

  • すべての AMP ページが実際に有効な AMP であることを保証する
  • AMP ページが効率的かつ安全にプリロードできるようにする
  • コンテンツに対して、ユーザーにメリットをもたらすさまざまなパフォーマンスの最適化を追加で実施する

まずは、次の点から見てみましょう。

基本: アナリティクス属性とリンク共有
AMP Cache モデルはオリジン モデル(ページは自身のドメインで提供する)に従ってはいませんが、すべてのトラフィックはサイトオーナーに帰結します。AMP は <amp-analytics>タグを通してさまざまなアナリティクス プロバイダ(現時点で 26あり、さらに増加中)をサポートしており、成功の度合いの計測や、トラフィックが正しく関連づけられていることを確認できます。

ユーザーやデベロッパーがキャッシュされた AMP の結果から canonical ページへの「クリックスルー」を行いたい理由を尋ねてみると、多くの人がリンク共有と答えます。また、当然ながら、canonical URL の代わりに google.com の URL をコピーするのは気が進みません。しかし、これは皆さんが考えるほど大きな問題ではありません。Google はキャッシュされた AMP 検索結果を Schema.org や OpenGraph のメタデータを使って補正するので、それに従うプラットフォームにリンクを投稿すれば、canonical URL が共有されることになります。しかし、共有フローを改善する機会は他にもあります。ネイティブのウェブビューでは、アプリがサポートしていれば canonical を直接共有できます。また、ユーザーからのフィードバックに基づき、Google のチームはすべてのサーフェスで canonical URL に簡単にアクセスできる方法を作成しています。

この点が解決したところで、次はもう少し深く掘り下げてみましょう。

AMP ラベルが表示されていれば、それは AMP である
AMP Project は厳格な検証が必要なエコシステムで構成されており、それによって高パフォーマンスと高品質を保証しています。検証ツールの中には開発中に使えるものもありますが、コンテンツをユーザーに提示する最終段階で妥当性を保証するのは AMP Cache です。

AMP Cache から AMP ページが初めてリクエストされると、まずキャッシュがドキュメントを検証します。そこで問題が検出された場合、ページはユーザーに提供されません。AMP と統合されているプラットフォーム(Bing、Pinterest、Google など)では、トラフィックを直接オリジン上の AMP ページに送るか、AMP Cache に送るかを選択できます。しかし、妥当性が保証されるのは、ページがキャッシュから提供されるときだけです。ユーザーに AMP ラベルが表示されている場合、ほぼ確実に高速でユーザー フレンドリーな操作ができることが保証されています(低速で有効な AMP ページを作ることができた場合は例外です。これは難しいことですが、不可能ではありません。たとえば、巨大なウェブフォントがあると、このようなことが起きるかもしれません)。

想像以上に重要なプリレンダリング
この投稿で一番のポイントになるのは、プリレンダリングです。とりわけ AMP で行われるプリレンダリング的な動作は、オリジン サーバーで直接ホスティングすることで理論的に可能なあらゆる高速化をはるかに上回る効果があります。オリジン サーバーがユーザーの近くにあれば、まれに数ミリ秒ほど高速化できる可能性もあります。しかし、プリレンダリングはほぼ確実に最大の効果を発揮します。

体感速度を大幅に改善
実際、プリレンダリングを使うと、ミリ秒単位ではなく秒単位での高速化が可能です。AMP JS ライブラリによるさまざまなパフォーマンス最適化とは異なり、プリレンダリングの効果はかなり劇的です。この点が「即時的に表示される感覚」に大きく貢献しています。

cache_post


完全なプリレンダリングよりもはるかに効率的
もしそれだけの話であれば、オリジン サーバーから簡単に AMP ページをプリレンダリングできるはずです。しかし、オリジン上では、ページが有効な AMP であることは保証できません。有効な AMP であることは、AMP JS ライブラリが行うカスタム プリレンダリングにとって非常に重要です。リンクのプリフェッチのような単なるページ全体のプリレンダリングとは異なり、AMP のプリレンダリングではユーザーの帯域幅や CPU、電池の利用も制限されます。

有効な AMP ドキュメントは、プリレンダリングの段階で「協調的」に振る舞います。最初に表示されるビューポートのアセットのみがプリロードされ、サードパーティ製のスクリプトは実行されません。これによって、はるかに低コストで、帯域幅や CPU の負荷も低いプリロードを実現しています。さらに、プラットフォームは最初のページだけでなく、ユーザーがクリックしそうないくつかの AMP ページのプリレンダリングもできるようになります。

安全な埋め込み
AMP Cache はブラウザのプリレンダリングに依存していないため(上記のセクションを参照)、通常のナビゲーションでページからページへの移動を行うことはできません。そのため、AMP キャッシュ モデルでは、プラットフォームのページ上でインラインでページをオープンする必要があります。リクエストされた AMP ページで安全にその処理を実行できることが、AMP Cache によって保証されます。


  • 検証ツールによって、メイン ドキュメント内にクロスサイト スクリプティング(XSS)がないことが保証されます。
  • さらに、AMP Cache はドキュメントを解析して明確な方法でシリアライズし直します(つまり、HTML5 のエラー訂正には依存しません)。これによって確実に、バグや差異を解析するブラウザで XSS を防ぐことができます。
  • キャッシュは、コンテンツ セキュリティ ポリシー(CSP)を適用します。これによって、XSS 攻撃に対する多層防御が提供されます。


プライバシーの強化
さらに、AMP Cache はプリレンダリングの際に重要な問題となり得るものを取り除きます。AMP ページをプリロードしているコンテンツ プラットフォームの結果ページで検索を行った場合、プリロードされた AMP ページは自分がプリロードされていることがわかりません。

次のように考えてみましょう。たとえば、「breakfast burrito」で検索を行うとします。私のことをよく知っている方なら、同じタイトルの Parry Gripp の曲を検索していることは自明でしょう。しかし、検索結果ページには、実際に朝食のブリトーを売っているファストフード チェーンの AMP 検索結果も表示されます。翌月には、リンクをクリックしていないのに(ひょっとするとクリックするかもしれませんが…)あちこちに表示される実際の朝食のブリトーは見たくないと思うようになるでしょう。広告主も、ブリトーに関する意味のないマーケティングを繰り返して無駄なお金を使いたいとは思いません。AMP のプリロードは AMP ページのサイトオーナーや関連するサードパーティには隠蔽されるため、これはユーザーと広告主の双方にとってメリットになります。

劇的な高速化につながる自動最適化
AMP Cache はまず以上のようなことを行いますが、その後もたくさんの変換を行っています。具体的には、次のような最適化が挙げられます。

  • (大規模サイトオーナーだけでなく)すべてのコンテンツに対して、一貫性のある高速なコンテンツ配信ネットワークを無償で提供
  • スクリプトの理想的な順番への並び替え、重複するスクリプトタグの削除、不要な引用符や空白文字の削除などによる HTML の最適化
  • キャッシュ時間を無限にするための JavaScript URL の書き換え
  • イメージの最適化(帯域幅を平均 40% 削減)


イメージ圧縮という側面だけでも、Google はキャッシュを通してロスレス圧縮(EXIF データの削除など、視覚的変化のない圧縮)やロス圧縮(視覚的変化がある圧縮)を行っています。さらに、対応ブラウザに対してはイメージを WebP に変換し、srcset 属性(いわゆるレスポンシブ イメージ)がない場合は自動生成して、各端末で正しいサイズのイメージを生成、表示します。

さらなる改善に向けて
皆さんの言いたいことはわかります。AMP Cache プロバイダは、コンテンツのミラーリングを行っています。これは重要な役割で、大きな責任が伴います。キャッシュ プロバイダがすべての AMP ページに不快な広告を挿入するといったとんでもないことをしでかせば、AMP はサイトオーナーにとって有用なソリューションではなくなり、衰退してゆくことになるでしょう。

AMP は、サイトオーナーやユーザー、プラットフォームにとってモバイルウェブをよりよいものにするために、皆さんとともに作り上げたものです。AMP チームが AMP Cache の厳格なガイドラインをリリースしたのはそのためです。興味深い点を 2 つ抜粋しましょう。ガイドラインでは、コンテンツは「ソース ドキュメントを視覚的、UX 的に忠実に再現」できる必要があり、キャッシュ プロバイダはたとえキャッシュ自身が使われなくなったとしても、 URL はいつまでも使えるようにしなければならないことが明示されています。これらを始めとするさまざまなルールによって、キャッシュが皆さんのコンテンツを壊さないことが保証されています。

何よりも重要なのは、AMP Cache は 1 つだけではなく、そこには大きな余地があることです。先日、実際に Cloudflare が独自のキャッシュを発表しています。AMP Cache ガイドラインがリリースされたので、そのルールに従う限り、他のインフラ会社も新しい AMP Cache を作ることができます。どのキャッシュを選ぶかは、AMP を統合したプラットフォーム次第になります。

キャッシュからウェブ標準へ
以上で、AMP Cache がユーザー フレンドリーなモバイルウェブを即時的に提供するメリットやトレードオフについて理解していただけたと思います。しかし、同じようなさまざまな劇的な最適化をトレードオフなしに、あるいはキャッシュを使わずに行えたらどうでしょう。

個人的には、将来そういったことを実現し、キャッシュ モデルの先を行く(たとえば、アセットが読み込まれる前にページがどのように見えるかがわかる静的レイアウト システムなど)まだ発明されていないウェブ標準ができることを夢見ています。

2016 年、私たちは CPPでその最初の 1 歩を踏み出しました。現在、CPP は Feature Policyとなっています。これは、「このサイトでは document.write や iframe でのサードパーティ ページの読み込みは許可しない」といったことを指定する方法を提供します。静的レイアウトや安全なプリレンダリングのような高度な概念には、さらなるウェブ プラットフォームの変化が必要です。しかし、未来へのタイムトラベルのように、不可能なことではありません。ただ非常に難しいだけです。

TwitterSlackで連絡と取りながら、一緒にこれを探求してみませんか。また、私はいつも皆さんの質問やアイデア、懸念に耳を傾けていることもお忘れなく。前進あるのみ!



Posted by Yoshifumi Yamaguchi - Developer Relations Team

沈黙は言葉よりも雄弁に不正ソフトウェアを発見する

$
0
0
この記事は Megan Ruthven、ソフトウェア エンジニアによる Android Developers Blog の記事 "Silence speaks louder than words when finding malware | Android Developers Blog" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

Android セキュリティ チームでは、端末をさらに安全かつスムーズに操作できるようにする方法を模索しています。Google Play を利用する全端末を対象としたセキュリティ ソリューションの 1 つがアプリの確認です。アプリの確認では、端末上に有害な可能性があるアプリ(Potentially Harmful App、PHA)がないかどうかを確認します。PHA が見つかった場合、アプリの確認で警告を表示し、ユーザーがそのアプリをアンインストールできるようにします。

しかし、アプリの確認が行われない端末もあります。新しいスマートフォンを買った場合などセキュリティとは関係ない理由でそうなることもあれば、心配すべきことが起きていることもあります。アプリの確認が行われない場合、その端末は利用不能または安全ではない(Dead or Insecure、DOI)と見なされます。あるアプリをダウンロードした端末が高確率で DOI 端末となった場合、そのアプリは DOI アプリと見なされます。私たちは Android ユーザーを保護するため、アプリが PHA かどうかを DOI 指標などのセキュリティ システムから判断しています。また脆弱性を発見した際には、セキュリティ アップデート システムを使って Android 端末にパッチを適用しています。

本ブログ投稿では、セキュリティに起因して端末が動作しなくなる原因を特定し、今後それが起こらないようにするための Android セキュリティ チームの研究について紹介します。
DOI アプリの判別

この問題をさらに深く理解してユーザーを保護するため、Android セキュリティ チームはアプリのインストール試行回数と DOI 端末との関連を調査し、端末に危害を与えるアプリを探しています。
そのような要素を念頭に置き、「継続利用率」に着目しました。アプリのダウンロード後もアプリの確認によるセキュリティ チェックが定期的に行われていれば、その端末は利用継続中と見なされます。そうでない場合、DOI の可能性があると見なされます。特定の日にアプリをダウンロードし、継続利用中のすべての端末の割合がアプリの継続利用率となります。継続利用は端末の健全性を示す強力なインジケーターなので、私たちはエコシステムの継続利用率が最大化されるよう努めています。

そこで、端末の継続利用率はすべてのアプリで同じになるはずという前提のもと、アプリの DOI スコアラーを利用します。あるアプリの継続利用率が平均よりも低い標準偏差を示す場合、DOI スコアラーはそのアプリにフラグを立てます。平均から標準偏差の数値を計算する一般的な方法に、Z スコアがあります。Z スコアの方程式を次に示します。

  • N = アプリをダウンロードした端末数
  • x = アプリをダウンロードした継続利用中の端末数
  • p = 何らかのアプリをダウンロードした端末の継続利用率

ここで、アプリの継続利用率の Z スコアを DOI スコアと呼びます。Z スコアが -3.7 より低い場合、DOI スコアはそのアプリが統計的に著しく低い継続利用率であるという指標になります。つまり、帰無仮説を真とする場合、Z スコアの大きさがそこまで大きくなる確率は 0.01% 以下しかありません。この場合の帰無仮説とは、アプリが低い継続利用率を示すのは、アプリの動作とは関係なく偶然であるということです。
これによって、極端な値(継続利用率が低くダウンロード数が多い)を示すアプリが DOI リストのトップに現れることになります。そこから DOI スコアと他の情報を組み合わせて、アプリを PHA に分類するかどうかを判断します。次に、アプリの確認を使用してインストール済みのアプリを削除し、今後はそのアプリがインストールされないようにします。

同じ端末にダウンロードされた通常のアプリと DOI アプリの違い


実際の結果
DOI スコアを使うと、3 つの有名な不正ソフトウェアである HummingbadGhost PushGooliganを含むアプリを他の手段に比べて多く判別できました。各マルウェアの動作は異なるにもかかわらず、DOI スコアラーはこの 3 つの不正ソフトウェアに関連する 25,000 以上のアプリを判別しています。これらのマルウェアが Android の機能を損ない、無視できない数のユーザーがファクトリー リセットを行ったり、端末の利用をやめたりしているためです。このアプローチは、PHA を検出し、それが広まる前にブロックするもう 1 つの有望な手段となっています。DOI スコアラーがなければ、これらのアプリの大半が人手によるレビューをすり抜けていたはずです。
DOI スコアラーを含む Android の不正ソフトウェア対策機能は、Android のユーザーやデベロッパーを保護するための何層にもわたる取り組みの 1 つです。Android のセキュリティや透過性に関する取り組みの概要については、こちらのページをご覧ください。



Posted by Yuichi Araki - Developer Relations Team

Google Play Developer Console から注文と課金設定を管理する

$
0
0
この記事は Suzanne van Tienen、Google Play プロダクト マネージャーによる Android Developers Blog の記事 "Manage paid orders and payments settings from the Google Play Developer Console" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

現在私たちはコミュニティからのフィードバックに基づき、有料アプリやアプリ内購入、定期購入が可能なアプリを開発したデベロッパーの販売関連の操作を改善し、シンプルにしようとしています。

まず、注文管理を Google Payments Center から Google Play Developer Console に移動し、いくつかの機能を改善しています。課金設定は、引き続き payments.google.com からも利用できますが、Developer Console からもアクセスできるようになります。新機能には適切なアクセス制御を設定できるため、必要なツールへのアクセス権のみをユーザーに与えることができます。



Google Play Developer Console の新しい注文管理タブ

今まで Google Payments Center で行っていたタスクは、Developer Console から実行できます。さらに、いくつかの改善も行っています。
  • 一括返金: 複数の注文を選択して同時に返金できるようになり、個々に返金する必要はなくなります。
  • 定期購入のキャンセル: 注文管理タブから、直接(別の UI を開かずに)返金と定期購入の取り消しを行うことができます。
  • パーミッション: Developer Console に「注文の管理」という新しいユーザー アクセス パーミッションを追加しました。このパーミッションを持つユーザーは、注文の検索、返金、定期購入のキャンセルが可能です。その他の機能は読み取り専用となり、売上レポートは表示されません(売上データは、「売上レポートの表示」パーミッションを持つユーザーのみ参照できます)。Developer Console からアクセスする場合、課金設定にアクセスできるのはアカウント所有者のみです。

注文管理の Developer Console への移行

Developer Console から注文管理にアクセスできるようになり、1 月 23 日以降、Payments Center からは注文管理にアクセスできなくなりました。Developer Console アカウントに新しいユーザーを追加する方法を次に示します。
  1. Google Payments Centerにログインし、すべての既存ユーザーを確認します。
  2. Developer Console にログインし、Developer Console の注文管理にアクセスする必要があるすべてのユーザーに以下のいずれかまたは両方のパーミッションを追加します。
    1. 売上レポートの表示: 売上レポートへのアクセスと参照に必要なアクセス権を与えます。
    2. 注文の管理: 注文の参照や返金に必要なアクセス権を与えますが、売上の集計や統計の表示、販売および支払レポートのダウンロードはできません。
  3. 注文管理を行う新しい場所をユーザーに知らせます。


Posted by Takeshi Hagikura - Developer Relations Team
Viewing all 2206 articles
Browse latest View live